From ccd7db4d6888b4abff9a9e8c526f0c819ad8c01d Mon Sep 17 00:00:00 2001 From: Jon Marius Venstad Date: Tue, 30 Apr 2019 14:00:57 +0200 Subject: Change signatures to use SHA256ECDSA Signature implementation --- .../java/ai/vespa/hosted/api/SignaturesTest.java | 131 +++++---------------- 1 file changed, 30 insertions(+), 101 deletions(-) (limited to 'hosted-api/src/test') diff --git a/hosted-api/src/test/java/ai/vespa/hosted/api/SignaturesTest.java b/hosted-api/src/test/java/ai/vespa/hosted/api/SignaturesTest.java index 074f117167b..212b2bdebac 100644 --- a/hosted-api/src/test/java/ai/vespa/hosted/api/SignaturesTest.java +++ b/hosted-api/src/test/java/ai/vespa/hosted/api/SignaturesTest.java @@ -1,20 +1,19 @@ package ai.vespa.hosted.api; -import com.yahoo.security.KeyUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.BeforeClass; import org.junit.Test; import java.io.ByteArrayInputStream; import java.net.URI; import java.net.http.HttpRequest; import java.security.DigestInputStream; -import java.security.Key; import java.security.MessageDigest; +import java.security.Security; import java.time.Clock; import java.time.Instant; import java.time.ZoneOffset; -import static ai.vespa.hosted.api.Signatures.decrypted; -import static ai.vespa.hosted.api.Signatures.encrypted; import static ai.vespa.hosted.api.Signatures.sha256Digest; import static ai.vespa.hosted.api.Signatures.sha256Digester; import static java.nio.charset.StandardCharsets.UTF_8; @@ -23,99 +22,34 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** - * Tests that encryption and decryption are inverses, and that the keys used for this can be loaded. + * Tests that messages can be signed and verified, and that the keys used for this can be parsed. * * To generate appropriate keys, run the following commands: *
    - *
  1. {@code openssl genrsa -out mykey.pem 4096}
  2. - *
  3. {@code openssl pkcs8 -topk8 -in mykey.pem -outform PEM -out private_key.pem -nocrypt}
  4. - *
  5. {@code openssl rsa -pubout -in mykey.pem -outform PEM -out public_key.pem}
  6. + *
  7. {@code openssl ecparam -name prime256v1 -genkey -noout -out private_key.pem}
  8. + *
  9. {@code openssl ec -pubout -in private_key.pem -out public_key.pem}
  10. *
