Skip to content

Commit

Permalink
test for invalid signature using EC521
Browse files Browse the repository at this point in the history
  • Loading branch information
spwitt committed Feb 27, 2024
1 parent 206a71a commit 8db30c7
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 17 deletions.
29 changes: 28 additions & 1 deletion src/test/java/io/fusionauth/jwt/JWTTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ public void test_openssl_keys_p_256() {
assertEquals(actual.subject, jwt.subject);
}

@Test
@Test(invocationCount = 1000)
public void test_openssl_keys_p_521() {
JWT jwt = new JWT()
.setSubject("1234567890")
Expand Down Expand Up @@ -996,6 +996,33 @@ public void test_openssl_keys_p_521() {
assertEquals(actual.subject, jwt.subject);
}

@Test(invocationCount = 1000)
public void test_openssl_keys_p_521_failed_validation() {
JWT jwt = new JWT()
.setSubject("1234567890")
.addClaim("name", "John Doe 208")
.addClaim("admin", true)
.addClaim("iat", 1516239022);

// PKCS#8 PEM, needs no encapsulation
Signer signer = ECSigner.newSHA512Signer("-----BEGIN PRIVATE KEY-----\n" +
"MF8CAQAwEAYHKoZIzj0CAQYFK4EEACMESDBGAgEBBEHNkRW+AZ87Hobcc0BIW1YV\n" +
"Ia5uQ0QVj8kkAN7sgTzKmawnf82FqFnHzqyhshHfwx9eIv723E3/XrA+3nw+8/l9\n" +
"ew==\n" +
"-----END PRIVATE KEY-----");
String encodedJWT = JWT.getEncoder().encode(jwt, signer, header
-> header.set("kid", "S-CdQFQmkHB1rFfzQS4kxhzKk8xtZPAECItUvB0plIM"));

Verifier verifier = ECVerifier.newVerifier("-----BEGIN PUBLIC KEY-----\n" +
"MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBa5VzP87t5eGBqoZFLs9xQiodlD7E\n" +
"0xCzD7SrjshhOfOYei9kb7Yt5bvXShTfji16r1tgpaVzc5ffG693O4RVsUsBV7nl\n" +
"mCRG7g5x9FD2VIiSwnrDHyVf0bYNMeBM4vrt245VNT0E1xkJWhUB2JIl4dGvv0qE\n" +
"dYamwqrHFpoN7QW530Y=\n" +
"-----END PUBLIC KEY-----");
JWT actual = JWT.getDecoder().decode(encodedJWT, verifier);
assertEquals(actual.subject, jwt.subject);
}

@Test
public void test_zonedDateTime() {
ZonedDateTime expiration = ZonedDateTime.now(ZoneOffset.UTC).plusMinutes(60).truncatedTo(ChronoUnit.SECONDS);
Expand Down
67 changes: 54 additions & 13 deletions src/test/java/io/fusionauth/jwt/ec/ECSignerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@

package io.fusionauth.jwt.ec;

import io.fusionauth.jwks.JSONWebKeyBuilder;
import io.fusionauth.jwt.BaseJWTTest;
import io.fusionauth.jwt.InvalidJWTSignatureException;
import io.fusionauth.jwt.InvalidKeyTypeException;
import io.fusionauth.jwt.JWTUtils;
import io.fusionauth.jwt.Signer;
import io.fusionauth.jwt.Verifier;
import io.fusionauth.jwt.domain.JWT;
import io.fusionauth.pem.PEMEncoder;
import io.fusionauth.pem.domain.PEM;
import io.fusionauth.security.BCFIPSCryptoProvider;
import org.testng.annotations.Test;
Expand All @@ -27,6 +34,7 @@
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
Expand Down Expand Up @@ -59,28 +67,61 @@ public void test_invalidKey() {
}
}

@Test
@Test(invocationCount = 1000)
public void round_trip_raw1() throws Exception {
// Generate a key-pair and sign and verify a message
KeyPairGenerator g = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec parameterSpec = new ECGenParameterSpec("secp256r1");
ECGenParameterSpec parameterSpec = new ECGenParameterSpec("secp384r1");
g.initialize(parameterSpec);
KeyPair pair = g.generateKeyPair();
System.out.println(new PEMEncoder().encode(pair.getPublic()));
System.out.println(new PEMEncoder().encode(pair.getPrivate()));
System.out.println(JWTUtils.generateJWS_kid_S256(new JSONWebKeyBuilder().build(pair.getPublic())));

// Instance of signature class with SHA256withECDSA algorithm
Signature signature = Signature.getInstance("SHA256withECDSA");
Signature signature = Signature.getInstance("SHA384withECDSA");
signature.initSign(pair.getPrivate());
Signer signer = ECSigner.newSHA384Signer(pair.getPrivate());
Verifier verifier = ECVerifier.newVerifier(pair.getPublic());

for (int i = 0; i < 250; i++) {
JWT jwt = new JWT()
.setSubject("1234567890")
.addClaim("name", "John Doe " + i)
.addClaim("admin", true)
.addClaim("iat", 1516239022);

String encodedJWT = JWT.getEncoder().encode(jwt, signer, header
-> header.set("kid", JWTUtils.generateJWS_kid_S256(new JSONWebKeyBuilder().build(pair.getPublic()))));

JWT actual = JWT.getDecoder().decode(encodedJWT, verifier);
assertEquals(actual.subject, jwt.subject);
assertEquals(actual.getString("name"), jwt.getString("name"));
// try {
// System.out.println("Good " + encodedJWT);
// } catch (InvalidJWTSignatureException e) {
// System.out.println("Bad " + encodedJWT);
// }
}

// Sign a message
String message = "text ecdsa with sha256";
signature.update((message).getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = signature.sign();

// Validation
Signature verifier = Signature.getInstance("SHA256withECDSA");
verifier.initVerify(pair.getPublic());
verifier.update(message.getBytes(StandardCharsets.UTF_8));
assertTrue(verifier.verify(signatureBytes));
// for (int i = 0; i < 250; i++) {
// // Sign a message
// byte[] bytes = new byte[i+1];
// new SecureRandom().nextBytes(bytes);
// signature.update(bytes);
// byte[] signatureBytes = signature.sign();
//
// // Validation
// Signature verifier = Signature.getInstance("SHA512withECDSA");
// verifier.initVerify(pair.getPublic());
// verifier.update(bytes);
// boolean verified = verifier.verify(signatureBytes);
// if (!verified) {
// System.out.println("Public: " + new String(pair.getPublic().getEncoded(), StandardCharsets.UTF_8));
// System.out.println("Private: " + new String(pair.getPrivate().getEncoded(), StandardCharsets.UTF_8));
// }
// assertTrue(verified);
// }
}

@Test
Expand Down
7 changes: 4 additions & 3 deletions src/test/java/io/fusionauth/security/KeyUtilsTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.fusionauth.security;

import io.fusionauth.pem.PEMDecoder;
import io.fusionauth.pem.domain.PEM;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
Expand All @@ -34,8 +35,8 @@ public class KeyUtilsTests {
@DataProvider(name = "ecKeyLengths")
public Object[][] ecKeyLengths() {
return new Object[][]{
{"EC", 256, 256, 256},
{"EC", 384, 384, 384},
// {"EC", 256, 256, 256},
// {"EC", 384, 384, 384},
{"EC", 521, 521, 521}
};
}
Expand Down Expand Up @@ -63,7 +64,7 @@ public void problematicKey() {
// failures where the key is not an exact size and we have to figure out which key size it should be reported as.
// - For testing locally, you can ramp up this invocation count to 100k or something like that to prove that we have
// consistency over time.
@Test(dataProvider = "ecKeyLengths", invocationCount = 500)
@Test(dataProvider = "ecKeyLengths", invocationCount = 20000)
public void ec_getKeyLength(String algorithm, int keySize, int privateKeySize, int publicKeySize) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
keyPairGenerator.initialize(keySize);
Expand Down

0 comments on commit 8db30c7

Please sign in to comment.