11package com .auth0 .jwt .algorithms ;
22
3+ import com .auth0 .jwt .exceptions .SignatureGenerationException ;
34import com .auth0 .jwt .exceptions .SignatureVerificationException ;
45import org .apache .commons .codec .binary .Base64 ;
56import org .junit .Rule ;
67import org .junit .Test ;
78import org .junit .rules .ExpectedException ;
89
9- import java .io .UnsupportedEncodingException ;
1010import java .security .*;
1111import java .security .interfaces .ECKey ;
12+ import java .security .interfaces .ECPrivateKey ;
1213import java .security .interfaces .ECPublicKey ;
1314
1415import static com .auth0 .jwt .PemUtils .readPrivateKeyFromFile ;
1516import static com .auth0 .jwt .PemUtils .readPublicKeyFromFile ;
16- import static org .hamcrest .Matchers .is ;
17+ import static org .hamcrest .Matchers .* ;
1718import static org .hamcrest .Matchers .isA ;
19+ import static org .junit .Assert .assertThat ;
1820import static org .junit .internal .matchers .ThrowableMessageMatcher .hasMessage ;
1921import static org .mockito .ArgumentMatchers .any ;
2022import static org .mockito .ArgumentMatchers .anyString ;
@@ -40,6 +42,8 @@ public class ECDSAAlgorithmTest {
4042 //JOSE Signatures obtained using Node 'jwa' lib: https://github.com/brianloveswords/node-jwa
4143 //DER Signatures obtained from source JOSE signature using 'ecdsa-sig-formatter' lib: https://github.com/Brightspace/node-ecdsa-sig-formatter
4244
45+ // Verify
46+
4347 @ Test
4448 public void shouldPassECDSA256VerificationWithJOSESignature () throws Exception {
4549 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g" ;
@@ -85,7 +89,7 @@ public void shouldFailECDSA256VerificationOnInvalidSignatureLength() throws Exce
8589
8690 byte [] bytes = new byte [63 ];
8791 new SecureRandom ().nextBytes (bytes );
88- String signature = toBase64 (bytes );
92+ String signature = Base64 . encodeBase64URLSafeString (bytes );
8993 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
9094 Algorithm algorithm = Algorithm .ECDSA256 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_256 , "EC" ));
9195 AlgorithmUtils .verify (algorithm , jwt );
@@ -98,7 +102,7 @@ public void shouldFailECDSA256VerificationOnInvalidJOSESignature() throws Except
98102
99103 byte [] bytes = new byte [64 ];
100104 new SecureRandom ().nextBytes (bytes );
101- String signature = toBase64 (bytes );
105+ String signature = Base64 . encodeBase64URLSafeString (bytes );
102106 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
103107 Algorithm algorithm = Algorithm .ECDSA256 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_256 , "EC" ));
104108 AlgorithmUtils .verify (algorithm , jwt );
@@ -112,7 +116,7 @@ public void shouldFailECDSA256VerificationOnInvalidDERSignature() throws Excepti
112116 byte [] bytes = new byte [64 ];
113117 bytes [0 ] = 0x30 ;
114118 new SecureRandom ().nextBytes (bytes );
115- String signature = toBase64 (bytes );
119+ String signature = Base64 . encodeBase64URLSafeString (bytes );
116120 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
117121 Algorithm algorithm = Algorithm .ECDSA256 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_256 , "EC" ));
118122 AlgorithmUtils .verify (algorithm , jwt );
@@ -163,7 +167,7 @@ public void shouldFailECDSA384VerificationOnInvalidSignatureLength() throws Exce
163167
164168 byte [] bytes = new byte [95 ];
165169 new SecureRandom ().nextBytes (bytes );
166- String signature = toBase64 (bytes );
170+ String signature = Base64 . encodeBase64URLSafeString (bytes );
167171 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
168172 Algorithm algorithm = Algorithm .ECDSA384 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_384 , "EC" ));
169173 AlgorithmUtils .verify (algorithm , jwt );
@@ -176,7 +180,7 @@ public void shouldFailECDSA384VerificationOnInvalidJOSESignature() throws Except
176180
177181 byte [] bytes = new byte [96 ];
178182 new SecureRandom ().nextBytes (bytes );
179- String signature = toBase64 (bytes );
183+ String signature = Base64 . encodeBase64URLSafeString (bytes );
180184 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
181185 Algorithm algorithm = Algorithm .ECDSA384 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_384 , "EC" ));
182186 AlgorithmUtils .verify (algorithm , jwt );
@@ -190,7 +194,7 @@ public void shouldFailECDSA384VerificationOnInvalidDERSignature() throws Excepti
190194 byte [] bytes = new byte [96 ];
191195 new SecureRandom ().nextBytes (bytes );
192196 bytes [0 ] = 0x30 ;
193- String signature = toBase64 (bytes );
197+ String signature = Base64 . encodeBase64URLSafeString (bytes );
194198 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
195199 Algorithm algorithm = Algorithm .ECDSA384 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_384 , "EC" ));
196200 AlgorithmUtils .verify (algorithm , jwt );
@@ -241,7 +245,7 @@ public void shouldFailECDSA512VerificationOnInvalidSignatureLength() throws Exce
241245
242246 byte [] bytes = new byte [131 ];
243247 new SecureRandom ().nextBytes (bytes );
244- String signature = toBase64 (bytes );
248+ String signature = Base64 . encodeBase64URLSafeString (bytes );
245249 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
246250 Algorithm algorithm = Algorithm .ECDSA512 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_512 , "EC" ));
247251 AlgorithmUtils .verify (algorithm , jwt );
@@ -254,7 +258,7 @@ public void shouldFailECDSA512VerificationOnInvalidJOSESignature() throws Except
254258
255259 byte [] bytes = new byte [132 ];
256260 new SecureRandom ().nextBytes (bytes );
257- String signature = toBase64 (bytes );
261+ String signature = Base64 . encodeBase64URLSafeString (bytes );
258262 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
259263 Algorithm algorithm = Algorithm .ECDSA512 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_512 , "EC" ));
260264 AlgorithmUtils .verify (algorithm , jwt );
@@ -268,7 +272,7 @@ public void shouldFailECDSA512VerificationOnInvalidDERSignature() throws Excepti
268272 byte [] bytes = new byte [132 ];
269273 new SecureRandom ().nextBytes (bytes );
270274 bytes [0 ] = 0x30 ;
271- String signature = toBase64 (bytes );
275+ String signature = Base64 . encodeBase64URLSafeString (bytes );
272276 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
273277 Algorithm algorithm = Algorithm .ECDSA512 ((ECKey ) readPublicKeyFromFile (INVALID_PUBLIC_KEY_FILE_512 , "EC" ));
274278 AlgorithmUtils .verify (algorithm , jwt );
@@ -283,15 +287,15 @@ public void shouldFailJOSEToDERConversionOnInvalidJOSESignatureLength() throws E
283287
284288 byte [] bytes = new byte [256 ];
285289 new SecureRandom ().nextBytes (bytes );
286- String signature = toBase64 (bytes );
290+ String signature = Base64 . encodeBase64URLSafeString (bytes );
287291 String jwt = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9." + signature ;
288292
289293 Algorithm algorithm = new ECDSAAlgorithm ("ES256" , "SHA256withECDSA" , 128 , (ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" ));
290294 AlgorithmUtils .verify (algorithm , jwt );
291295 }
292296
293297 @ Test
294- public void shouldThrowWhenSignatureAlgorithmDoesNotExists () throws Exception {
298+ public void shouldThrowOnVerifyWhenSignatureAlgorithmDoesNotExists () throws Exception {
295299 exception .expect (SignatureVerificationException .class );
296300 exception .expectMessage ("The Token's Signature resulted invalid when verified using the Algorithm: some-alg" );
297301 exception .expectCause (isA (NoSuchAlgorithmException .class ));
@@ -307,7 +311,7 @@ public void shouldThrowWhenSignatureAlgorithmDoesNotExists() throws Exception {
307311 }
308312
309313 @ Test
310- public void shouldThrowWhenThePublicKeyIsInvalid () throws Exception {
314+ public void shouldThrowOnVerifyWhenThePublicKeyIsInvalid () throws Exception {
311315 exception .expect (SignatureVerificationException .class );
312316 exception .expectMessage ("The Token's Signature resulted invalid when verified using the Algorithm: some-alg" );
313317 exception .expectCause (isA (InvalidKeyException .class ));
@@ -323,7 +327,7 @@ public void shouldThrowWhenThePublicKeyIsInvalid() throws Exception {
323327 }
324328
325329 @ Test
326- public void shouldThrowWhenTheSignatureIsNotPrepared () throws Exception {
330+ public void shouldThrowOnVerifyWhenTheSignatureIsNotPrepared () throws Exception {
327331 exception .expect (SignatureVerificationException .class );
328332 exception .expectMessage ("The Token's Signature resulted invalid when verified using the Algorithm: some-alg" );
329333 exception .expectCause (isA (SignatureException .class ));
@@ -338,13 +342,136 @@ public void shouldThrowWhenTheSignatureIsNotPrepared() throws Exception {
338342 AlgorithmUtils .verify (algorithm , jwt );
339343 }
340344
341- private String toBase64 (byte [] bytes ) {
342- String res = null ;
343- try {
344- res = new String (Base64 .encodeBase64 (bytes , false , true ), "UTF-8" );
345- } catch (UnsupportedEncodingException e ) {
346- e .printStackTrace ();
347- }
348- return res ;
345+ //Sign
346+ private static final String ES256Header = "eyJhbGciOiJFUzI1NiJ9" ;
347+ private static final String ES384Header = "eyJhbGciOiJFUzM4NCJ9" ;
348+ private static final String ES512Header = "eyJhbGciOiJFUzUxMiJ9" ;
349+ private static final String auth0IssPayload = "eyJpc3MiOiJhdXRoMCJ9" ;
350+
351+ @ Test
352+ public void shouldDoECDSA256Signing () throws Exception {
353+ Algorithm algorithmSign = Algorithm .ECDSA256 ((ECKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_256 , "EC" ));
354+ Algorithm algorithmVerify = Algorithm .ECDSA256 ((ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" ));
355+ byte [] contentBytes = String .format ("%s.%s" , ES256Header , auth0IssPayload ).getBytes ();
356+ byte [] signatureBytes = algorithmSign .sign (contentBytes );
357+
358+ assertThat (signatureBytes , is (notNullValue ()));
359+ algorithmVerify .verify (contentBytes , signatureBytes );
360+ }
361+
362+ @ Test
363+ public void shouldFailOnECDSA256SigningWhenUsingPublicKey () throws Exception {
364+ exception .expect (SignatureGenerationException .class );
365+ exception .expectMessage ("The Token's Signature couldn't be generated when signing using the Algorithm: SHA256withECDSA" );
366+ exception .expectCause (isA (IllegalArgumentException .class ));
367+ exception .expectCause (hasMessage (is ("The given ECKey is not a ECPrivateKey." )));
368+
369+ Algorithm algorithm = Algorithm .ECDSA256 ((ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_256 , "EC" ));
370+ algorithm .sign (new byte [0 ]);
371+ }
372+
373+ @ Test
374+ public void shouldDoECDSA384Signing () throws Exception {
375+ Algorithm algorithmSign = Algorithm .ECDSA384 ((ECKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_384 , "EC" ));
376+ Algorithm algorithmVerify = Algorithm .ECDSA384 ((ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_384 , "EC" ));
377+ byte [] contentBytes = String .format ("%s.%s" , ES384Header , auth0IssPayload ).getBytes ();
378+ byte [] signatureBytes = algorithmSign .sign (contentBytes );
379+
380+ assertThat (signatureBytes , is (notNullValue ()));
381+ algorithmVerify .verify (contentBytes , signatureBytes );
382+ }
383+
384+ @ Test
385+ public void shouldFailOnECDSA384SigningWhenUsingPublicKey () throws Exception {
386+ exception .expect (SignatureGenerationException .class );
387+ exception .expectMessage ("The Token's Signature couldn't be generated when signing using the Algorithm: SHA384withECDSA" );
388+ exception .expectCause (isA (IllegalArgumentException .class ));
389+ exception .expectCause (hasMessage (is ("The given ECKey is not a ECPrivateKey." )));
390+
391+ Algorithm algorithm = Algorithm .ECDSA384 ((ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_384 , "EC" ));
392+ algorithm .sign (new byte [0 ]);
393+ }
394+
395+ @ Test
396+ public void shouldDoECDSA512Signing () throws Exception {
397+ Algorithm algorithmSign = Algorithm .ECDSA512 ((ECKey ) readPrivateKeyFromFile (PRIVATE_KEY_FILE_512 , "EC" ));
398+ Algorithm algorithmVerify = Algorithm .ECDSA512 ((ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_512 , "EC" ));
399+ byte [] contentBytes = String .format ("%s.%s" , ES512Header , auth0IssPayload ).getBytes ();
400+ byte [] signatureBytes = algorithmSign .sign (contentBytes );
401+
402+ assertThat (signatureBytes , is (notNullValue ()));
403+ algorithmVerify .verify (contentBytes , signatureBytes );
404+ }
405+
406+ @ Test
407+ public void shouldFailOnECDSA512SigningWhenUsingPublicKey () throws Exception {
408+ exception .expect (SignatureGenerationException .class );
409+ exception .expectMessage ("The Token's Signature couldn't be generated when signing using the Algorithm: SHA512withECDSA" );
410+ exception .expectCause (isA (IllegalArgumentException .class ));
411+ exception .expectCause (hasMessage (is ("The given ECKey is not a ECPrivateKey." )));
412+
413+ Algorithm algorithm = Algorithm .ECDSA512 ((ECKey ) readPublicKeyFromFile (PUBLIC_KEY_FILE_512 , "EC" ));
414+ algorithm .sign (new byte [0 ]);
415+ }
416+
417+ @ Test
418+ public void shouldThrowOnSignWhenSignatureAlgorithmDoesNotExists () throws Exception {
419+ exception .expect (SignatureGenerationException .class );
420+ exception .expectMessage ("The Token's Signature couldn't be generated when signing using the Algorithm: some-algorithm" );
421+ exception .expectCause (isA (NoSuchAlgorithmException .class ));
422+
423+ CryptoHelper crypto = mock (CryptoHelper .class );
424+ when (crypto .createSignatureFor (anyString (), any (PrivateKey .class ), any (byte [].class )))
425+ .thenThrow (NoSuchAlgorithmException .class );
426+
427+ ECKey key = mock (ECKey .class , withSettings ().extraInterfaces (ECPrivateKey .class ));
428+ Algorithm algorithm = new ECDSAAlgorithm (crypto , "some-alg" , "some-algorithm" , 32 , key );
429+ algorithm .sign (ES256Header .getBytes ());
430+ }
431+
432+ @ Test
433+ public void shouldThrowOnSignWhenThePrivateKeyIsInvalid () throws Exception {
434+ exception .expect (SignatureGenerationException .class );
435+ exception .expectMessage ("The Token's Signature couldn't be generated when signing using the Algorithm: some-algorithm" );
436+ exception .expectCause (isA (InvalidKeyException .class ));
437+
438+ CryptoHelper crypto = mock (CryptoHelper .class );
439+ when (crypto .createSignatureFor (anyString (), any (PrivateKey .class ), any (byte [].class )))
440+ .thenThrow (InvalidKeyException .class );
441+
442+ ECKey key = mock (ECKey .class , withSettings ().extraInterfaces (ECPrivateKey .class ));
443+ Algorithm algorithm = new ECDSAAlgorithm (crypto , "some-alg" , "some-algorithm" , 32 , key );
444+ algorithm .sign (ES256Header .getBytes ());
445+ }
446+
447+ @ Test
448+ public void shouldThrowOnSignWhenUsingPublicKey () throws Exception {
449+ exception .expect (SignatureGenerationException .class );
450+ exception .expectMessage ("The Token's Signature couldn't be generated when signing using the Algorithm: some-algorithm" );
451+ exception .expectCause (isA (IllegalArgumentException .class ));
452+ exception .expectCause (hasMessage (is ("The given ECKey is not a ECPrivateKey." )));
453+
454+ CryptoHelper crypto = mock (CryptoHelper .class );
455+ when (crypto .createSignatureFor (anyString (), any (PrivateKey .class ), any (byte [].class )))
456+ .thenThrow (InvalidKeyException .class );
457+
458+ ECKey key = mock (ECKey .class , withSettings ().extraInterfaces (ECPublicKey .class ));
459+ Algorithm algorithm = new ECDSAAlgorithm (crypto , "some-alg" , "some-algorithm" , 32 , key );
460+ algorithm .sign (ES256Header .getBytes ());
461+ }
462+
463+ @ Test
464+ public void shouldThrowOnSignWhenTheSignatureIsNotPrepared () throws Exception {
465+ exception .expect (SignatureGenerationException .class );
466+ exception .expectMessage ("The Token's Signature couldn't be generated when signing using the Algorithm: some-algorithm" );
467+ exception .expectCause (isA (SignatureException .class ));
468+
469+ CryptoHelper crypto = mock (CryptoHelper .class );
470+ when (crypto .createSignatureFor (anyString (), any (PrivateKey .class ), any (byte [].class )))
471+ .thenThrow (SignatureException .class );
472+
473+ ECKey key = mock (ECKey .class , withSettings ().extraInterfaces (ECPrivateKey .class ));
474+ Algorithm algorithm = new ECDSAAlgorithm (crypto , "some-alg" , "some-algorithm" , 32 , key );
475+ algorithm .sign (ES256Header .getBytes ());
349476 }
350477}
0 commit comments