- * Step 1 generates a private key, Step 2 converts this to Java-acceptable PKCS8 format, - * and Step 3 extracts and writes the public key to a separate file. - * The key generated in Step 1 should be thrown away when the other steps are complete. + * Step 1 generates a private key and Step 2 extracts and writes the public key to a separate file. * * @author jonmv */ public class SignaturesTest { - public static final String pemPrivateKey = "-----BEGIN PRIVATE KEY-----\n" + - "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\n" + - "ndl6Zvqa954h5bVtyL/qs7HvK5b7xQ==\n" + - "-----END PRIVATE KEY-----\n"; - - public static final String pemPublicKey = "-----BEGIN PUBLIC KEY-----\n" + - "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsKL8jvIEy2peLtEvyhWW\n" + - "b/O/9RHTfPXjeXahXmVrXE4zY5CJ6Mf1PFkwQ8K8S35YhSbOZM4aYhF9V8F4jwyW\n" + - "nX6qWUMrWVHOuS32fkjdNo0z/KxCbG5nRIWLuv/PkHNuIJqMCbwn6Qud5a+wxeLg\n" + - "LqlroCtUJKAGj4YlZ5i8oMdCqfHKl/DMwcks5XxtIArz6GcM2z8fOB3NRexj32MU\n" + - "LH7ybWhCDx/RSqGQYJ8sWEFIK4HSmYqwqIQpFAm/ixISkeWBL6ikgqchZNMf7xyn\n" + - "yJxjCHgtkxANsQhHj2kgAzLDeBsuM+/WRhBGa+LRvEcuu/zZv9+7eVhpaYJveLVd\n" + - "cwPewW/8liBmKIzj/QPCn7ZlVRk094TZD6TCER4+JFW9mo0vFD8S9o0zhMlckzCF\n" + - "4ZNNgyP9tI8Wecq25A+sUY5/WZNLi+mka/GnfPt97GrhM0YHb1M6t4nh1R437Nwh\n" + - "rUHR/YDazbBvLk5T71GgfQfn44L9SwsqEYaHvdZAfV0IZJBtDo/yCe/yvgtHTymB\n" + - "eBrRMpBU5recPtW8bgEWlHl6Qyduw9EBJjNYxvBpgV/D/tNBcau0aGxmhwpBevet\n" + - "ekV6XA2miC7rWu2Wrq2l5LjXEgZOD5PNN2vQS2Cdet9JHYWbVbK3mBLgoChcC5Xo\n" + - "/QHLU4RydI0i0+Z2/tjGsGsCAwEAAQ==\n" + - "-----END PUBLIC KEY-----\n"; - - private static final String otherPemPublicKey = "-----BEGIN PUBLIC KEY-----\n" + - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1ouH9SLS6J2a5WkzAD86\n" + - "TJNosNhacGJloUQyxfTsOLJXdKJkK5/kD101bTwdYRqMx9vR2l8zSXdpUjsn45qD\n" + - "2Nu0fvO4npIfeTfZDhXFsX7/aSW+/AJbGE/Zz3Oi7fGrndlgkCe3J3iqMtPMvQ0T\n" + - "JbKWmh+EonNR3nkdapxlI8+gEqAODQTZuGT5/juZztMr1hsx83KpWaYnkj/t8b9M\n" + - "wWhThcmk5zjuoQCT4mF8pFe+r8V9V59g4Y+G/u1xs1+vDH2sBULOem2OPGBnnslE\n" + - "hOZEOK1l6HX61MF/9d26LkYWoWpzBkaCwl1Lw4GslXFr1F4+8RoGT1xmkZQmb+f/\n" + - "XwIDAQAB\n" + - "-----END PUBLIC KEY-----\n"; + private static final String emPemPublicKey = "-----BEGIN PUBLIC KEY-----\n" + + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuKVFA8dXk43kVfYKzkUqhEY2rDT9\n" + + "z/4jKSTHwbYR8wdsOSrJGVEUPbS2nguIJ64OJH7gFnxM6sxUVj+Nm2HlXw==\n" + + "-----END PUBLIC KEY-----\n"; + + private static final String ecPemPrivateKey = "-----BEGIN EC PRIVATE KEY-----\n" + + "MHcCAQEEIJUmbIX8YFLHtpRgkwqDDE3igU9RG6JD9cYHWAZii9j7oAoGCCqGSM49\n" + + "AwEHoUQDQgAEuKVFA8dXk43kVfYKzkUqhEY2rDT9z/4jKSTHwbYR8wdsOSrJGVEU\n" + + "PbS2nguIJ64OJH7gFnxM6sxUVj+Nm2HlXw==\n" + + "-----END EC PRIVATE KEY-----\n"; + + private static final String otherEcPemPublicKey = "-----BEGIN PUBLIC KEY-----\n" + + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFELzPyinTfQ/sZnTmRp5E4Ve/sbE\n" + + "pDhJeqczkyFcT2PysJ5sZwm7rKPEeXDOhzTPCyRvbUqc2SGdWbKUGGa/Yw==\n" + + "-----END PUBLIC KEY-----\n"; private static final byte[] message = ("Hello,\n" + "\n" + @@ -124,13 +58,9 @@ public class SignaturesTest { "Yours truly,\n" + "∠( ᐛ 」∠)_").getBytes(UTF_8); - @Test - public void testEncryption() { - Key privateKey = KeyUtils.fromPemEncodedPrivateKey(pemPrivateKey); - Key publicKey = KeyUtils.fromPemEncodedPublicKey(pemPublicKey); - - assertArrayEquals(message, decrypted(encrypted(message, privateKey), publicKey)); - assertArrayEquals(message, decrypted(encrypted(message, publicKey), privateKey)); + @BeforeClass + public static void register() { + Security.addProvider(new BouncyCastleProvider()); } @Test @@ -148,15 +78,14 @@ public class SignaturesTest { @Test public void testSigning() { Clock clock = Clock.fixed(Instant.EPOCH, ZoneOffset.UTC); - RequestSigner signer = new RequestSigner(pemPrivateKey, "myKey", clock); + RequestSigner signer = new RequestSigner(ecPemPrivateKey, "myKey", clock); URI requestUri = URI.create("https://host:123/path//./../more%2fpath/?yes=no"); - HttpRequest.Builder builder = HttpRequest.newBuilder(requestUri); HttpRequest request = signer.signed(builder, Method.GET); // GET request with correct signature and URI as-is. - RequestVerifier verifier = new RequestVerifier(pemPublicKey, clock); + RequestVerifier verifier = new RequestVerifier(emPemPublicKey, clock); assertTrue(verifier.verify(Method.valueOf(request.method()), request.uri(), request.headers().firstValue("X-Timestamp").get(), @@ -209,7 +138,7 @@ public class SignaturesTest { "Wrong/signature")); // Key pair mismatch. - verifier = new RequestVerifier(otherPemPublicKey, clock); + verifier = new RequestVerifier(otherEcPemPublicKey, clock); assertFalse(verifier.verify(Method.valueOf(request.method()), request.uri().normalize(), request.headers().firstValue("X-Timestamp").get(), @@ -217,7 +146,7 @@ public class SignaturesTest { request.headers().firstValue("X-Authorization").get())); // Too old request. - verifier = new RequestVerifier(pemPublicKey, Clock.fixed(Instant.EPOCH.plusSeconds(301), ZoneOffset.UTC)); + verifier = new RequestVerifier(emPemPublicKey, Clock.fixed(Instant.EPOCH.plusSeconds(301), ZoneOffset.UTC)); assertFalse(verifier.verify(Method.valueOf(request.method()), request.uri().normalize(), request.headers().firstValue("X-Timestamp").get(), @@ -225,7 +154,7 @@ public class SignaturesTest { request.headers().firstValue("X-Authorization").get())); // Too new request. - verifier = new RequestVerifier(pemPublicKey, Clock.fixed(Instant.EPOCH.minusSeconds(301), ZoneOffset.UTC)); + verifier = new RequestVerifier(emPemPublicKey, Clock.fixed(Instant.EPOCH.minusSeconds(301), ZoneOffset.UTC)); assertFalse(verifier.verify(Method.valueOf(request.method()), request.uri().normalize(), request.headers().firstValue("X-Timestamp").get(), -- cgit v1.2.3