fix incorrect JWS implementation
This commit is contained in:
parent
d72bcebdf0
commit
0636cd898f
4 changed files with 99 additions and 27 deletions
|
@ -58,81 +58,148 @@ public class JWSBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String encode(Algorithm alg, byte[] data, byte[] signature) {
|
protected String encodeAll(StringBuffer encoding, byte[] signature) {
|
||||||
StringBuffer encoding = new StringBuffer();
|
|
||||||
encoding.append(encodeHeader(alg));
|
|
||||||
encoding.append('.');
|
encoding.append('.');
|
||||||
encoding.append(Base64Url.encode(data));
|
if (signature != null) {
|
||||||
encoding.append('.');
|
|
||||||
if (alg != Algorithm.none) {
|
|
||||||
encoding.append(Base64Url.encode(signature));
|
encoding.append(Base64Url.encode(signature));
|
||||||
}
|
}
|
||||||
return encoding.toString();
|
return encoding.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void encode(Algorithm alg, byte[] data, StringBuffer encoding) {
|
||||||
|
encoding.append(encodeHeader(alg));
|
||||||
|
encoding.append('.');
|
||||||
|
encoding.append(Base64Url.encode(data));
|
||||||
|
}
|
||||||
|
|
||||||
protected byte[] marshalContent() {
|
protected byte[] marshalContent() {
|
||||||
return contentBytes;
|
return contentBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EncodingBuilder {
|
public class EncodingBuilder {
|
||||||
public String none() {
|
public String none() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
return encode(Algorithm.none, data, null);
|
encode(Algorithm.none, data, buffer);
|
||||||
|
return encodeAll(buffer, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String rsa256(PrivateKey privateKey) {
|
public String rsa256(PrivateKey privateKey) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = RSAProvider.sign(data, Algorithm.RS256, privateKey);
|
encode(Algorithm.RS256, data, buffer);
|
||||||
return encode(Algorithm.RS256, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS256, privateKey);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String rsa384(PrivateKey privateKey) {
|
public String rsa384(PrivateKey privateKey) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = RSAProvider.sign(data, Algorithm.RS384, privateKey);
|
encode(Algorithm.RS384, data, buffer);
|
||||||
return encode(Algorithm.RS384, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS384, privateKey);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String rsa512(PrivateKey privateKey) {
|
public String rsa512(PrivateKey privateKey) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = RSAProvider.sign(data, Algorithm.RS512, privateKey);
|
encode(Algorithm.RS512, data, buffer);
|
||||||
return encode(Algorithm.RS512, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS512, privateKey);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String hmac256(byte[] sharedSecret) {
|
public String hmac256(byte[] sharedSecret) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS256, sharedSecret);
|
encode(Algorithm.HS256, data, buffer);
|
||||||
return encode(Algorithm.HS256, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String hmac384(byte[] sharedSecret) {
|
public String hmac384(byte[] sharedSecret) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS384, sharedSecret);
|
encode(Algorithm.HS384, data, buffer);
|
||||||
return encode(Algorithm.HS384, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String hmac512(byte[] sharedSecret) {
|
public String hmac512(byte[] sharedSecret) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS512, sharedSecret);
|
encode(Algorithm.HS512, data, buffer);
|
||||||
return encode(Algorithm.HS512, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String hmac256(SecretKey sharedSecret) {
|
public String hmac256(SecretKey sharedSecret) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS256, sharedSecret);
|
encode(Algorithm.HS256, data, buffer);
|
||||||
return encode(Algorithm.HS256, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String hmac384(SecretKey sharedSecret) {
|
public String hmac384(SecretKey sharedSecret) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS384, sharedSecret);
|
encode(Algorithm.HS384, data, buffer);
|
||||||
return encode(Algorithm.HS384, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String hmac512(SecretKey sharedSecret) {
|
public String hmac512(SecretKey sharedSecret) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] data = marshalContent();
|
byte[] data = marshalContent();
|
||||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS512, sharedSecret);
|
encode(Algorithm.HS512, data, buffer);
|
||||||
return encode(Algorithm.HS512, data, signature);
|
byte[] signature = null;
|
||||||
|
try {
|
||||||
|
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return encodeAll(buffer, signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ public class JWSInput {
|
||||||
String encodedHeader;
|
String encodedHeader;
|
||||||
String encodedContent;
|
String encodedContent;
|
||||||
String encodedSignature;
|
String encodedSignature;
|
||||||
|
String encodedSignatureInput;
|
||||||
JWSHeader header;
|
JWSHeader header;
|
||||||
byte[] content;
|
byte[] content;
|
||||||
byte[] signature;
|
byte[] signature;
|
||||||
|
@ -26,6 +27,7 @@ public class JWSInput {
|
||||||
if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
|
if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
|
||||||
encodedHeader = parts[0];
|
encodedHeader = parts[0];
|
||||||
encodedContent = parts[1];
|
encodedContent = parts[1];
|
||||||
|
encodedSignatureInput = encodedHeader + '.' + encodedContent;
|
||||||
try {
|
try {
|
||||||
content = Base64Url.decode(encodedContent);
|
content = Base64Url.decode(encodedContent);
|
||||||
if (parts.length > 2) {
|
if (parts.length > 2) {
|
||||||
|
@ -55,6 +57,9 @@ public class JWSInput {
|
||||||
public String getEncodedSignature() {
|
public String getEncodedSignature() {
|
||||||
return encodedSignature;
|
return encodedSignature;
|
||||||
}
|
}
|
||||||
|
public String getEncodedSignatureInput() {
|
||||||
|
return encodedSignatureInput;
|
||||||
|
}
|
||||||
|
|
||||||
public JWSHeader getHeader() {
|
public JWSHeader getHeader() {
|
||||||
return header;
|
return header;
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class HMACProvider {
|
||||||
|
|
||||||
public static boolean verify(JWSInput input, byte[] sharedSecret) {
|
public static boolean verify(JWSInput input, byte[] sharedSecret) {
|
||||||
try {
|
try {
|
||||||
byte[] signature = sign(input.getContent(), input.getHeader().getAlgorithm(), sharedSecret);
|
byte[] signature = sign(input.getEncodedSignatureInput().getBytes("UTF-8"), input.getHeader().getAlgorithm(), sharedSecret);
|
||||||
String x = Base64Url.encode(signature);
|
String x = Base64Url.encode(signature);
|
||||||
return x.equals(input.getEncodedSignature());
|
return x.equals(input.getEncodedSignature());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class RSAProvider {
|
||||||
try {
|
try {
|
||||||
Signature verifier = getSignature(input.getHeader().getAlgorithm());
|
Signature verifier = getSignature(input.getHeader().getAlgorithm());
|
||||||
verifier.initVerify(publicKey);
|
verifier.initVerify(publicKey);
|
||||||
verifier.update(input.getContent());
|
verifier.update(input.getEncodedSignatureInput().getBytes("UTF-8"));
|
||||||
return verifier.verify(input.getSignature());
|
return verifier.verify(input.getSignature());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|
Loading…
Reference in a new issue