mirror of https://github.com/jwtk/jjwt.git
Cleanup as per request of https://github.com/lhazlewood
This commit is contained in:
parent
c60deebb64
commit
61510dfca5
5
pom.xml
5
pom.xml
|
@ -307,11 +307,6 @@
|
||||||
<lineRate>100</lineRate>
|
<lineRate>100</lineRate>
|
||||||
<branchRate>90</branchRate>
|
<branchRate>90</branchRate>
|
||||||
</regex>
|
</regex>
|
||||||
<regex>
|
|
||||||
<pattern>io.jsonwebtoken.impl.crypto.ECDSA</pattern>
|
|
||||||
<lineRate>80</lineRate>
|
|
||||||
<branchRate>60</branchRate>
|
|
||||||
</regex>
|
|
||||||
</regexes>
|
</regexes>
|
||||||
</check>
|
</check>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -1,177 +0,0 @@
|
||||||
package io.jsonwebtoken.impl.crypto;
|
|
||||||
|
|
||||||
|
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.lang.JOSEException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Elliptic Curve Digital Signature Algorithm (ECDSA) functions and utilities.
|
|
||||||
*/
|
|
||||||
public class ECDSA {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the expected signature byte array length (R + S parts) for
|
|
||||||
* the specified ECDSA algorithm.
|
|
||||||
*
|
|
||||||
* @param alg The ECDSA algorithm. Must be supported and not
|
|
||||||
* {@code null}.
|
|
||||||
*
|
|
||||||
* @return The expected byte array length for the signature.
|
|
||||||
*
|
|
||||||
* @throws JOSEException If the algorithm is not supported.
|
|
||||||
*/
|
|
||||||
public static int getSignatureByteArrayLength(final SignatureAlgorithm alg)
|
|
||||||
throws JOSEException {
|
|
||||||
|
|
||||||
switch (alg) {
|
|
||||||
case ES256: return 64;
|
|
||||||
case ES384: return 96;
|
|
||||||
case ES512: return 132;
|
|
||||||
default:
|
|
||||||
throw new JOSEException("unsupported algorithm: " + alg.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transcodes the JCA ASN.1/DER-encoded signature into the concatenated
|
|
||||||
* R + S format expected by ECDSA JWS.
|
|
||||||
*
|
|
||||||
* @param derSignature The ASN1./DER-encoded. Must not be {@code null}.
|
|
||||||
* @param outputLength The expected length of the ECDSA JWS signature.
|
|
||||||
*
|
|
||||||
* @return The ECDSA JWS encoded signature.
|
|
||||||
*
|
|
||||||
* @throws JOSEException If the ASN.1/DER signature format is invalid.
|
|
||||||
*/
|
|
||||||
public static byte[] transcodeSignatureToConcat(final byte[] derSignature, int outputLength)
|
|
||||||
throws JOSEException {
|
|
||||||
|
|
||||||
if (derSignature.length < 8 || derSignature[0] != 48) {
|
|
||||||
throw new JOSEException("Invalid ECDSA signature format");
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset;
|
|
||||||
if (derSignature[1] > 0) {
|
|
||||||
offset = 2;
|
|
||||||
} else if (derSignature[1] == (byte) 0x81) {
|
|
||||||
offset = 3;
|
|
||||||
} else {
|
|
||||||
throw new JOSEException("Invalid ECDSA signature format");
|
|
||||||
}
|
|
||||||
|
|
||||||
byte rLength = derSignature[offset + 1];
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = rLength; (i > 0) && (derSignature[(offset + 2 + rLength) - i] == 0); i--) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
byte sLength = derSignature[offset + 2 + rLength + 1];
|
|
||||||
|
|
||||||
int j;
|
|
||||||
for (j = sLength; (j > 0) && (derSignature[(offset + 2 + rLength + 2 + sLength) - j] == 0); j--) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
int rawLen = Math.max(i, j);
|
|
||||||
rawLen = Math.max(rawLen, outputLength / 2);
|
|
||||||
|
|
||||||
if ((derSignature[offset - 1] & 0xff) != derSignature.length - offset
|
|
||||||
|| (derSignature[offset - 1] & 0xff) != 2 + rLength + 2 + sLength
|
|
||||||
|| derSignature[offset] != 2
|
|
||||||
|| derSignature[offset + 2 + rLength] != 2) {
|
|
||||||
throw new JOSEException("Invalid ECDSA signature format");
|
|
||||||
}
|
|
||||||
|
|
||||||
final byte[] concatSignature = new byte[2 * rawLen];
|
|
||||||
|
|
||||||
System.arraycopy(derSignature, (offset + 2 + rLength) - i, concatSignature, rawLen - i, i);
|
|
||||||
System.arraycopy(derSignature, (offset + 2 + rLength + 2 + sLength) - j, concatSignature, 2 * rawLen - j, j);
|
|
||||||
|
|
||||||
return concatSignature;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transcodes the ECDSA JWS signature into ASN.1/DER format for use by
|
|
||||||
* the JCA verifier.
|
|
||||||
*
|
|
||||||
* @param jwsSignature The JWS signature, consisting of the
|
|
||||||
* concatenated R and S values. Must not be
|
|
||||||
* {@code null}.
|
|
||||||
*
|
|
||||||
* @return The ASN.1/DER encoded signature.
|
|
||||||
*
|
|
||||||
* @throws JOSEException If the ECDSA JWS signature format is invalid.
|
|
||||||
*/
|
|
||||||
public static byte[] transcodeSignatureToDER(byte[] jwsSignature)
|
|
||||||
throws JOSEException {
|
|
||||||
|
|
||||||
int rawLen = jwsSignature.length / 2;
|
|
||||||
|
|
||||||
int i = rawLen;
|
|
||||||
|
|
||||||
while((i > 0) && (jwsSignature[rawLen - i] == 0)) i--;
|
|
||||||
|
|
||||||
int j = i;
|
|
||||||
|
|
||||||
if (jwsSignature[rawLen - i] < 0) {
|
|
||||||
j += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int k = rawLen;
|
|
||||||
|
|
||||||
while ((k > 0) && (jwsSignature[2 * rawLen - k] == 0)) k--;
|
|
||||||
|
|
||||||
int l = k;
|
|
||||||
|
|
||||||
if (jwsSignature[2 * rawLen - k] < 0) {
|
|
||||||
l += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int len = 2 + j + 2 + l;
|
|
||||||
|
|
||||||
if (len > 255) {
|
|
||||||
throw new JOSEException("Invalid ECDSA signature format");
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset;
|
|
||||||
|
|
||||||
final byte derSignature[];
|
|
||||||
|
|
||||||
if (len < 128) {
|
|
||||||
derSignature = new byte[2 + 2 + j + 2 + l];
|
|
||||||
offset = 1;
|
|
||||||
} else {
|
|
||||||
derSignature = new byte[3 + 2 + j + 2 + l];
|
|
||||||
derSignature[1] = (byte) 0x81;
|
|
||||||
offset = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
derSignature[0] = 48;
|
|
||||||
derSignature[offset++] = (byte) len;
|
|
||||||
derSignature[offset++] = 2;
|
|
||||||
derSignature[offset++] = (byte) j;
|
|
||||||
|
|
||||||
System.arraycopy(jwsSignature, rawLen - i, derSignature, (offset + j) - i, i);
|
|
||||||
|
|
||||||
offset += j;
|
|
||||||
|
|
||||||
derSignature[offset++] = 2;
|
|
||||||
derSignature[offset++] = (byte) l;
|
|
||||||
|
|
||||||
System.arraycopy(jwsSignature, 2 * rawLen - k, derSignature, (offset + l) - k, k);
|
|
||||||
|
|
||||||
return derSignature;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevents public instantiation.
|
|
||||||
*/
|
|
||||||
private ECDSA() {}
|
|
||||||
}
|
|
|
@ -15,9 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package io.jsonwebtoken.impl.crypto;
|
package io.jsonwebtoken.impl.crypto;
|
||||||
|
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.lang.Assert;
|
|
||||||
|
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
|
@ -25,6 +22,10 @@ import java.security.SecureRandom;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.JwtException;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.lang.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ElliptiCurve crypto provider.
|
* ElliptiCurve crypto provider.
|
||||||
*
|
*
|
||||||
|
@ -135,4 +136,166 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
throw new IllegalStateException("Unable to generate Elliptic Curve KeyPair: " + e.getMessage(), e);
|
throw new IllegalStateException("Unable to generate Elliptic Curve KeyPair: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the expected signature byte array length (R + S parts) for
|
||||||
|
* the specified ECDSA algorithm.
|
||||||
|
*
|
||||||
|
* @param alg The ECDSA algorithm. Must be supported and not
|
||||||
|
* {@code null}.
|
||||||
|
*
|
||||||
|
* @return The expected byte array length for the signature.
|
||||||
|
*
|
||||||
|
* @throws JwtException If the algorithm is not supported.
|
||||||
|
*/
|
||||||
|
public static int getSignatureByteArrayLength(final SignatureAlgorithm alg)
|
||||||
|
throws JwtException {
|
||||||
|
|
||||||
|
switch (alg) {
|
||||||
|
case ES256: return 64;
|
||||||
|
case ES384: return 96;
|
||||||
|
case ES512: return 132;
|
||||||
|
default:
|
||||||
|
throw new JwtException("Unsupported Algorithm: " + alg.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transcodes the JCA ASN.1/DER-encoded signature into the concatenated
|
||||||
|
* R + S format expected by ECDSA JWS.
|
||||||
|
*
|
||||||
|
* @param derSignature The ASN1./DER-encoded. Must not be {@code null}.
|
||||||
|
* @param outputLength The expected length of the ECDSA JWS signature.
|
||||||
|
*
|
||||||
|
* @return The ECDSA JWS encoded signature.
|
||||||
|
*
|
||||||
|
* @throws JwtException If the ASN.1/DER signature format is invalid.
|
||||||
|
*/
|
||||||
|
public static byte[] transcodeSignatureToConcat(final byte[] derSignature, int outputLength)
|
||||||
|
throws JwtException {
|
||||||
|
|
||||||
|
if (derSignature.length < 8 || derSignature[0] != 48) {
|
||||||
|
throw new JwtException("Invalid ECDSA signature format");
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset;
|
||||||
|
if (derSignature[1] > 0) {
|
||||||
|
offset = 2;
|
||||||
|
} else if (derSignature[1] == (byte) 0x81) {
|
||||||
|
offset = 3;
|
||||||
|
} else {
|
||||||
|
throw new JwtException("Invalid ECDSA signature format");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte rLength = derSignature[offset + 1];
|
||||||
|
|
||||||
|
int i = rLength;
|
||||||
|
while ((i > 0)
|
||||||
|
&& (derSignature[(offset + 2 + rLength) - i] == 0))
|
||||||
|
i--;
|
||||||
|
|
||||||
|
byte sLength = derSignature[offset + 2 + rLength + 1];
|
||||||
|
|
||||||
|
int j = sLength;
|
||||||
|
while ((j > 0)
|
||||||
|
&& (derSignature[(offset + 2 + rLength + 2 + sLength) - j] == 0))
|
||||||
|
j--;
|
||||||
|
|
||||||
|
int rawLen = Math.max(i, j);
|
||||||
|
rawLen = Math.max(rawLen, outputLength / 2);
|
||||||
|
|
||||||
|
if ((derSignature[offset - 1] & 0xff) != derSignature.length - offset
|
||||||
|
|| (derSignature[offset - 1] & 0xff) != 2 + rLength + 2 + sLength
|
||||||
|
|| derSignature[offset] != 2
|
||||||
|
|| derSignature[offset + 2 + rLength] != 2) {
|
||||||
|
throw new JwtException("Invalid ECDSA signature format");
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte[] concatSignature = new byte[2 * rawLen];
|
||||||
|
|
||||||
|
System.arraycopy(derSignature, (offset + 2 + rLength) - i, concatSignature, rawLen - i, i);
|
||||||
|
System.arraycopy(derSignature, (offset + 2 + rLength + 2 + sLength) - j, concatSignature, 2 * rawLen - j, j);
|
||||||
|
|
||||||
|
return concatSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transcodes the ECDSA JWS signature into ASN.1/DER format for use by
|
||||||
|
* the JCA verifier.
|
||||||
|
*
|
||||||
|
* @param jwsSignature The JWS signature, consisting of the
|
||||||
|
* concatenated R and S values. Must not be
|
||||||
|
* {@code null}.
|
||||||
|
*
|
||||||
|
* @return The ASN.1/DER encoded signature.
|
||||||
|
*
|
||||||
|
* @throws JwtException If the ECDSA JWS signature format is invalid.
|
||||||
|
*/
|
||||||
|
public static byte[] transcodeSignatureToDER(byte[] jwsSignature)
|
||||||
|
throws JwtException {
|
||||||
|
|
||||||
|
int rawLen = jwsSignature.length / 2;
|
||||||
|
|
||||||
|
int i = rawLen;
|
||||||
|
|
||||||
|
while((i > 0)
|
||||||
|
&& (jwsSignature[rawLen - i] == 0))
|
||||||
|
i--;
|
||||||
|
|
||||||
|
int j = i;
|
||||||
|
|
||||||
|
if (jwsSignature[rawLen - i] < 0) {
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k = rawLen;
|
||||||
|
|
||||||
|
while ((k > 0)
|
||||||
|
&& (jwsSignature[2 * rawLen - k] == 0))
|
||||||
|
k--;
|
||||||
|
|
||||||
|
int l = k;
|
||||||
|
|
||||||
|
if (jwsSignature[2 * rawLen - k] < 0) {
|
||||||
|
l += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = 2 + j + 2 + l;
|
||||||
|
|
||||||
|
if (len > 255) {
|
||||||
|
throw new JwtException("Invalid ECDSA signature format");
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
final byte derSignature[];
|
||||||
|
|
||||||
|
if (len < 128) {
|
||||||
|
derSignature = new byte[2 + 2 + j + 2 + l];
|
||||||
|
offset = 1;
|
||||||
|
} else {
|
||||||
|
derSignature = new byte[3 + 2 + j + 2 + l];
|
||||||
|
derSignature[1] = (byte) 0x81;
|
||||||
|
offset = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
derSignature[0] = 48;
|
||||||
|
derSignature[offset++] = (byte) len;
|
||||||
|
derSignature[offset++] = 2;
|
||||||
|
derSignature[offset++] = (byte) j;
|
||||||
|
|
||||||
|
System.arraycopy(jwsSignature, rawLen - i, derSignature, (offset + j) - i, i);
|
||||||
|
|
||||||
|
offset += j;
|
||||||
|
|
||||||
|
derSignature[offset++] = 2;
|
||||||
|
derSignature[offset++] = (byte) l;
|
||||||
|
|
||||||
|
System.arraycopy(jwsSignature, 2 * rawLen - k, derSignature, (offset + l) - k, k);
|
||||||
|
|
||||||
|
return derSignature;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,9 @@ public class EllipticCurveSignatureValidator extends EllipticCurveProvider imple
|
||||||
Signature sig = createSignatureInstance();
|
Signature sig = createSignatureInstance();
|
||||||
PublicKey publicKey = (PublicKey) key;
|
PublicKey publicKey = (PublicKey) key;
|
||||||
try {
|
try {
|
||||||
byte[] derSignature = ECDSA.transcodeSignatureToDER(signature);
|
int expectedSize = getSignatureByteArrayLength(alg);
|
||||||
|
//if the expected size is not valid for JOSE, fall back to ASN.1 DER signature
|
||||||
|
byte[] derSignature = expectedSize != signature.length && signature[0] == 0x30 ? signature : EllipticCurveProvider.transcodeSignatureToDER(signature);
|
||||||
return doVerify(sig, publicKey, data, derSignature);
|
return doVerify(sig, publicKey, data, derSignature);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = "Unable to verify Elliptic Curve signature using configured ECPublicKey. " + e.getMessage();
|
String msg = "Unable to verify Elliptic Curve signature using configured ECPublicKey. " + e.getMessage();
|
||||||
|
|
|
@ -21,9 +21,9 @@ import java.security.PrivateKey;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
import java.security.interfaces.ECPrivateKey;
|
import java.security.interfaces.ECPrivateKey;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.JwtException;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
import io.jsonwebtoken.SignatureException;
|
import io.jsonwebtoken.SignatureException;
|
||||||
import io.jsonwebtoken.lang.JOSEException;
|
|
||||||
|
|
||||||
public class EllipticCurveSigner extends EllipticCurveProvider implements Signer {
|
public class EllipticCurveSigner extends EllipticCurveProvider implements Signer {
|
||||||
|
|
||||||
|
@ -44,16 +44,16 @@ public class EllipticCurveSigner extends EllipticCurveProvider implements Signer
|
||||||
throw new SignatureException("Invalid Elliptic Curve PrivateKey. " + e.getMessage(), e);
|
throw new SignatureException("Invalid Elliptic Curve PrivateKey. " + e.getMessage(), e);
|
||||||
} catch (java.security.SignatureException e) {
|
} catch (java.security.SignatureException e) {
|
||||||
throw new SignatureException("Unable to calculate signature using Elliptic Curve PrivateKey. " + e.getMessage(), e);
|
throw new SignatureException("Unable to calculate signature using Elliptic Curve PrivateKey. " + e.getMessage(), e);
|
||||||
} catch (JOSEException e) {
|
} catch (JwtException e) {
|
||||||
throw new SignatureException("Unable to convert signature to JOSE format. " + e.getMessage(), e);
|
throw new SignatureException("Unable to convert signature to JOSE format. " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] doSign(byte[] data) throws InvalidKeyException, java.security.SignatureException, JOSEException {
|
protected byte[] doSign(byte[] data) throws InvalidKeyException, java.security.SignatureException, JwtException {
|
||||||
PrivateKey privateKey = (PrivateKey)key;
|
PrivateKey privateKey = (PrivateKey)key;
|
||||||
Signature sig = createSignatureInstance();
|
Signature sig = createSignatureInstance();
|
||||||
sig.initSign(privateKey);
|
sig.initSign(privateKey);
|
||||||
sig.update(data);
|
sig.update(data);
|
||||||
return ECDSA.transcodeSignatureToConcat(sig.sign(), ECDSA.getSignatureByteArrayLength(alg));
|
return transcodeSignatureToConcat(sig.sign(), getSignatureByteArrayLength(alg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package io.jsonwebtoken.impl.crypto;
|
package io.jsonwebtoken.impl.crypto;
|
||||||
|
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.SignatureException;
|
|
||||||
import io.jsonwebtoken.lang.Assert;
|
|
||||||
import io.jsonwebtoken.lang.RuntimeEnvironment;
|
|
||||||
|
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.SignatureException;
|
||||||
|
import io.jsonwebtoken.lang.Assert;
|
||||||
|
import io.jsonwebtoken.lang.RuntimeEnvironment;
|
||||||
|
|
||||||
abstract class SignatureProvider {
|
abstract class SignatureProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
package io.jsonwebtoken.lang;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Javascript Object Signing and Encryption (JOSE) exception.
|
|
||||||
*/
|
|
||||||
public class JOSEException extends Exception {
|
|
||||||
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new JOSE exception with the specified message.
|
|
||||||
*
|
|
||||||
* @param message The exception message.
|
|
||||||
*/
|
|
||||||
public JOSEException(final String message) {
|
|
||||||
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package io.jsonwebtoken.impl.crypto
|
package io.jsonwebtoken.impl.crypto
|
||||||
|
|
||||||
|
import io.jsonwebtoken.JwtException
|
||||||
import io.jsonwebtoken.SignatureAlgorithm
|
import io.jsonwebtoken.SignatureAlgorithm
|
||||||
import io.jsonwebtoken.SignatureException
|
import io.jsonwebtoken.SignatureException
|
||||||
import io.jsonwebtoken.impl.TextCodec
|
import io.jsonwebtoken.impl.TextCodec
|
||||||
|
@ -76,4 +77,113 @@ class EllipticCurveSignatureValidatorTest {
|
||||||
//Test verification for token created using https://github.com/jwt/ruby-jwt/tree/v1.5.4
|
//Test verification for token created using https://github.com/jwt/ruby-jwt/tree/v1.5.4
|
||||||
verifier("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJ0ZXN0IjoidGVzdCJ9.AV26tERbSEwcoDGshneZmhokg-tAKUk0uQBoHBohveEd51D5f6EIs6cskkgwtfzs4qAGfx2rYxqQXr7LTXCNquKiAJNkTIKVddbPfped3_TQtmHZTmMNiqmWjiFj7Y9eTPMMRRu26w4gD1a8EQcBF-7UGgeH4L_1CwHJWAXGbtu7uMUn")
|
verifier("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJ0ZXN0IjoidGVzdCJ9.AV26tERbSEwcoDGshneZmhokg-tAKUk0uQBoHBohveEd51D5f6EIs6cskkgwtfzs4qAGfx2rYxqQXr7LTXCNquKiAJNkTIKVddbPfped3_TQtmHZTmMNiqmWjiFj7Y9eTPMMRRu26w4gD1a8EQcBF-7UGgeH4L_1CwHJWAXGbtu7uMUn")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void legacySignatureCompatTest() {
|
||||||
|
def withoutSignature = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCIsImlhdCI6MTQ2NzA2NTgyN30"
|
||||||
|
def keypair = EllipticCurveProvider.generateKeyPair()
|
||||||
|
def signature = Signature.getInstance(SignatureAlgorithm.ES512.jcaName, "BC")
|
||||||
|
def data = withoutSignature.getBytes("US-ASCII")
|
||||||
|
signature.initSign(keypair.private)
|
||||||
|
signature.update(data)
|
||||||
|
def signed = signature.sign()
|
||||||
|
assert new EllipticCurveSignatureValidator(SignatureAlgorithm.ES512, keypair.public).isValid(data, signed)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void invalidAlgorithmTest() {
|
||||||
|
def invalidAlgorithm = SignatureAlgorithm.HS256
|
||||||
|
try {
|
||||||
|
EllipticCurveProvider.getSignatureByteArrayLength(invalidAlgorithm)
|
||||||
|
fail()
|
||||||
|
} catch (JwtException e) {
|
||||||
|
assertEquals e.message, 'Unsupported Algorithm: ' + invalidAlgorithm.name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void invalidECDSASignatureFormatTest() {
|
||||||
|
try {
|
||||||
|
def signature = new byte[257]
|
||||||
|
SignatureProvider.DEFAULT_SECURE_RANDOM.nextBytes(signature)
|
||||||
|
EllipticCurveProvider.transcodeSignatureToDER(signature)
|
||||||
|
fail()
|
||||||
|
} catch (JwtException e) {
|
||||||
|
assertEquals e.message, 'Invalid ECDSA signature format'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void invalidDERSignatureToJoseFormatTest() {
|
||||||
|
def verify = { signature ->
|
||||||
|
try {
|
||||||
|
EllipticCurveProvider.transcodeSignatureToConcat(signature, 132)
|
||||||
|
fail()
|
||||||
|
} catch (JwtException e) {
|
||||||
|
assertEquals e.message, 'Invalid ECDSA signature format'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def signature = new byte[257]
|
||||||
|
SignatureProvider.DEFAULT_SECURE_RANDOM.nextBytes(signature)
|
||||||
|
//invalid type
|
||||||
|
signature[0] = 34
|
||||||
|
verify(signature)
|
||||||
|
def shortSignature = new byte[7]
|
||||||
|
SignatureProvider.DEFAULT_SECURE_RANDOM.nextBytes(shortSignature)
|
||||||
|
verify(shortSignature)
|
||||||
|
signature[0] = 48
|
||||||
|
// signature[1] = 0x81
|
||||||
|
signature[1] = -10
|
||||||
|
verify(signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void edgeCaseSignatureLengthTest() {
|
||||||
|
def signature = new byte[1]
|
||||||
|
EllipticCurveProvider.transcodeSignatureToDER(signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void edgeCaseSignatureToConcatLengthTest() {
|
||||||
|
try {
|
||||||
|
def signature = TextCodec.BASE64.decode("MIEAAGg3OVb/ZeX12cYrhK3c07TsMKo7Kc6SiqW++4CAZWCX72DkZPGTdCv2duqlupsnZL53hiG3rfdOLj8drndCU+KHGrn5EotCATdMSLCXJSMMJoHMM/ZPG+QOHHPlOWnAvpC1v4lJb32WxMFNz1VAIWrl9Aa6RPG1GcjCTScKjvEE")
|
||||||
|
EllipticCurveProvider.transcodeSignatureToConcat(signature, 132)
|
||||||
|
fail()
|
||||||
|
} catch (JwtException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void edgeCaseSignatureToConcatInvalidSignatureTest() {
|
||||||
|
try {
|
||||||
|
def signature = TextCodec.BASE64.decode("MIGBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
||||||
|
EllipticCurveProvider.transcodeSignatureToConcat(signature, 132)
|
||||||
|
fail()
|
||||||
|
} catch (JwtException e) {
|
||||||
|
assertEquals e.message, 'Invalid ECDSA signature format'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void edgeCaseSignatureToConcatInvalidSignatureBranchTest() {
|
||||||
|
try {
|
||||||
|
def signature = TextCodec.BASE64.decode("MIGBAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
||||||
|
EllipticCurveProvider.transcodeSignatureToConcat(signature, 132)
|
||||||
|
fail()
|
||||||
|
} catch (JwtException e) {
|
||||||
|
assertEquals e.message, 'Invalid ECDSA signature format'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void edgeCaseSignatureToConcatInvalidSignatureBranch2Test() {
|
||||||
|
try {
|
||||||
|
def signature = TextCodec.BASE64.decode("MIGBAj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
||||||
|
EllipticCurveProvider.transcodeSignatureToConcat(signature, 132)
|
||||||
|
fail()
|
||||||
|
} catch (JwtException e) {
|
||||||
|
assertEquals e.message, 'Invalid ECDSA signature format'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package io.jsonwebtoken.impl.crypto
|
package io.jsonwebtoken.impl.crypto
|
||||||
|
|
||||||
|
import io.jsonwebtoken.JwtException
|
||||||
import io.jsonwebtoken.SignatureAlgorithm
|
import io.jsonwebtoken.SignatureAlgorithm
|
||||||
import io.jsonwebtoken.SignatureException
|
import io.jsonwebtoken.SignatureException
|
||||||
import io.jsonwebtoken.lang.JOSEException
|
import org.junit.Test
|
||||||
|
|
||||||
import java.security.InvalidKeyException
|
import java.security.InvalidKeyException
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PrivateKey
|
import java.security.PrivateKey
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import static org.junit.Assert.*
|
import static org.junit.Assert.*
|
||||||
|
|
||||||
class EllipticCurveSignerTest {
|
class EllipticCurveSignerTest {
|
||||||
|
@ -88,11 +88,11 @@ class EllipticCurveSignerTest {
|
||||||
PrivateKey privateKey = kp.getPrivate();
|
PrivateKey privateKey = kp.getPrivate();
|
||||||
|
|
||||||
String msg = 'foo'
|
String msg = 'foo'
|
||||||
final JOSEException ex = new JOSEException(msg)
|
final JwtException ex = new JwtException(msg)
|
||||||
|
|
||||||
def signer = new EllipticCurveSigner(SignatureAlgorithm.ES256, privateKey) {
|
def signer = new EllipticCurveSigner(SignatureAlgorithm.ES256, privateKey) {
|
||||||
@Override
|
@Override
|
||||||
protected byte[] doSign(byte[] data) throws InvalidKeyException, java.security.SignatureException, JOSEException {
|
protected byte[] doSign(byte[] data) throws InvalidKeyException, java.security.SignatureException, JwtException {
|
||||||
throw ex
|
throw ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue