JWT asymmetric encryption public-private key encryption and decryption can set the expiration time [JwtHelper of Spring security framework] [Jwts of jsonwebtoken.JJWT]

Posted by climbjm on Sun, 20 Feb 2022 07:55:20 +0100

introduce

Recently, I want to develop a coder management platform. For the technical selection of login module, I chose JWT
Jwt can ensure that the login information placed on the client is not tampered with.
In order to be more secure, I use RSA asymmetric encryption. That is, the private key is used to generate Jwt, and the public key is used to verify Jwt.

problem

At first, I wanted to use spring's security framework, because it contains JWT, Bcrypt and other contents, and using JwtHelper class, I can easily generate JWT with private key and decrypt public key.
But after searching the whole network, I couldn't find the method of JwtHelper to set the expiration time of Jwt.
One blogger said that iat and exp data can be added manually in the load. But after testing, it still can't.
Finally, I decided to use Jwts for encryption and decryption

Encryption and decryption of JWT

The code provides encryption and decryption of Jwts and JwtHelper

Step 1: generate key

Generated through keyTool (certificate management tool provided by java)
This tool is available as long as JDK is installed. You can enter keytool in cmd interface to check whether there is such a tool.
If:

'keytool' is not an internal or external command, nor is it a runnable program or batch file.


You can enter the jdk installation directory. Under the bin folder, there is keytool Exe file.
At this time, enter cmd in the address bar and press enter to open the cmd window here.

Execute the following command:

// The following instructions are one line. Setting multiple lines is convenient for reading
keytool -genkeypair 
-alias key alias  
-keyalg Algorithm used 
-keypass Key access password 
-keystore Generated keystore file name, extension is jks
-storepass The access password of the keystore, which is used to open jks file


After entering the information, you can generate jks files in the current directory.

Step 2: export public key

For microservices, the private key is placed on the authentication service, and other services only need to store the public key. Because other services only perform verification and do not encrypt JWT
You can export the key through openssl, that is, the public key or private key in string format
openssl needs to be installed, Click here Jump Download
After installation, add environment variables:

Execute the following command:

keytool -list -rfc --keystore jks file(Include extension.jks) | openssl x509 -inform pem -pubkey


Copy the contents of ----- BEGIN PUBLIC KEY ----- and ----- END PUBLIC KEY -----, create a new file and store it.
Generally, create public key

Put it into the resource directory of the project

Step 3: encrypt JWT

	/**
     * Generate JWT token based on private key
     *
     * @author Eugenema
     * @date 2022/2/19 17:49
     *
     * @param userInfo User information
     *
     * @return Encrypted JWT
     **/
    public String createJWT(UserInfo userInfo){
        //load
        Map<String,Object> payload = new HashMap<>(2);
        payload.put("id", userInfo.getId());
        payload.put("userName",userInfo.getName());

		/** Private key: under the resource directory */
        ClassPathResource keyFileResource = new ClassPathResource("emPerson.jks");
        //Create a secret key factory. The parameters are: secret key file, secret key library password
        //import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
        //pom file:
        /**
        <dependency>
      		<groupId>org.springframework.security</groupId>
      		<artifactId>spring-security-rsa</artifactId>
      		<version>1.0.11.RELEASE</version>
    	</dependency>
    	*/
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(keyFileResource, "Keystore password password".toCharArray());
        //Obtain the secret key. The parameters are: alias, secret key and password
        KeyPair keyContent = keyStoreKeyFactory.getKeyPair("alias alias", "Password of secret key".toCharArray());
        /** Private key */
        PrivateKey privateKey = keyContent.getPrivate();

        //Generate JWT through JwtHelper
        //Deprecated because the expiration time cannot be set
//        Jwt jwtContent = JwtHelper.encode(JSON.toJSONString(payload), new RsaSigner(privateKey));
//        String jwtEncoded = jwtContent.getEncoded();
//        System.out.println(jwtEncoded);

		//Generate JWT through Jwts
		//pom file:
		/**
		<dependency>
      		<groupId>io.jsonwebtoken</groupId>
      		<artifactId>jjwt</artifactId>
      		<version>0.9.0</version>
    	</dependency>
		*/
        JwtBuilder eugeneMa = Jwts.builder()
        		//Set load
        		.addClaims(payload)
        		//Setting ID is said to prevent replay attacks
                .setId(String.valueOf(System.currentTimeMillis()))
                //set up themes
                .setSubject("eugeneMa")
                //Set issuing time
                .setIssuedAt(new Date())
                //Set expiration time
                .setExpiration(new Date(System.currentTimeMillis() + 30000))
                //Set encryption algorithm and private key
                .signWith(SignatureAlgorithm.RS256, privateKey);
        //Return to JWT
		return eugeneMa.compact();
    }

Step 4: decrypt JWT

	/**
     * Parsing JWT
     *
     * @author Eugenema
     * @date 2022/2/19 18:47
     *
     * @param jwt JWT to decrypt
     *
     * @return jwt after parsing
     **/
    public String parseJwt(String jwt){
    	//Parsing through JwtHelper
    	//Jwt token = JwtHelper.decodeAndVerify(jwt, new RsaVerifier(getPubKey));
    	//return token.getClaims();
    	
		//Parsing through Jwts
		Jws<Claims> claimsJws = Jwts.parser().setSigningKey(getPubKey()).parseClaimsJws(jwt);
		return claimJws.getBody();
    }

	/**
     * Get public key
     *
     * @author Eugenema
     * @date 2022/2/19 19:01
     *
     * @return Public key. If the acquisition fails, null will be returned
     **/
    private static PublicKey getPubKey() {
    	//Point to the public key file in the resource directory
        Resource publicKey = new ClassPathResource("public.key");
        try {
            InputStreamReader publicKeyIs = new InputStreamReader(publicKey.getInputStream());
            BufferedReader publicKeyBr = new BufferedReader(publicKeyIs);
            StringBuilder publicKeySb = new StringBuilder();
            String line;
            //Change multiple lines in the file to one line
            while ((line = publicKeyBr.readLine()) != null) {
                publicKeySb.append(line);
            }
			
			//Convert String to java PublicKey object
            byte[] byteKey = Base64.getDecoder().decode(publicKeySb.toString());
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (Exception e) {
            logger.error("Get public key exception!", e);
            return null;
        }
    }

Topics: Java Spring security jwt