Skip to content

Commit

Permalink
feat: extending crypto support, fixes #142;
Browse files Browse the repository at this point in the history
  • Loading branch information
smansoft committed Jan 19, 2022
1 parent 2b6e9a5 commit eb762ea
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ private JSONObject generateKeySignature(Algorithm algorithm, Long expirationTime
break;
}
case ED: {
EdDSAParameterSpec edSpec = new EdDSAParameterSpec(signatureAlgorithm.getName());
EdDSAParameterSpec edSpec = new EdDSAParameterSpec(signatureAlgorithm.getCurve().getAlias());
keyGen = KeyPairGenerator.getInstance(signatureAlgorithm.getName(), "BC");
keyGen.initialize(edSpec, new SecureRandom());
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/**
*
*/
package io.jans.as.model.jwt;

import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;

import org.bouncycastle.jcajce.provider.asymmetric.edec.BCEdDSAPublicKey;
import org.json.JSONObject;

import io.jans.as.model.crypto.AbstractCryptoProvider;
import io.jans.as.model.crypto.signature.AlgorithmFamily;
import io.jans.as.model.crypto.signature.ECDSAPublicKey;
import io.jans.as.model.crypto.signature.EDDSAPublicKey;
import io.jans.as.model.crypto.signature.RSAPublicKey;
import io.jans.as.model.crypto.signature.SignatureAlgorithm;
import io.jans.as.model.exception.InvalidJwtException;
import io.jans.as.model.jws.ECDSASigner;
import io.jans.as.model.jws.EDDSASigner;
import io.jans.as.model.jws.HMACSigner;
import io.jans.as.model.jws.JwsSigner;
import io.jans.as.model.jws.PlainTextSignature;
import io.jans.as.model.jws.RSASigner;

/**
* Provides signature verification, using signature from JWT.
*
* @author Sergey Manoylo
* @version September 6, 2021
*/
public class JwtVerifier {

private AbstractCryptoProvider cryptoProvider;

private JSONObject jwks;

/**
* Constructor
*/
public JwtVerifier() {
}

/**
* Constructor.
*
* @param cryptoProvider crypto provider.
* @param jwks JSON Web Keys.
*/
public JwtVerifier(final AbstractCryptoProvider cryptoProvider, final JSONObject jwks) {
this.cryptoProvider = cryptoProvider;
this.jwks = jwks;
}

/**
* Verifying the input JWT (token).
*
* @param jwt input JWT (token).
* @param clientSecret client secret (is used by HMAC-family algorithms).
* @return Boolean result of the verification.
* @throws Exception
*/
public boolean verifyJwt(final Jwt jwt, final String clientSecret) throws Exception {

if (jwt == null) {
throw new InvalidJwtException("JwtVerifyer: jwt == null (jwt isn't defined)");
}

String signKeyId = jwt.getHeader().getKeyId();

SignatureAlgorithm signatureAlgorithm = jwt.getHeader().getSignatureAlgorithm();
if (signatureAlgorithm == null) {
throw new InvalidJwtException(
"JwtVerifyer: signatureAlgorithm == null (signatureAlgorithm isn't defined)");
}

final AlgorithmFamily algorithmFamily = signatureAlgorithm.getFamily();

PublicKey publicKey = getPublicKey(algorithmFamily, signKeyId);

JwsSigner signer = null;
switch (signatureAlgorithm.getFamily()) {
case NONE: {
signer = new PlainTextSignature();
break;
}
case HMAC: {
if (clientSecret == null) {
throw new InvalidJwtException("JwtVerifyer: clientSecret == null (clientSecret isn't defined)");
}
signer = new HMACSigner(signatureAlgorithm, clientSecret);
break;
}
case RSA: {
if(publicKey != null) {
java.security.interfaces.RSAPublicKey jrsaPublicKey = (java.security.interfaces.RSAPublicKey) publicKey;
RSAPublicKey rsaPublicKey = new RSAPublicKey(jrsaPublicKey.getModulus(), jrsaPublicKey.getPublicExponent());
signer = new RSASigner(signatureAlgorithm, rsaPublicKey);
}
break;
}
case EC: {
if(publicKey != null) {
ECPublicKey ecPublicKey = (ECPublicKey) publicKey;
ECDSAPublicKey ecdsaPublicKey = new ECDSAPublicKey(signatureAlgorithm, ecPublicKey.getW().getAffineX(), ecPublicKey.getW().getAffineY());
signer = new ECDSASigner(signatureAlgorithm, ecdsaPublicKey);
}
break;
}
case ED: {
if(publicKey != null) {
BCEdDSAPublicKey bceddsaPublicKey = (BCEdDSAPublicKey) publicKey;
EDDSAPublicKey eddsaPublicKey = new EDDSAPublicKey(signatureAlgorithm, bceddsaPublicKey.getEncoded());
signer = new EDDSASigner(signatureAlgorithm, eddsaPublicKey);
}
break;
}
default: {
break;
}
}

if (signer == null) {
throw new InvalidJwtException("JwtVerifyer: signer == null (signer isn't defined)");
}

return signer.validate(jwt);
}

/**
* Verifying the input JWT (token).
*
* @param jwt input JWT (token).
* @return Boolean result of the verification.
* @throws Exception
*/
public boolean verifyJwt(final Jwt jwt) throws Exception {
return verifyJwt(jwt, null);
}

/**
* Returns public key, only if AlgorithmFamily == RSA, EC, ED
* from jwks (JSON Web Keys).
*
* @param algorithmFamily input Algorithm Family.
* @param signKeyId Key ID.
* @return Public key.
* @throws Exception
*/
private PublicKey getPublicKey(final AlgorithmFamily algorithmFamily, final String signKeyId) throws Exception {
PublicKey publicKey = null;
if (AlgorithmFamily.RSA.equals(algorithmFamily) || AlgorithmFamily.EC.equals(algorithmFamily) || AlgorithmFamily.ED.equals(algorithmFamily)) {
if (signKeyId == null) {
throw new InvalidJwtException("JwtVerifyer: signKeyId == null (signKeyId isn't defined)");
}
publicKey = cryptoProvider.getPublicKey(signKeyId, jwks, null);
if (publicKey == null) {
throw new InvalidJwtException("JwtVerifyer: publicKey == null (publicKey isn't defined)");
}
}
return publicKey;
}
}
37 changes: 18 additions & 19 deletions jans-auth-server/server/src/test/resources/testng.properties
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,21 @@ keyStoreFile=${clientKeyStoreFile}
keyStoreSecret=${clientKeyStoreSecret}
jwksFile=${clientKeyJwksFile}
clientJwksUri=https://${test.server.name}/jans-auth-client/test/resources/jwks.json
RS256_keyId=b9d367de-1d0e-4d5a-81a2-9b9a6a8a0efb_sig_rs256
RS384_keyId=cce3f067-0303-48e8-a6cc-4c70c5e4570a_sig_rs384
RS512_keyId=8bab0875-e5e6-4d28-a58c-92d9c74e4beb_sig_rs512
ES256_keyId=85a911ec-0d89-4687-be58-f0c5854749b7_sig_es256
ES256K_keyId=eda7a7c8-c1ab-47ca-86f2-0131e1d2a9c3_sig_es256k
ES384_keyId=194f40fb-b2fb-40d0-a9d8-03538aa36390_sig_es384
ES512_keyId=396d7aca-a420-4bde-9b83-27f6a5828415_sig_es512
PS256_keyId=e980b9ca-655c-4717-9569-0c3044b57db0_sig_ps256
PS384_keyId=fea6f463-1260-4c5d-a0d0-c2060a695b05_sig_ps384
PS512_keyId=4d507c02-fbea-4f60-b5b0-691abf745523_sig_ps512
Ed25519_keyId=5cabcd33-21f1-473e-918c-5e2f02ed7b42_sig_ed25519
Ed448_keyId=92462b61-d7a1-493a-ae26-c2cb87149974_sig_ed448
RSA1_5_keyId=abf26816-6b84-4aa9-ba59-40fd568e5f03_enc_rsa1_5
RSA_OAEP_keyId=bb58a032-d144-415a-aac8-cd18da931b29_enc_rsa-oaep
RSA_OAEP_256_keyId=1acbbd79-a60f-4ba6-bac4-0efb1ad8fdbe_enc_rsa-oaep-256
ECDH_ES_keyId=01686710-811a-4fb0-9070-173e27947a48_enc_ecdh-es
ECDH_ES_PLUS_A128KW_keyId=e8b6d7e0-e812-4565-b8a0-d17731783cb3_enc_ecdh-es+a128kw
ECDH_ES_PLUS_A192KW_keyId=e5473bd1-4b5c-4f8f-934c-801eb5cc0827_enc_ecdh-es+a192kw
ECDH_ES_PLUS_A256KW_keyId=7bf50e8d-c44c-4e0a-9493-fd3d16b0d5ca_enc_ecdh-es+a256kw
RS256_keyId=98f362bc-b116-4fc3-aa96-01049ee6d18e_sig_rs256
RS384_keyId=7a4692ec-195c-4d36-be30-f28ddd81617f_sig_rs384
RS512_keyId=04be6c0c-31ef-4952-ad36-b42f0270449b_sig_rs512
ES256_keyId=8d6add6b-c055-4ac8-b2e6-cd708c5ee98c_sig_es256
ES256K_keyId=14f55073-91f6-4ca7-ae8d-c0c9c099ff66_sig_es256k
ES384_keyId=5850260b-673a-47a9-b8a6-ff42504a3f9f_sig_es384
ES512_keyId=b9f39abd-adb6-4fa4-a369-e53e852793fe_sig_es512
PS256_keyId=ca82d18a-a88e-4472-9873-b1c98ce8af34_sig_ps256
PS384_keyId=9d6f30f9-e8bf-4018-b773-2fb1ba192b10_sig_ps384
PS512_keyId=5a8da4ed-4fde-4edb-b55f-89a620139b94_sig_ps512
EdDSA_keyId=0d3a450a-015d-411d-a6bc-5ed3b78448ec_sig_eddsa
RSA1_5_keyId=47ee59ea-0e37-442f-9cd7-68b7570d9097_enc_rsa1_5
RSA_OAEP_keyId=61a6c2a7-2f2a-4174-ad8a-310f0c1c9470_enc_rsa-oaep
RSA_OAEP_256_keyId=cc64bc7b-b74b-44ad-889a-7621a90376bb_enc_rsa-oaep-256
ECDH_ES_keyId=27ef4cea-48f7-4c48-9848-01487aad7d4e_enc_ecdh-es
ECDH_ES_PLUS_A128KW_keyId=1116230b-eebd-4393-bfb1-5cb9cee8f2d7_enc_ecdh-es+a128kw
ECDH_ES_PLUS_A192KW_keyId=b7e05862-9364-4236-a79b-a5a7f09d137f_enc_ecdh-es+a192kw
ECDH_ES_PLUS_A256KW_keyId=9849f6f4-130c-4bac-837a-f002d00fe1c3_enc_ecdh-es+a256kw
6 changes: 6 additions & 0 deletions jans-auth-server/server/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@
</classes>
</test>

<test name="JWT signer-verifyer test" enabled="true">
<classes>
<class name="io.jans.as.server.comp.JwtSignerVerifyerTest" />
</classes>
</test>

<parameter name="serverUri" value="https://${test.server.name}" />
<parameter name="authorizePath" value="restv1/authorize" />
<parameter name="introspectionPath" value="restv1/introspection" />
Expand Down

0 comments on commit eb762ea

Please sign in to comment.