Skip to content

Commit 5f1e6cd

Browse files
committed
Current x509 and current KeyBundle - needs comments
1 parent 36c5786 commit 5f1e6cd

17 files changed

Lines changed: 782 additions & 7 deletions

File tree

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
### of contributors, see the revision history in source control.
55

66
Auth0 LLC, Google LLC
7+

lib/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ dependencies {
3737
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.2'
3838
compile 'commons-codec:commons-codec:1.11'
3939
compile 'com.google.code.gson:gson:2.8.2'
40+
compile 'com.auth0:jwks-rsa:0.3.0'
41+
compile 'com.nimbusds:nimbus-jose-jwt:2.19.1'
42+
compile 'org.apache.httpcomponents:httpcore:4.4.1'
43+
compile 'org.apache.httpcomponents:httpclient:4.5'
44+
compile group: 'org.slf4j', name:'slf4j-api', version: '1.7.2'
45+
compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'
4046
testCompile 'org.bouncycastle:bcprov-jdk15on:1.58'
4147
testCompile 'junit:junit:4.12'
4248
testCompile 'net.jodah:concurrentunit:0.4.3'

lib/src/main/java/com/auth0/jwt/algorithms/CryptoHelper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ byte[] createSignatureFor(String algorithm, byte[] secretBytes, byte[] contentBy
3434
mac.init(new SecretKeySpec(secretBytes, algorithm));
3535
return mac.doFinal(contentBytes);
3636
}
37-
37+
//get back public key from x509 DER string
38+
//use public key to verify (public key might be in pem format)
39+
//pass
3840
boolean verifySignatureFor(String algorithm, PublicKey publicKey, byte[] contentBytes, byte[] signatureBytes) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
3941
final Signature s = Signature.getInstance(algorithm);
4042
s.initVerify(publicKey);

lib/src/main/java/com/auth0/jwt/algorithms/ECDSAAlgorithm.java

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,43 @@
1919

2020
package com.auth0.jwt.algorithms;
2121

22+
import com.auth0.jwk.Jwk;
23+
import com.auth0.jwk.JwkProvider;
24+
import com.auth0.jwk.UrlJwkProvider;
2225
import com.auth0.jwt.creators.EncodeType;
2326
import com.auth0.jwt.exceptions.SignatureGenerationException;
2427
import com.auth0.jwt.exceptions.SignatureVerificationException;
2528
import com.auth0.jwt.interfaces.DecodedJWT;
2629
import com.auth0.jwt.interfaces.ECDSAKeyProvider;
30+
import com.auth0.jwt.interfaces.Payload;
31+
import com.google.gson.JsonElement;
32+
import com.google.gson.JsonObject;
33+
import com.google.gson.JsonParser;
34+
import com.nimbusds.jose.JWSAlgorithm;
35+
import com.nimbusds.jose.JWSHeader;
36+
import com.nimbusds.jose.JWSObject;
37+
import com.nimbusds.jose.crypto.RSASSASigner;
38+
import com.nimbusds.jose.crypto.RSASSAVerifier;
39+
import com.nimbusds.jose.jwk.JWK;
40+
import net.minidev.json.JSONArray;
41+
import net.minidev.json.JSONObject;
42+
import net.minidev.json.parser.JSONParser;
2743
import org.apache.commons.codec.binary.Base32;
2844
import org.apache.commons.codec.binary.Base64;
2945
import org.apache.commons.codec.binary.Hex;
3046
import org.apache.commons.codec.binary.StringUtils;
3147

48+
import java.io.File;
49+
import java.io.FileReader;
50+
import java.net.URL;
3251
import java.net.URLDecoder;
3352
import java.nio.charset.StandardCharsets;
34-
import java.security.InvalidKeyException;
35-
import java.security.NoSuchAlgorithmException;
36-
import java.security.SignatureException;
53+
import java.security.*;
3754
import java.security.interfaces.ECPrivateKey;
3855
import java.security.interfaces.ECPublicKey;
56+
import java.security.interfaces.RSAPrivateKey;
57+
import java.security.interfaces.RSAPublicKey;
58+
import java.util.List;
3959

4060
class ECDSAAlgorithm extends Algorithm {
4161

@@ -80,10 +100,48 @@ public void verify(DecodedJWT jwt, EncodeType encodeType) throws Exception {
80100
}
81101

82102
try {
83-
ECPublicKey publicKey = keyProvider.getPublicKeyById(jwt.getKeyId());
103+
104+
//create a http request that gets back a response for the jwks uri and then once you get back the response,
105+
//parse it to get back the x509 DER string and get the public key from that string
106+
//from the public key of that string, pass it into verifySignatureFor()
107+
PublicKey publicKey = null;
108+
String kid = jwt.getKeyId();
109+
String algorithm = jwt.getAlgorithm();
110+
if(kid == null) {
111+
publicKey = keyProvider.getPublicKeyById(kid);
112+
} else if(algorithm.equals("RSA")){
113+
//JwkProvider provider = new UrlJwkProvider("https://sandrino.auth0.com/.well-known/jwks.json");
114+
JwkProvider provider = new UrlJwkProvider(new File("/Users/jdahmubed/documents/jwksRSA.json").toURI().toURL());//"file:///);
115+
Jwk jwk = provider.get(kid);
116+
publicKey = jwk.getPublicKey();
117+
} /*else if(algorithm.contains("ES")) {
118+
// JSONParser parser = new JSONParser();
119+
// JSONArray a = (JSONArray) parser.parse(new FileReader("/Users/jdahmubed/documents/jwks.json"));
120+
121+
JsonObject gsonObject = new JsonObject();
122+
123+
124+
JsonParser parser = new JsonParser();
125+
JsonElement jsonElement = parser.parse(new FileReader("/Users/jdahmubed/documents/jwks.json"));
126+
gsonObject = jsonElement.getAsJsonObject();
127+
128+
JSONObject jsonObject = new JSONObject();
129+
for(String key : gsonObject.keySet()) {
130+
jsonObject.put(key, gsonObject.get(key));
131+
}
132+
jsonObject.put("alg", "ES256");
133+
JWSHeader jwsHeader = JWSHeader.parse(jsonObject);
134+
135+
JWSHeader header = new JWSHeader(JWSAlgorithm.ES256);
136+
header.setJWKURL(new File("/Users/jdahmubed/documents/jwks.json").toURI().toURL());
137+
List<com.nimbusds.jose.util.Base64> list = header.getX509CertChain();
138+
System.out.print(list);
139+
}*/
140+
84141
if (publicKey == null) {
85142
throw new IllegalStateException("The given Public Key is null.");
86143
}
144+
//pass in publicKey from x509 or the current key (look up)
87145
boolean valid = crypto.verifySignatureFor(getDescription(), publicKey, contentBytes, JOSEToDER(signatureBytes));
88146

89147
if (!valid) {
@@ -241,6 +299,7 @@ static ECDSAKeyProvider providerForKeys(final ECPublicKey publicKey, final ECPri
241299
if (publicKey == null && privateKey == null) {
242300
throw new IllegalArgumentException("Both provided Keys cannot be null.");
243301
}
302+
244303
return new ECDSAKeyProvider() {
245304
@Override
246305
public ECPublicKey getPublicKeyById(String keyId) {

lib/src/main/java/com/auth0/jwt/algorithms/HMACAlgorithm.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public void verify(DecodedJWT jwt, EncodeType encodeType) throws Exception {
9090
}
9191

9292
try {
93+
//need to add fucntionality to pass in secret or pass in x509 public key
94+
//jwks uri
9395
boolean valid = crypto.verifySignatureFor(getDescription(), secret, contentBytes, signatureBytes);
9496
if (!valid) {
9597
throw new SignatureVerificationException(this);

lib/src/main/java/com/auth0/jwt/algorithms/RSAAlgorithm.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919

2020
package com.auth0.jwt.algorithms;
2121

22+
import com.auth0.jwk.Jwk;
23+
import com.auth0.jwk.JwkProvider;
24+
import com.auth0.jwk.UrlJwkProvider;
2225
import com.auth0.jwt.creators.EncodeType;
26+
import com.auth0.jwt.creators.JWTCreator;
2327
import com.auth0.jwt.exceptions.SignatureGenerationException;
2428
import com.auth0.jwt.exceptions.SignatureVerificationException;
2529
import com.auth0.jwt.interfaces.DecodedJWT;
@@ -28,18 +32,24 @@
2832
import org.apache.commons.codec.binary.Base64;
2933
import org.apache.commons.codec.binary.Hex;
3034

35+
import java.io.*;
3136
import java.net.URLDecoder;
3237
import java.nio.charset.StandardCharsets;
3338
import java.security.InvalidKeyException;
3439
import java.security.NoSuchAlgorithmException;
40+
import java.security.PublicKey;
3541
import java.security.SignatureException;
42+
import java.security.cert.CertificateFactory;
43+
import java.security.cert.X509Certificate;
3644
import java.security.interfaces.RSAPrivateKey;
3745
import java.security.interfaces.RSAPublicKey;
46+
import java.util.Arrays;
3847

3948
class RSAAlgorithm extends Algorithm {
4049

4150
private final RSAKeyProvider keyProvider;
4251
private final CryptoHelper crypto;
52+
public static byte[] bytesAfterBeingDecoded;
4353

4454
//Visible for testing
4555
RSAAlgorithm(CryptoHelper crypto, String id, String algorithm, RSAKeyProvider keyProvider) throws IllegalArgumentException {
@@ -70,14 +80,46 @@ public void verify(DecodedJWT jwt, EncodeType encodeType) throws Exception {
7080
Base32 base32 = new Base32();
7181
urlDecoded = URLDecoder.decode(signature, "UTF-8");
7282
signatureBytes = base32.decode(urlDecoded);
83+
System.out.println("signature bytes after being decoded: " + Arrays.toString(signatureBytes));
84+
bytesAfterBeingDecoded = signatureBytes;
85+
System.out.println("Are they equal? " + Arrays.equals(JWTCreator.bytesBeforeBeingDecoded, bytesAfterBeingDecoded));
7386
break;
7487
case Base64:
7588
signatureBytes = Base64.decodeBase64(signature);
89+
System.out.println("signature bytes after being decoded: " + Arrays.toString(signatureBytes));
90+
bytesAfterBeingDecoded = signatureBytes;
91+
System.out.println("Are they equal? " + Arrays.equals(JWTCreator.bytesBeforeBeingDecoded, bytesAfterBeingDecoded));
7692
break;
7793
}
7894

7995
try {
80-
RSAPublicKey publicKey = keyProvider.getPublicKeyById(jwt.getKeyId());
96+
//RSAPublicKey publicKey = keyProvider.getPublicKeyById(jwt.getKeyId());
97+
/*String kid = jwt.getKeyId();
98+
JwkProvider provider = new UrlJwkProvider(new File("/Users/jdahmubed/documents/jwksRSA.json").toURI().toURL());
99+
Jwk jwk = provider.get(kid);
100+
PublicKey publicKey = jwk.getPublicKey();*/
101+
102+
String kid = jwt.getKeyId();
103+
JwkProvider provider = new UrlJwkProvider(new File("/Users/jdahmubed/documents/jwksRSA.json").toURI().toURL());
104+
Jwk jwk = provider.get(kid);
105+
String cert = jwk.getCertificateChain().get(0);
106+
try (Writer writer = new BufferedWriter(new OutputStreamWriter(
107+
new FileOutputStream("/Users/jdahmubed/workspace/javaOIDCMsgForCOMMENTS/lib/src/main/java/com/auth0/jwt/algorithms/jwks.cert"), "utf-8"))) {
108+
writer.write("-----BEGIN CERTIFICATE-----");
109+
writer.append("\n"+ cert + "\n");
110+
writer.append("-----END CERTIFICATE-----");
111+
}
112+
CertificateFactory fact = CertificateFactory.getInstance("X.509");
113+
FileInputStream is = new FileInputStream ("/Users/jdahmubed/workspace/javaOIDCMsgForCOMMENTS/lib/src/main/java/com/auth0/jwt/algorithms/jwks.cert");
114+
X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
115+
PublicKey publicKey = cer.getPublicKey();
116+
117+
/*
118+
FileInputStream fin = new FileInputStream("/Users/jdahmubed/documents/jwksRSA.json");
119+
CertificateFactory f = CertificateFactory.getInstance("X.509");
120+
X509Certificate certificate = (X509Certificate)f.generateCertificate(fin);
121+
PublicKey publicKey = certificate.getPublicKey();*/
122+
81123
if (publicKey == null) {
82124
throw new IllegalStateException("The given Public Key is null.");
83125
}

lib/src/main/java/com/auth0/jwt/creators/JWTCreator.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
import java.net.URLDecoder;
4040
import java.net.URLEncoder;
4141
import java.nio.charset.StandardCharsets;
42+
import java.util.Arrays;
4243
import java.util.Date;
4344
import java.util.HashMap;
4445
import java.util.Map;
46+
import java.util.logging.Logger;
4547

4648
/**
4749
* The JWTCreator class holds the sign method to generate a complete JWT (with Signature) from a given Header and Payload content.
@@ -52,6 +54,7 @@ public final class JWTCreator {
5254
private final Algorithm algorithm;
5355
private final String headerJson;
5456
private final String payloadJson;
57+
public static byte[] bytesBeforeBeingDecoded;
5558

5659
private JWTCreator(Algorithm algorithm, Map<String, Object> headerClaims, Map<String, Object> payloadClaims) throws JWTCreationException {
5760
this.algorithm = algorithm;
@@ -424,31 +427,58 @@ private String signBase16Encoding() throws UnsupportedEncodingException {
424427

425428
private String signBase32Encoding() throws UnsupportedEncodingException{
426429
Base32 base32 = new Base32();
430+
System.out.println("headerJson: " + headerJson);
431+
System.out.println("headerJson bytes: " + Arrays.toString(headerJson.getBytes()));
427432
String header = URLEncoder.encode(headerJson, "UTF-8");
428433
String payload = URLEncoder.encode(payloadJson, "UTF-8");
429434

430435
byte[] bHeader = header.getBytes("UTF-8");
431436
String encodedHeader = base32.encodeAsString(bHeader);
432437

438+
439+
System.out.println("header after base64 encoding: " + URLDecoder.decode(new String(base32.decode(encodedHeader))).getBytes());
440+
System.out.println("header after base64 encoding bytes: " + Arrays.toString(URLDecoder.decode(new String(base32.decode(encodedHeader))).getBytes()));
441+
System.out.println("header after base64 decoding: " + new String(URLDecoder.decode(new String(base32.decode(encodedHeader))).getBytes()));
442+
System.out.println("header after base64 decoding bytes: " + Arrays.toString(URLDecoder.decode(new String(base32.decode(encodedHeader))).getBytes()));
443+
444+
System.out.println("Are they equal I? " + Arrays.equals(headerJson.getBytes(), URLDecoder.decode(new String(base32.decode(encodedHeader))).getBytes()));
445+
433446
byte[] bPayload = payload.getBytes("UTF-8");
434447
String encodedPayload = base32.encodeAsString(bPayload);
448+
System.out.println("payload after base64 encoding: " + encodedPayload);
449+
System.out.println("payload after base64 encoding bytes: " + Arrays.toString(encodedPayload.getBytes()));
435450

436451
String content = String.format("%s.%s", encodedHeader, encodedPayload);
437452
byte[] signatureBytes = algorithm.sign(content.getBytes(StandardCharsets.UTF_8));
453+
System.out.println("signature bytes: " + Arrays.toString(signatureBytes));
438454
String signature = base32.encodeAsString(signatureBytes);
439455
String signatureFinal = URLEncoder.encode(signature, "UTF-8");
456+
System.out.println("signature after base64 encoding bytes: " + Arrays.toString(signature.getBytes()));
457+
bytesBeforeBeingDecoded = signatureBytes;
440458

441459
return String.format("%s.%s", content, signatureFinal);
442460
}
443461

444462
private String defaultSign() throws SignatureGenerationException {
463+
System.out.println("headerJson: " + headerJson);
464+
System.out.println("headerJson bytes: " + Arrays.toString(headerJson.getBytes()));
445465
String header = Base64.encodeBase64URLSafeString(headerJson.getBytes(StandardCharsets.UTF_8));
466+
System.out.println("header after base64 encoding: " + header);
467+
System.out.println("header after base64 encoding bytes: " + Arrays.toString(header.getBytes()));
468+
System.out.println("header after base64 decoding: " + new String(Base64.decodeBase64(header)));
469+
System.out.println("header after base64 decoding bytes: " + Arrays.toString(Base64.decodeBase64(header)));
470+
471+
System.out.println("Are they equal I? " + Arrays.equals(headerJson.getBytes(), Base64.decodeBase64(header)));
446472
String payload = Base64.encodeBase64URLSafeString(payloadJson.getBytes(StandardCharsets.UTF_8));
473+
System.out.println("payload after base64 encoding: " + payload);
474+
System.out.println("payload after base64 encoding bytes: " + Arrays.toString(payload.getBytes()));
447475
String content = String.format("%s.%s", header, payload);
448476

449477
byte[] signatureBytes = algorithm.sign(content.getBytes(StandardCharsets.UTF_8));
478+
System.out.println("signature bytes: " + Arrays.toString(signatureBytes));
450479
String signature = Base64.encodeBase64URLSafeString(signatureBytes);
451-
480+
System.out.println("signature after base64 encoding bytes: " + Arrays.toString(signature.getBytes()));
481+
bytesBeforeBeingDecoded = signatureBytes;
452482
return String.format("%s.%s", content, signature);
453483
}
454484
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.auth0.jwt.exceptions.oicmsg_exceptions;
2+
3+
public class ImportException extends Exception {
4+
public ImportException(String message) {
5+
super(message);
6+
}
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.auth0.jwt.exceptions.oicmsg_exceptions;
2+
3+
public class JWKException extends Exception{
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.auth0.jwt.exceptions.oicmsg_exceptions;
2+
3+
public enum KeyUsage {
4+
}

0 commit comments

Comments
 (0)