Skip to content

Commit 1b28a97

Browse files
committed
feat: Support for 'kid' and JCS in JWT format.
1 parent 7677642 commit 1b28a97

File tree

1 file changed

+60
-27
lines changed

1 file changed

+60
-27
lines changed

src/main/java/com/danubetech/verifiablecredentials/jwt/JwtObject.java

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import info.weboftrust.ldsignatures.adapter.JWSSignerAdapter;
1010
import info.weboftrust.ldsignatures.adapter.JWSVerifierAdapter;
1111
import org.bitcoinj.core.ECKey;
12+
import org.erdtman.jcs.JsonCanonicalizer;
1213

14+
import java.io.IOException;
1315
import java.security.interfaces.RSAPrivateKey;
1416
import java.security.interfaces.RSAPublicKey;
1517
import java.util.Map;
@@ -33,10 +35,15 @@ public JwtObject(JWTClaimsSet payload, JWSObject jwsObject, String compactSerial
3335
* Sign
3436
*/
3537

36-
private String sign(JWSSigner jwsSigner, JWSAlgorithm alg) throws JOSEException {
38+
private String sign(JWSSigner jwsSigner, JWSAlgorithm alg, String kid, boolean canonicalize) throws JOSEException {
3739

38-
JWSHeader jwsHeader = new JWSHeader.Builder(alg).build();
39-
JWSObject jwsObject = new EscapedSlashWorkaroundJWSObject(jwsHeader, this.getPayload());
40+
JWSHeader.Builder jwsHeaderBuilder = new JWSHeader.Builder(alg);
41+
jwsHeaderBuilder.type(JOSEObjectType.JWT);
42+
if (kid != null) jwsHeaderBuilder.keyID(kid);
43+
44+
JWSHeader jwsHeader = jwsHeaderBuilder.build();
45+
46+
JWSObject jwsObject = new EscapedSlashWorkaroundJWSObject(jwsHeader, this.getPayload(), canonicalize);
4047

4148
jwsObject.sign(jwsSigner);
4249

@@ -46,102 +53,119 @@ private String sign(JWSSigner jwsSigner, JWSAlgorithm alg) throws JOSEException
4653
return this.compactSerialization;
4754
}
4855

56+
public String sign_RSA_RS256(ByteSigner signer, String kid, boolean canonicalize) throws JOSEException {
57+
return this.sign(new JWSSignerAdapter(signer, JWSAlgorithm.RS256), JWSAlgorithm.RS256, kid, canonicalize);
58+
}
59+
4960
public String sign_RSA_RS256(ByteSigner signer) throws JOSEException {
61+
return this.sign_RSA_RS256(signer, null, true);
62+
}
5063

51-
return this.sign(new JWSSignerAdapter(signer, JWSAlgorithm.RS256), JWSAlgorithm.RS256);
64+
public String sign_RSA_RS256(RSAPrivateKey privateKey, String kid, boolean canonicalize) throws JOSEException {
65+
return this.sign_RSA_RS256(new RSA_RS256_PrivateKeySigner(privateKey), kid, canonicalize);
5266
}
5367

5468
public String sign_RSA_RS256(RSAPrivateKey privateKey) throws JOSEException {
69+
return this.sign_RSA_RS256(privateKey, null, true);
70+
}
5571

56-
return this.sign_RSA_RS256(new RSA_RS256_PrivateKeySigner(privateKey));
72+
public String sign_RSA_RS256(com.nimbusds.jose.jwk.RSAKey privateKey, String kid, boolean canonicalize) throws JOSEException {
73+
return this.sign(new com.nimbusds.jose.crypto.RSASSASigner(privateKey), JWSAlgorithm.RS256, kid, canonicalize);
5774
}
5875

5976
public String sign_RSA_RS256(com.nimbusds.jose.jwk.RSAKey privateKey) throws JOSEException {
77+
return this.sign_RSA_RS256(privateKey, null, true);
78+
}
6079

61-
return this.sign(new com.nimbusds.jose.crypto.RSASSASigner(privateKey), JWSAlgorithm.RS256);
80+
public String sign_Ed25519_EdDSA(ByteSigner signer, String kid, boolean canonicalize) throws JOSEException {
81+
return this.sign(new JWSSignerAdapter(signer, JWSAlgorithm.EdDSA), JWSAlgorithm.EdDSA, kid, canonicalize);
6282
}
6383

6484
public String sign_Ed25519_EdDSA(ByteSigner signer) throws JOSEException {
85+
return this.sign_Ed25519_EdDSA(signer, null, true);
86+
}
6587

66-
return this.sign(new JWSSignerAdapter(signer, JWSAlgorithm.EdDSA), JWSAlgorithm.EdDSA);
88+
public String sign_Ed25519_EdDSA(byte[] privateKey, String kid, boolean canonicalize) throws JOSEException {
89+
return this.sign_Ed25519_EdDSA(new Ed25519_EdDSA_PrivateKeySigner(privateKey), kid, canonicalize);
6790
}
6891

6992
public String sign_Ed25519_EdDSA(byte[] privateKey) throws JOSEException {
93+
return this.sign_Ed25519_EdDSA(privateKey, null, true);
94+
}
7095

71-
return this.sign_Ed25519_EdDSA(new Ed25519_EdDSA_PrivateKeySigner(privateKey));
96+
public String sign_Ed25519_EdDSA(com.nimbusds.jose.jwk.OctetKeyPair privateKey, String kid, boolean canonicalize) throws JOSEException {
97+
return this.sign(new com.nimbusds.jose.crypto.Ed25519Signer(privateKey), JWSAlgorithm.EdDSA, kid, canonicalize);
7298
}
7399

74100
public String sign_Ed25519_EdDSA(com.nimbusds.jose.jwk.OctetKeyPair privateKey) throws JOSEException {
101+
return this.sign_Ed25519_EdDSA(privateKey, null, true);
102+
}
75103

76-
return this.sign(new com.nimbusds.jose.crypto.Ed25519Signer(privateKey), JWSAlgorithm.EdDSA);
104+
public String sign_secp256k1_ES256K(ByteSigner signer, String kid, boolean canonicalize) throws JOSEException {
105+
return this.sign(new JWSSignerAdapter(signer, JWSAlgorithm.ES256K), JWSAlgorithm.ES256K, kid, canonicalize);
77106
}
78107

79108
public String sign_secp256k1_ES256K(ByteSigner signer) throws JOSEException {
109+
return this.sign_secp256k1_ES256K(signer, null, true);
110+
}
80111

81-
return this.sign(new JWSSignerAdapter(signer, JWSAlgorithm.ES256K), JWSAlgorithm.ES256K);
112+
public String sign_secp256k1_ES256K(ECKey privateKey, String kid, boolean canonicalize) throws JOSEException {
113+
return this.sign_secp256k1_ES256K(new secp256k1_ES256K_PrivateKeySigner(privateKey));
82114
}
83115

84116
public String sign_secp256k1_ES256K(ECKey privateKey) throws JOSEException {
117+
return this.sign_secp256k1_ES256K(privateKey, null, true);
118+
}
85119

86-
return this.sign_secp256k1_ES256K(new secp256k1_ES256K_PrivateKeySigner(privateKey));
120+
public String sign_secp256k1_ES256K(com.nimbusds.jose.jwk.ECKey privateKey, String kid, boolean canonicalize) throws JOSEException {
121+
return this.sign(new com.nimbusds.jose.crypto.ECDSASigner(privateKey), JWSAlgorithm.ES256K, kid, canonicalize);
87122
}
88123

89124
public String sign_secp256k1_ES256K(com.nimbusds.jose.jwk.ECKey privateKey) throws JOSEException {
90-
91-
return this.sign(new com.nimbusds.jose.crypto.ECDSASigner(privateKey), JWSAlgorithm.ES256K);
125+
return this.sign_secp256k1_ES256K(privateKey, null, true);
92126
}
93127

94128
/*
95129
* Verify
96130
*/
97131

98132
private boolean verify(JWSVerifier jwsVerifier) throws JOSEException {
99-
100133
return this.jwsObject.verify(jwsVerifier);
101134
}
102135

103136
public boolean verify_RSA_RS256(ByteVerifier verifier) throws JOSEException {
104-
105137
return this.verify(new JWSVerifierAdapter(verifier, JWSAlgorithm.RS256));
106138
}
107139

108140
public boolean verify_RSA_RS256(RSAPublicKey publicKey) throws JOSEException {
109-
110141
return this.verify_RSA_RS256(new RSA_RS256_PublicKeyVerifier(publicKey));
111142
}
112143

113144
public boolean verify_RSA_RS256(com.nimbusds.jose.jwk.RSAKey publicKey) throws JOSEException {
114-
115145
return this.verify(new com.nimbusds.jose.crypto.RSASSAVerifier(publicKey));
116146
}
117147

118148
public boolean verify_Ed25519_EdDSA(ByteVerifier verifier) throws JOSEException {
119-
120149
return this.verify(new JWSVerifierAdapter(verifier, JWSAlgorithm.EdDSA));
121150
}
122151

123152
public boolean verify_Ed25519_EdDSA(byte[] publicKey) throws JOSEException {
124-
125153
return this.verify_Ed25519_EdDSA(new Ed25519_EdDSA_PublicKeyVerifier(publicKey));
126154
}
127155

128156
public boolean verify_Ed25519_EdDSA(com.nimbusds.jose.jwk.OctetKeyPair publicKey) throws JOSEException {
129-
130157
return this.verify(new com.nimbusds.jose.crypto.Ed25519Verifier(publicKey));
131158
}
132159

133160
public boolean verify_secp256k1_ES256K(ByteVerifier verifier) throws JOSEException {
134-
135161
return this.verify(new JWSVerifierAdapter(verifier, JWSAlgorithm.ES256K));
136162
}
137163

138164
public boolean verify_secp256k1_ES256K(ECKey publicKey) throws JOSEException {
139-
140165
return this.verify_secp256k1_ES256K(new secp256k1_ES256K_PublicKeyVerifier(publicKey));
141166
}
142167

143168
public boolean verify_secp256k1_ES256K(com.nimbusds.jose.jwk.ECKey publicKey) throws JOSEException {
144-
145169
return this.verify(new com.nimbusds.jose.crypto.ECDSAVerifier(publicKey));
146170
}
147171

@@ -153,13 +177,22 @@ private static class EscapedSlashWorkaroundJWSObject extends JWSObject {
153177

154178
private static final long serialVersionUID = -587898962717783109L;
155179

156-
public EscapedSlashWorkaroundJWSObject(final JWSHeader jwsHeader, final JWTClaimsSet jwtClaimsSet) {
157-
super(jwsHeader, makePayload(jwtClaimsSet));
180+
public EscapedSlashWorkaroundJWSObject(final JWSHeader jwsHeader, final JWTClaimsSet jwtClaimsSet, boolean canonicalize) {
181+
super(jwsHeader, makePayload(jwtClaimsSet, canonicalize));
158182
}
159183

160-
private static Payload makePayload(JWTClaimsSet jwtClaimsSet) {
184+
private static Payload makePayload(JWTClaimsSet jwtClaimsSet, boolean canonicalize) {
161185
Map<String, Object> jsonObject = jwtClaimsSet.toJSONObject();
162-
return new Payload(JSONObjectUtils.toJSONString(jsonObject).replace("\\/", "/"));
186+
String payloadString = JSONObjectUtils.toJSONString(jsonObject);
187+
if (canonicalize) {
188+
try {
189+
payloadString = new JsonCanonicalizer(payloadString).getEncodedString();
190+
} catch (IOException ex) {
191+
throw new IllegalArgumentException(ex.getMessage(), ex);
192+
}
193+
}
194+
payloadString = payloadString.replace("\\/", "/");
195+
return new Payload(payloadString);
163196
}
164197
}
165198

0 commit comments

Comments
 (0)