Skip to content

Commit 72704dd

Browse files
committed
convert signature to DER format (java expects this)
1 parent 54d5897 commit 72704dd

2 files changed

Lines changed: 69 additions & 4 deletions

File tree

lib/src/main/java/com/auth0/jwtdecodejava/algorithms/Algorithm.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public static Algorithm HMAC512(String secret) {
7979
* @return a valid ECDSA256 Algorithm.
8080
*/
8181
public static Algorithm ECDSA256(PublicKey publicKey) {
82-
return new ECDSAAlgorithm("ES256", "SHA256withECDSA", publicKey);
82+
return new ECDSAAlgorithm("ES256", "SHA256withECDSA", 32, publicKey);
8383
}
8484

8585
/**
@@ -89,7 +89,7 @@ public static Algorithm ECDSA256(PublicKey publicKey) {
8989
* @return a valid ECDSA384 Algorithm.
9090
*/
9191
public static Algorithm ECDSA384(PublicKey publicKey) {
92-
return new ECDSAAlgorithm("ES384", "SHA384withECDSA", publicKey);
92+
return new ECDSAAlgorithm("ES384", "SHA384withECDSA", 48, publicKey);
9393
}
9494

9595
/**
@@ -99,7 +99,7 @@ public static Algorithm ECDSA384(PublicKey publicKey) {
9999
* @return a valid ECDSA512 Algorithm.
100100
*/
101101
public static Algorithm ECDSA512(PublicKey publicKey) {
102-
return new ECDSAAlgorithm("ES512", "SHA512withECDSA", publicKey);
102+
return new ECDSAAlgorithm("ES512", "SHA512withECDSA", 66, publicKey);
103103
}
104104

105105
public static Algorithm none() {

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

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77

88
class ECDSAAlgorithm extends Algorithm {
99

10+
private final int ecNumberSize;
1011
private final PublicKey publicKey;
1112

12-
ECDSAAlgorithm(String id, String algorithm, PublicKey publicKey) {
13+
ECDSAAlgorithm(String id, String algorithm, int ecNumberSize, PublicKey publicKey) {
1314
super(id, algorithm);
1415
if (publicKey == null) {
1516
throw new IllegalArgumentException("The PublicKey cannot be null");
1617
}
18+
this.ecNumberSize = ecNumberSize;
1719
this.publicKey = publicKey;
1820
}
1921

@@ -29,6 +31,9 @@ public void verify(String[] jwtParts) throws SignatureVerificationException {
2931
s.initVerify(publicKey);
3032
s.update(content.getBytes());
3133
byte[] signature = Base64.decodeBase64(jwtParts[2]);
34+
if (isJOSESignature(signature)) {
35+
signature = JOSEToDER(signature);
36+
}
3237
boolean valid = s.verify(signature);
3338
if (!valid) {
3439
throw new SignatureVerificationException(this);
@@ -38,4 +43,64 @@ public void verify(String[] jwtParts) throws SignatureVerificationException {
3843
}
3944
}
4045

46+
private boolean isJOSESignature(byte[] signature) {
47+
//TODO: Check if the signature has JOSE format.
48+
return true;
49+
}
50+
51+
private byte[] JOSEToDER(byte[] joseSignature) throws SignatureException {
52+
if (joseSignature.length != ecNumberSize * 2) {
53+
throw new SignatureException(String.format("The signature length was invalid. Expected %d bytes but received %d", ecNumberSize * 2, joseSignature.length));
54+
}
55+
56+
// Retrieve R and S number's length and padding.
57+
int rPadding = countPadding(joseSignature, 0, ecNumberSize);
58+
int sPadding = countPadding(joseSignature, ecNumberSize, joseSignature.length);
59+
int rLength = ecNumberSize - rPadding;
60+
int sLength = ecNumberSize - sPadding;
61+
62+
int length = 2 + rLength + 2 + sLength;
63+
if (length > 0xFF) {
64+
throw new SignatureException("Invalid ECDSA signature format");
65+
}
66+
67+
byte[] derSignature;
68+
int offset;
69+
if (length > 0x7f) {
70+
derSignature = new byte[3 + length];
71+
derSignature[1] = (byte) 0x81;
72+
offset = 2;
73+
} else {
74+
derSignature = new byte[2 + length];
75+
offset = 1;
76+
}
77+
78+
// DER Structure: http://crypto.stackexchange.com/a/1797
79+
// Header with length info
80+
derSignature[0] = (byte) 0x30;
81+
derSignature[offset++] = (byte) length;
82+
derSignature[offset++] = (byte) 0x02;
83+
derSignature[offset++] = (byte) rLength;
84+
85+
// R number
86+
System.arraycopy(joseSignature, 0, derSignature, offset + (rLength - ecNumberSize), ecNumberSize);
87+
offset += rLength;
88+
89+
// S number length
90+
derSignature[offset++] = (byte) 0x02;
91+
derSignature[offset++] = (byte) sLength;
92+
93+
// S number
94+
System.arraycopy(joseSignature, ecNumberSize, derSignature, offset + (sLength - ecNumberSize), ecNumberSize);
95+
96+
return derSignature;
97+
}
98+
99+
private int countPadding(byte[] bytes, int fromIndex, int toIndex) {
100+
int padding = 0;
101+
while (fromIndex + padding < toIndex && bytes[fromIndex + padding] == 0) {
102+
padding++;
103+
}
104+
return bytes[fromIndex + padding] > 0x7f ? padding : padding - 1;
105+
}
41106
}

0 commit comments

Comments
 (0)