All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.hiwepy.jwt.token.SignedWithHamcAndEncryptedWithRsaJWTRepository Maven / Gradle / Ivy

/*
 * Copyright (c) 2018, hiwepy (https://github.com/hiwepy).
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.github.hiwepy.jwt.token;

import java.text.ParseException;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.github.hiwepy.jwt.JwtPayload;
import com.github.hiwepy.jwt.exception.IncorrectJwtException;
import com.github.hiwepy.jwt.exception.InvalidJwtToken;
import com.github.hiwepy.jwt.exception.JwtException;
import com.github.hiwepy.jwt.time.JwtTimeProvider;
import com.github.hiwepy.jwt.utils.NimbusdsUtils;
import com.github.hiwepy.jwt.verifier.ExtendedMACVerifier;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEEncrypter;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.KeyLengthException;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jose.crypto.RSADecrypter;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

/**
 *  JSON Web Token (JWT) with HMAC signature and RSA encryption 
 * 

https://www.connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-hmac

*

https://www.connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-rsa-encryption

*

https://www.connect2id.com/products/nimbus-jose-jwt/examples/signed-and-encrypted-jwt

*/ public class SignedWithHamcAndEncryptedWithRsaJWTRepository implements JwtKeyPairRepository { private JwtTimeProvider timeProvider = JwtTimeProvider.DEFAULT_TIME_PROVIDER; /** * Issue JSON Web Token (JWT) * @author :hiwepy * @param signingKey : Signing key * @param secretKey : Encryption key * @param jwtId : Jwt Id * @param subject : Jwt Subject * @param issuer : Jwt Issuer * @param audience : Jwt Audience * @param roles : The Roles * @param permissions : The Perms * @param algorithm : Supported algorithms: *

HS256 - HMAC with SHA-256, requires 256+ bit secret

*

HS384 - HMAC with SHA-384, requires 384+ bit secret

*

HS512 - HMAC with SHA-512, requires 512+ bit secret

* @param period : Jwt Expiration Cycle * @return JSON Web Token (JWT) * @throws JwtException When Authentication Exception */ @Override public String issueJwt(String signingKey, RSAKey secretKey, String jwtId, String subject, String issuer, String audience, String roles, String permissions, String algorithm, long period) throws JwtException { Map claims = new HashMap(); claims.put("roles", roles); claims.put("perms", permissions); return this.issueJwt(signingKey, secretKey, jwtId, subject, issuer, audience, claims, algorithm, period); } /** * Issue JSON Web Token (JWT) * @author :hiwepy * @param signingKey : Signing key * @param secretKey : Encryption key * @param jwtId : Jwt Id * @param subject : Jwt Subject * @param issuer : Jwt Issuer * @param audience : Jwt Audience * @param claims : Jwt Claims * @param algorithm : Supported algorithms: *

HS256 - HMAC with SHA-256, requires 256+ bit secret

*

HS384 - HMAC with SHA-384, requires 384+ bit secret

*

HS512 - HMAC with SHA-512, requires 512+ bit secret

* @param period : Jwt Expiration Cycle * @return JSON Web Token (JWT) * @throws JwtException When Authentication Exception */ @Override public String issueJwt(String signingKey, RSAKey secretKey, String jwtId, String subject, String issuer, String audience, Map claims, String algorithm, long period) throws JwtException { try { //-------------------- Step 1:Get ClaimsSet -------------------- // Prepare JWT with claims set JWTClaimsSet.Builder builder = NimbusdsUtils.claimsSet(jwtId, subject, issuer, audience, claims, period); // 签发时间 long currentTimeMillis = this.getTimeProvider().now(); Date now = new Date(currentTimeMillis); builder.issueTime(now); // 有效期起始时间 builder.notBeforeTime(now); // Token过期时间 if (period >= 0) { // 有效时间 Date expiration = new Date(currentTimeMillis + period ); builder.expirationTime(expiration); } JWTClaimsSet claimsSet = builder.build(); //-------------------- Step 2:Hamc Signature -------------------- // Request JWS Header with HMAC JWSAlgorithm JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.parse(algorithm)); SignedJWT signedJWT = new SignedJWT(jwsHeader, claimsSet); // Create HMAC signer byte[] secret = Base64.getDecoder().decode(signingKey); JWSSigner signer = new MACSigner(secret); // Compute the HMAC signature signedJWT.sign(signer); //-------------------- Step 3:RSA Encrypt ---------------------- // Request JWT encrypted with RSA-OAEP-256 and 256-bit AES/GCM JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM); // Create JWE object with signed JWT as payload JWEObject jweObject = new JWEObject( jweHeader, new Payload(signedJWT)); // Create an encrypter with the specified public RSA key JWEEncrypter encrypter = new RSAEncrypter(secretKey.toPublicJWK()); // Do the actual encryption jweObject.encrypt(encrypter); // Serialise to JWE compact form return jweObject.serialize(); } catch (IllegalStateException e) { throw new IncorrectJwtException(e); } catch (KeyLengthException e) { throw new IncorrectJwtException(e); } catch (JOSEException e) { throw new IncorrectJwtException(e); } } /** * Verify the validity of JWT * @author : hiwepy * @param signingKey : *

If the jws was signed with a SecretKey, the same SecretKey should be specified on the JwtParser.

*

If the jws was signed with a PrivateKey, that key's corresponding PublicKey (not the PrivateKey) should be specified on the JwtParser.

* @param secretKey : *

If the jws was encrypted with a SecretKey, the same SecretKey should be specified on the JwtParser.

*

If the jws was encrypted with a PrivateKey, that key's corresponding PublicKey (not the PrivateKey) should be specified on the JwtParser.

* @param token : JSON Web Token (JWT) * @param checkExpiry : If Check validity. * @return If Validity * @throws JwtException When Authentication Exception */ @Override public boolean verify(String signingKey, RSAKey secretKey, String token, boolean checkExpiry) throws JwtException { try { //-------------------- Step 1:RSA Decrypt ---------------------- // Parse the JWE string JWEObject jweObject = JWEObject.parse(token); // Decrypt with private key jweObject.decrypt(new RSADecrypter(secretKey)); // Extract payload SignedJWT signedJWT = jweObject.getPayload().toSignedJWT(); //-------------------- Step 2:Hamc Verify -------------------- // Create HMAC verifier byte[] secret = Base64.getDecoder().decode(signingKey); JWSVerifier verifier = checkExpiry ? new ExtendedMACVerifier(secret, signedJWT.getJWTClaimsSet(), this.getTimeProvider()) : new MACVerifier(secret) ; // Retrieve / verify the JWT claims according to the app requirements return signedJWT.verify(verifier); } catch (IllegalStateException e) { throw new IncorrectJwtException(e); } catch (NumberFormatException e) { throw new IncorrectJwtException(e); } catch (ParseException e) { throw new IncorrectJwtException(e); } catch (JOSEException e) { throw new InvalidJwtToken(e); } } /** * Parser JSON Web Token (JWT) * @author :hiwepy * @param signingKey : *

If the jws was signed with a SecretKey, the same SecretKey should be specified on the JwtParser.

*

If the jws was signed with a PrivateKey, that key's corresponding PublicKey (not the PrivateKey) should be specified on the JwtParser.

* @param secretKey : *

If the jws was encrypted with a SecretKey, the same SecretKey should be specified on the JwtParser.

*

If the jws was encrypted with a PrivateKey, that key's corresponding PublicKey (not the PrivateKey) should be specified on the JwtParser.

* @param token : JSON Web Token (JWT) * @param checkExpiry : If Check validity. * @return JwtPlayload {@link JwtPayload} * @throws JwtException When Authentication Exception */ @Override public JwtPayload getPlayload(String signingKey, RSAKey secretKey, String token, boolean checkExpiry) throws JwtException { try { //-------------------- Step 1:RSA Decrypt ---------------------- // Parse the JWE string JWEObject jweObject = JWEObject.parse(token); // Decrypt with private key jweObject.decrypt(new RSADecrypter(secretKey)); // Extract payload SignedJWT signedJWT = jweObject.getPayload().toSignedJWT(); //-------------------- Step 2:Hamc Verify -------------------- // Create HMAC verifier byte[] secret = Base64.getDecoder().decode(signingKey); JWSVerifier verifier = checkExpiry ? new ExtendedMACVerifier(secret, signedJWT.getJWTClaimsSet(), this.getTimeProvider()) : new MACVerifier(secret) ; // Retrieve / verify the JWT claims according to the app requirements if(!signedJWT.verify(verifier)) { throw new JwtException(String.format("Invalid JSON Web Token (JWT) : %s", token)); } //-------------------- Step 3:Gets The Claims --------------- // Retrieve JWT claims return NimbusdsUtils.payload(signedJWT.getJWTClaimsSet()); } catch (IllegalStateException e) { throw new IncorrectJwtException(e); } catch (NumberFormatException e) { throw new IncorrectJwtException(e); } catch (ParseException e) { throw new IncorrectJwtException(e); } catch (JOSEException e) { throw new InvalidJwtToken(e); } } public JwtTimeProvider getTimeProvider() { return timeProvider; } public void setTimeProvider(JwtTimeProvider timeProvider) { this.timeProvider = timeProvider; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy