44import com .auth0 .jwt .exceptions .SignatureGenerationException ;
55import com .auth0 .jwt .exceptions .SignatureVerificationException ;
66import com .auth0 .jwt .interfaces .ECDSAKeyProvider ;
7+ import com .auth0 .jwt .interfaces .JWTVerifier ;
78import org .hamcrest .Matchers ;
89import org .hamcrest .collection .IsIn ;
910import org .junit .Assert ;
1213import org .junit .rules .ExpectedException ;
1314
1415import java .io .ByteArrayOutputStream ;
16+ import java .math .BigInteger ;
1517import java .nio .charset .StandardCharsets ;
1618import java .security .*;
1719import java .security .interfaces .ECKey ;
1820import java .security .interfaces .ECPrivateKey ;
1921import java .security .interfaces .ECPublicKey ;
22+ import java .security .spec .ECParameterSpec ;
2023import java .util .Arrays ;
2124import java .util .Base64 ;
2225
@@ -574,6 +577,10 @@ public void shouldThrowOnVerifyWhenSignatureAlgorithmDoesNotExists() throws Exce
574577 .thenThrow (NoSuchAlgorithmException .class );
575578
576579 ECPublicKey publicKey = mock (ECPublicKey .class );
580+ when (publicKey .getParams ()).thenReturn (mock (ECParameterSpec .class ));
581+ byte [] a = new byte [64 ];
582+ Arrays .fill (a , Byte .MAX_VALUE );
583+ when (publicKey .getParams ().getOrder ()).thenReturn (new BigInteger (a ));
577584 ECPrivateKey privateKey = mock (ECPrivateKey .class );
578585 ECDSAKeyProvider provider = ECDSAAlgorithm .providerForKeys (publicKey , privateKey );
579586 Algorithm algorithm = new ECDSAAlgorithm (crypto , "some-alg" , "some-algorithm" , 32 , provider );
@@ -592,6 +599,10 @@ public void shouldThrowOnVerifyWhenThePublicKeyIsInvalid() throws Exception {
592599 .thenThrow (InvalidKeyException .class );
593600
594601 ECPublicKey publicKey = mock (ECPublicKey .class );
602+ when (publicKey .getParams ()).thenReturn (mock (ECParameterSpec .class ));
603+ byte [] a = new byte [64 ];
604+ Arrays .fill (a , Byte .MAX_VALUE );
605+ when (publicKey .getParams ().getOrder ()).thenReturn (new BigInteger (a ));
595606 ECPrivateKey privateKey = mock (ECPrivateKey .class );
596607 ECDSAKeyProvider provider = ECDSAAlgorithm .providerForKeys (publicKey , privateKey );
597608 Algorithm algorithm = new ECDSAAlgorithm (crypto , "some-alg" , "some-algorithm" , 32 , provider );
@@ -610,6 +621,10 @@ public void shouldThrowOnVerifyWhenTheSignatureIsNotPrepared() throws Exception
610621 .thenThrow (SignatureException .class );
611622
612623 ECPublicKey publicKey = mock (ECPublicKey .class );
624+ when (publicKey .getParams ()).thenReturn (mock (ECParameterSpec .class ));
625+ byte [] a = new byte [64 ];
626+ Arrays .fill (a , Byte .MAX_VALUE );
627+ when (publicKey .getParams ().getOrder ()).thenReturn (new BigInteger (a ));
613628 ECPrivateKey privateKey = mock (ECPrivateKey .class );
614629 ECDSAKeyProvider provider = ECDSAAlgorithm .providerForKeys (publicKey , privateKey );
615630 Algorithm algorithm = new ECDSAAlgorithm (crypto , "some-alg" , "some-algorithm" , 32 , provider );
@@ -939,12 +954,13 @@ public void shouldThrowOnDERSignatureConversionIfSNumberDoesNotHaveExpectedLengt
939954
940955 @ Test
941956 public void shouldThrowOnJOSESignatureConversionIfDoesNotHaveExpectedLength () throws Exception {
942- ECDSAAlgorithm algorithm256 = (ECDSAAlgorithm ) Algorithm .ECDSA256 ((ECPublicKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" ), (ECPrivateKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" ));
957+ ECPublicKey publicKey = (ECPublicKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
958+ ECDSAAlgorithm algorithm256 = (ECDSAAlgorithm ) Algorithm .ECDSA256 (publicKey , (ECPrivateKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" ));
943959 byte [] joseSignature = new byte [32 * 2 - 1 ];
944960 exception .expect (SignatureException .class );
945961 exception .expectMessage ("Invalid JOSE signature format." );
946962
947- algorithm256 .JOSEToDER (joseSignature );
963+ algorithm256 .validateSignatureStructure (joseSignature , publicKey );
948964 }
949965
950966 @ Test
@@ -1309,4 +1325,146 @@ public void shouldFailOnECDSA256SigningWithDeprecatedMethodWhenProvidedPrivateKe
13091325 algorithm .sign (new byte [0 ]);
13101326 }
13111327
1328+ @ Test
1329+ public void invalidECDSA256SignatureShouldFailTokenVerification () throws Exception {
1330+ exception .expect (SignatureVerificationException .class );
1331+ exception .expectCause (isA (SignatureException .class ));
1332+
1333+ String jwtWithInvalidSig = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0._____wAAAAD__________7zm-q2nF56E87nKwvxjJVH_____AAAAAP__________vOb6racXnoTzucrC_GMlUQ" ;
1334+
1335+ ECKey key256 = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
1336+ ECKey key384 = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_384 , "EC" );
1337+ ECKey key512 = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_512 , "EC" );
1338+ ECKey key256k = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256K , "EC" );
1339+ JWTVerifier verifier256 = JWT .require (Algorithm .ECDSA256 (key256 )).build ();
1340+ JWTVerifier verifier384 = JWT .require (Algorithm .ECDSA256 (key384 )).build ();
1341+ JWTVerifier verifier512 = JWT .require (Algorithm .ECDSA256 (key512 )).build ();
1342+ JWTVerifier verifier256k = JWT .require (Algorithm .ECDSA256 (key256k )).build ();
1343+ verifier256 .verify (jwtWithInvalidSig );
1344+ verifier384 .verify (jwtWithInvalidSig );
1345+ verifier512 .verify (jwtWithInvalidSig );
1346+ verifier256k .verify (jwtWithInvalidSig );
1347+ }
1348+
1349+ @ Test
1350+ public void emptyECDSA256SignatureShouldFailTokenVerification () throws Exception {
1351+ exception .expect (SignatureVerificationException .class );
1352+ exception .expectCause (isA (SignatureException .class ));
1353+
1354+ String jwtWithInvalidSig = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ;
1355+
1356+ ECKey key256 = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
1357+ ECKey key384 = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_384 , "EC" );
1358+ ECKey key512 = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_512 , "EC" );
1359+ ECKey key256k = (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256K , "EC" );
1360+ JWTVerifier verifier256 = JWT .require (Algorithm .ECDSA256 (key256 )).build ();
1361+ JWTVerifier verifier384 = JWT .require (Algorithm .ECDSA256 (key384 )).build ();
1362+ JWTVerifier verifier512 = JWT .require (Algorithm .ECDSA256 (key512 )).build ();
1363+ JWTVerifier verifier256k = JWT .require (Algorithm .ECDSA256 (key256k )).build ();
1364+ verifier256 .verify (jwtWithInvalidSig );
1365+ verifier384 .verify (jwtWithInvalidSig );
1366+ verifier512 .verify (jwtWithInvalidSig );
1367+ verifier256k .verify (jwtWithInvalidSig );
1368+ }
1369+
1370+ @ Test
1371+ public void signatureWithAllZerosShouldFail () throws Exception {
1372+ exception .expect (SignatureException .class );
1373+ exception .expectMessage ("Invalid signature format." );
1374+
1375+ ECPublicKey pubKey = (ECPublicKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
1376+
1377+ ECDSAAlgorithm algorithm256 = (ECDSAAlgorithm ) Algorithm .ECDSA256 (pubKey , (ECPrivateKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" ));
1378+ byte [] signatureBytes = new byte [64 ];
1379+ algorithm256 .validateSignatureStructure (signatureBytes , pubKey );
1380+ }
1381+
1382+ @ Test
1383+ public void signatureWithRZeroShouldFail () throws Exception {
1384+ exception .expect (SignatureException .class );
1385+ exception .expectMessage ("Invalid signature format." );
1386+
1387+ ECPublicKey publicKey = (ECPublicKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
1388+ ECPrivateKey privateKey = (ECPrivateKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" );
1389+
1390+ String signedJwt = JWT .create ().sign (Algorithm .ECDSA256 (publicKey , privateKey ));
1391+
1392+ String [] chunks = signedJwt .split ("\\ ." );
1393+ byte [] signature = Base64 .getUrlDecoder ().decode (chunks [2 ]);
1394+
1395+ byte [] sigWithBlankR = new byte [signature .length ];
1396+ for (int i = 0 ; i < signature .length ; i ++) {
1397+ if (i < signature .length / 2 ) {
1398+ sigWithBlankR [i ] = 0 ;
1399+ } else {
1400+ sigWithBlankR [i ] = signature [i ];
1401+ }
1402+ }
1403+
1404+ ECDSAAlgorithm algorithm256 = (ECDSAAlgorithm ) Algorithm .ECDSA256 (publicKey , privateKey );
1405+ algorithm256 .validateSignatureStructure (sigWithBlankR , publicKey );
1406+ }
1407+
1408+ @ Test
1409+ public void signatureWithSZeroShouldFail () throws Exception {
1410+ exception .expect (SignatureException .class );
1411+ exception .expectMessage ("Invalid signature format." );
1412+
1413+ ECPublicKey publicKey = (ECPublicKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
1414+ ECPrivateKey privateKey = (ECPrivateKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" );
1415+
1416+ String signedJwt = JWT .create ().sign (Algorithm .ECDSA256 (publicKey , privateKey ));
1417+
1418+ String [] chunks = signedJwt .split ("\\ ." );
1419+ byte [] signature = Base64 .getUrlDecoder ().decode (chunks [2 ]);
1420+
1421+ byte [] sigWithBlankS = new byte [signature .length ];
1422+ for (int i = 0 ; i < signature .length ; i ++) {
1423+ if (i < signature .length / 2 ) {
1424+ sigWithBlankS [i ] = signature [i ];
1425+ } else {
1426+ sigWithBlankS [i ] = 0 ;
1427+ }
1428+ }
1429+
1430+ ECDSAAlgorithm algorithm256 = (ECDSAAlgorithm ) Algorithm .ECDSA256 (publicKey , privateKey );
1431+ algorithm256 .validateSignatureStructure (sigWithBlankS , publicKey );
1432+ }
1433+
1434+ @ Test
1435+ public void signatureWithRValueNotLessThanOrderShouldFail () throws Exception {
1436+ exception .expect (SignatureException .class );
1437+ exception .expectMessage ("Invalid signature format." );
1438+
1439+ ECPublicKey publicKey = (ECPublicKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
1440+ ECPrivateKey privateKey = (ECPrivateKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" );
1441+
1442+ String signedJwt = JWT .create ().sign (Algorithm .ECDSA256 (publicKey , privateKey ));
1443+ String jwtWithInvalidSig = signedJwt .substring (0 , signedJwt .lastIndexOf ('.' ) + 1 ) + "_____wAAAAD__________7zm-q2nF56E87nKwvxjJVH_____AAAAAP__________vOb6racXnoTzucrC_GMlUQ" ;
1444+
1445+ String [] chunks = jwtWithInvalidSig .split ("\\ ." );
1446+ byte [] invalidSignature = Base64 .getUrlDecoder ().decode (chunks [2 ]);
1447+
1448+ ECDSAAlgorithm algorithm256 = (ECDSAAlgorithm ) Algorithm .ECDSA256 (publicKey , privateKey );
1449+ algorithm256 .validateSignatureStructure (invalidSignature , publicKey );
1450+ }
1451+
1452+ @ Test
1453+ public void signatureWithSValueNotLessThanOrderShouldFail () throws Exception {
1454+ exception .expect (SignatureException .class );
1455+ exception .expectMessage ("Invalid signature format." );
1456+
1457+ ECPublicKey publicKey = (ECPublicKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" );
1458+ ECPrivateKey privateKey = (ECPrivateKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" );
1459+
1460+ String signedJwt = JWT .create ().sign (Algorithm .ECDSA256 (publicKey , privateKey ));
1461+ String jwtWithInvalidSig = signedJwt .substring (0 , signedJwt .lastIndexOf ('.' ) + 1 ) + "_____wAAAAD__________7zm-q2nF56E87nKwvxjJVH_____AAAAAP__________vOb6racXnoTzucrC_GMlUQ" ;
1462+
1463+ String [] chunks = jwtWithInvalidSig .split ("\\ ." );
1464+ byte [] invalidSignature = Base64 .getUrlDecoder ().decode (chunks [2 ]);
1465+ invalidSignature [0 ] = Byte .MAX_VALUE ;
1466+
1467+ ECDSAAlgorithm algorithm256 = (ECDSAAlgorithm ) Algorithm .ECDSA256 (publicKey , privateKey );
1468+ algorithm256 .validateSignatureStructure (invalidSignature , publicKey );
1469+ }
13121470}
0 commit comments