diff --git a/inspector-vc/pom.xml b/inspector-vc/pom.xml
index 396f3d5..f253160 100644
--- a/inspector-vc/pom.xml
+++ b/inspector-vc/pom.xml
@@ -11,10 +11,10 @@
org.1edtech
inspector-core
-
+
org.bouncycastle
- bcpkix-jdk15on
- 1.58
+ bcprov-jdk15to18
+ 1.65
com.auth0
diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java
index da95e80..d68c7e8 100644
--- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java
+++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java
@@ -114,9 +114,12 @@ public class OB30Inspector extends VCInspector {
}
//verify proofs TODO @Miles
- probeCount++;
- accumulator.add(new ProofVerifierProbe().run(crd, ctx));
- if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
+ //If this credential was not contained in a jwt it must have an internal proof.
+ if(isNullOrEmpty(crd.getJwt())){
+ probeCount++;
+ accumulator.add(new ProofVerifierProbe().run(crd, ctx));
+ if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
+ }
//check refresh service if we are not already refreshed
probeCount++;
diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java
index e506aec..1618148 100644
--- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java
+++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java
@@ -1,5 +1,15 @@
package org.oneedtech.inspect.vc.probe;
+import java.security.KeyFactory;
+import java.security.Security;
+import java.security.Signature;
+import java.security.spec.X509EncodedKeySpec;
+
+import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
import org.oneedtech.inspect.core.probe.Probe;
import org.oneedtech.inspect.core.probe.RunContext;
import org.oneedtech.inspect.core.report.ReportItems;
@@ -23,5 +33,22 @@ public class ProofVerifierProbe extends Probe {
return success(ctx);
}
+ public boolean validate(String pubkey, String signature, String timestamp, String message) throws Exception {
+ //TODO: continue this implementation.
+ //Pulled in bouncy castle library and made sure this sample compiled only.
+ final var provider = new BouncyCastleProvider();
+ Security.addProvider(provider);
+ final var byteKey = Hex.decode(pubkey);
+ final var pki = new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), byteKey);
+ final var pkSpec = new X509EncodedKeySpec(pki.getEncoded());
+ final var kf = KeyFactory.getInstance("ed25519", provider);
+ final var publicKey = kf.generatePublic(pkSpec);
+ final var signedData = Signature.getInstance("ed25519", provider);
+ signedData.initVerify(publicKey);
+ signedData.update(timestamp.getBytes());
+ signedData.update(message.getBytes());
+ return signedData.verify(Hex.decode(signature));
+ }
+
public static final String ID = ProofVerifierProbe.class.getSimpleName();
}
diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/SignatureVerifierProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/SignatureVerifierProbe.java
index 91f4f64..e8c06ae 100644
--- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/SignatureVerifierProbe.java
+++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/SignatureVerifierProbe.java
@@ -21,6 +21,10 @@ import org.springframework.util.Base64Utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.AlgorithmMismatchException;
+import com.auth0.jwt.exceptions.InvalidClaimException;
+import com.auth0.jwt.exceptions.SignatureVerificationException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -39,7 +43,7 @@ public class SignatureVerifierProbe extends Probe {
@Override
public ReportItems run(Credential crd, RunContext ctx) throws Exception {
try {
- testingSignatureValidationCode(crd);
+ verifySignature(crd);
} catch (Exception e) {
return fatal("Error verifying jwt signature: " + e.getMessage(), ctx);
}
@@ -47,7 +51,7 @@ public class SignatureVerifierProbe extends Probe {
return success(ctx);
}
- private void testingSignatureValidationCode(Credential crd) throws Exception {
+ private void verifySignature(Credential crd) throws Exception {
DecodedJWT decodedJwt = null;
String jwt = crd.getJwt();
if(isNullOrEmpty(jwt)) throw new IllegalArgumentException("invalid jwt");
@@ -90,7 +94,21 @@ public class SignatureVerifierProbe extends Probe {
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey)pub, null);
JWTVerifier verifier = JWT.require(algorithm)
.build(); //Reusable verifier instance
- decodedJwt = verifier.verify(jwt);
+ try {
+ decodedJwt = verifier.verify(jwt);
+ }
+ catch(SignatureVerificationException ex){
+ throw new Exception("JWT Invalid signature", ex);
+ }
+ catch(AlgorithmMismatchException ex){
+ throw new Exception("JWT Algorithm mismatch", ex);
+ }
+ catch(TokenExpiredException ex){
+ throw new Exception("JWT Token expired", ex);
+ }
+ catch(InvalidClaimException ex){
+ throw new Exception("JWT, one or more claims are invalid", ex);
+ }
}
public static final String ID = SignatureVerifierProbe.class.getSimpleName();