From 5abfef50fcfc033f5f5016c0ccd343b5da9f4253 Mon Sep 17 00:00:00 2001 From: Jon Chambers Date: Mon, 21 Oct 2024 13:09:54 -0400 Subject: [PATCH] Avoid repeated constants, standardize test assertions, and add links to docs for `PolicySigner` --- .../textsecuregcm/s3/PolicySigner.java | 41 ++++++++++++------- .../textsecuregcm/s3/PolicySignerTest.java | 11 ++--- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/s3/PolicySigner.java b/service/src/main/java/org/whispersystems/textsecuregcm/s3/PolicySigner.java index 1a3acd17e..3cfa6a00f 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/s3/PolicySigner.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/s3/PolicySigner.java @@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.s3; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; +import java.security.Key; import java.security.NoSuchAlgorithmException; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -19,33 +20,45 @@ public class PolicySigner { private final String awsAccessSecret; private final String region; - public PolicySigner(String awsAccessSecret, String region) { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd"); + + public PolicySigner(final String awsAccessSecret, final String region) { this.awsAccessSecret = awsAccessSecret; - this.region = region; + this.region = region; } - public String getSignature(ZonedDateTime now, String policy) { + // See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html + public String getSignature(final ZonedDateTime now, final String policy) { + final Mac mac; + try { - Mac mac = Mac.getInstance("HmacSHA256"); + mac = Mac.getInstance("HmacSHA256"); + } catch (final NoSuchAlgorithmException e) { + throw new AssertionError("Every implementation of the Java platform is required to support HmacSHA256", e); + } - mac.init(new SecretKeySpec(("AWS4" + awsAccessSecret).getBytes(StandardCharsets.UTF_8), "HmacSHA256")); - byte[] dateKey = mac.doFinal(now.format(DateTimeFormatter.ofPattern("yyyyMMdd")).getBytes(StandardCharsets.UTF_8)); + try { + mac.init(toHmacKey(("AWS4" + awsAccessSecret).getBytes(StandardCharsets.UTF_8))); + final byte[] dateKey = mac.doFinal(now.format(DATE_FORMAT).getBytes(StandardCharsets.UTF_8)); - mac.init(new SecretKeySpec(dateKey, "HmacSHA256")); - byte[] dateRegionKey = mac.doFinal(region.getBytes(StandardCharsets.UTF_8)); + mac.init(toHmacKey(dateKey)); + final byte[] dateRegionKey = mac.doFinal(region.getBytes(StandardCharsets.UTF_8)); - mac.init(new SecretKeySpec(dateRegionKey, "HmacSHA256")); - byte[] dateRegionServiceKey = mac.doFinal("s3".getBytes(StandardCharsets.UTF_8)); + mac.init(toHmacKey(dateRegionKey)); + final byte[] dateRegionServiceKey = mac.doFinal("s3".getBytes(StandardCharsets.UTF_8)); - mac.init(new SecretKeySpec(dateRegionServiceKey, "HmacSHA256")); - byte[] signingKey = mac.doFinal("aws4_request".getBytes(StandardCharsets.UTF_8)); + mac.init(toHmacKey(dateRegionServiceKey)); + final byte[] signingKey = mac.doFinal("aws4_request".getBytes(StandardCharsets.UTF_8)); - mac.init(new SecretKeySpec(signingKey, "HmacSHA256")); + mac.init(toHmacKey(signingKey)); return HexFormat.of().formatHex(mac.doFinal(policy.getBytes(StandardCharsets.UTF_8))); - } catch (NoSuchAlgorithmException | InvalidKeyException e) { + } catch (final InvalidKeyException e) { throw new AssertionError(e); } } + private static Key toHmacKey(final byte[] bytes) { + return new SecretKeySpec(bytes, "HmacSHA256"); + } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/s3/PolicySignerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/s3/PolicySignerTest.java index 52df80c4c..efe76725b 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/s3/PolicySignerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/s3/PolicySignerTest.java @@ -16,11 +16,12 @@ class PolicySignerTest { @Test void testSignature() { - Instant time = Instant.parse("2015-12-29T00:00:00Z"); - ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(time, ZoneOffset.UTC); - String encodedPolicy = "eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9"; - PolicySigner policySigner = new PolicySigner("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "us-east-1"); + final Instant time = Instant.parse("2015-12-29T00:00:00Z"); + final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(time, ZoneOffset.UTC); + final String encodedPolicy = "eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9"; + final PolicySigner policySigner = new PolicySigner("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "us-east-1"); - assertEquals(policySigner.getSignature(zonedDateTime, encodedPolicy), "8afdbf4008c03f22c2cd3cdb72e4afbb1f6a588f3255ac628749a66d7f09699e"); + assertEquals("8afdbf4008c03f22c2cd3cdb72e4afbb1f6a588f3255ac628749a66d7f09699e", + policySigner.getSignature(zonedDateTime, encodedPolicy)); } }