token加密——RSA加密

RSA加密工具類

RsaUtils.java
package com.hahashujia.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA加密解密
 * @author yanan.wang
 * @describe
 * @createTime 2020-04-01 16:04
 */
@Slf4j
public class RsaUtils {

    private static final String KEY_ALGORITHM = "RSA";
    private static final int RSA_KEY_SIZE = 512;

    public static void main(String[] args) throws Exception {
        genKeyPair();

    }

    /**
     * 私鑰加密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
        //private key
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 公鑰加密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 私鑰解密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {

        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 公鑰解密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 隨機生成密鑰對
     *
     * @throws NoSuchAlgorithmException
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        //KeyPairGenerator類用於生成公鑰和私鑰對,基於RSA算法生成對象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化密鑰對生成器,密鑰大小爲96-1024位
        keyPairGen.initialize(RSA_KEY_SIZE, new SecureRandom());
        // 生成一個密鑰對,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到私鑰
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 得到公鑰
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到私鑰字符串
        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
        // 將公鑰和私鑰保存到Map
        log.info("公鑰加密Key:{}", publicKeyString);
        log.info("私鑰解密Key:{}", privateKeyString);
        Map<String, String> keyMap = new HashMap<>();
        keyMap.put("publicKey", publicKeyString);
        keyMap.put("publicKey", privateKeyString);

    }
}

TokenService.java
 

package com.hahashujia.service;

import com.hahashujia.utils.RsaUtils;
import com.hahashujia.dao.ImpTokenHistoryDao;
import com.hahashujia.dao.entity.ImpTokenHistory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * EBS的Token加密/解密
 * 公鑰加密/私鑰解密
 *
 * @author yanan.wang
 * @describe
 * @createTime 2020-03-13 15:52
 */
@Component
@Slf4j
public class TokenService {

    @Value("${token.rsa.private_key}")
    private String ebsPrivateKey;
    @Value("${token.rsa.public_key}")
    private String ebsPublicKey;

    @Autowired
    private ImpTokenHistoryDao impTokenHistoryDao;

    /**
     * 獲得加密字符串,加密字符不得超過53個字節</p>
     * 需加密字符串:{sysCode}+時間戳+10位隨機數</p>
     * 加密方式:RSA+BASE64Encoder</p>
     * 時間戳:13字節
     * 隨機數:10字節
     *
     * @param sysCode :系統CODE:最多30字節
     * @return
     * @throws Exception
     */
    public String encryptionToken(String sysCode) {
        String encodeStr = null;
        try {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(sysCode)
                    .append(System.currentTimeMillis())
                    .append(randomNumber());
            log.info("原文:{}, 長度:{}", stringBuffer.toString(), stringBuffer.length());

            byte[] inputData = stringBuffer.toString().getBytes();
            log.info("字節長度:{}", inputData.length);
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] publicKey = base64Decoder.decodeBuffer(ebsPublicKey);
            byte[] encodeData = RsaUtils.encryptByPublicKey(inputData, publicKey);

            BASE64Encoder base64 = new BASE64Encoder();
            encodeStr = base64.encode(encodeData);

            log.info("公鑰加密後:{}", encodeStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encodeStr;
    }


    /**
     * check the existing token and insert a new token.
     * 私鑰解密
     *
     * @param token
     * @return
     * @throws Exception
     */
    public boolean validateToken(String token, String sysCode) {

        try {
            log.info("Token verification start.");
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] tokenByte = base64Decoder.decodeBuffer(token);
            byte[] privateKey = base64Decoder.decodeBuffer(ebsPrivateKey);
            byte[] decodeData = RsaUtils.decryptByPrivateKey(tokenByte, privateKey);
            String result = new String(decodeData);

            if (result.startsWith(sysCode)) {
                String str = result.substring(sysCode.length());
                long currentTime = Long.parseLong(str.substring(0, 13));
                if (checkTime(currentTime)) {
                    //查看token是否在數據庫存在
                    int existTask = impTokenHistoryDao.checkToken(token);
                    if (existTask == 0) {
                        impTokenHistoryDao.insert(ImpTokenHistory.builder()
                                .token(token)
                                .systemCode(sysCode)
                                .build());
                        log.info("Token verification passed.");
                        return Boolean.TRUE;
                    } else {
                        log.error("Token has expired. Reason : Token already exists in database. "
                                        + "token :{}, sysCode:{}, decrypt token:{}",
                                token, sysCode, result);
                    }

                } else {
                    log.error("Token has expired. Reason : Over 30 minutes. token :{}, sysCode:{}, decrypt token:{}",
                            token, sysCode, result);
                }
            } else {
                log.error("Token error. Reason : Incorrect token fixed component."
                                + " token :{}, sysCode:{}, decrypt token:{}",
                        token, sysCode, result);
            }

        } catch (Exception e) {
            log.error("Token error or expired.", e);
        }
        return Boolean.FALSE;

    }

    /**
     * 10位隨機數
     *
     * @return
     */
    private long randomNumber() {
        double temp = Math.random();
        return (long) (temp * 10000000000L);
    }

    /**
     * 校驗時間戳是否是30分鐘之內
     *
     * @param time
     * @return 30分鐘之內返回true
     */
    private boolean checkTime(long time) {
        long currentTime = System.currentTimeMillis();
        currentTime = currentTime - 1800000;

        if (time > currentTime) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

}

Controller層調用
 

    @ApiOperation(value = "接口描述(帶token)")
    @RequestMapping(value = "token", method = RequestMethod.POST)
    public ResponseEntity token(
            @RequestHeader(name = "token") String token) {

        if (!tokenService.validateToken(token, systemCode)) {
            return ResponseEntity.badRequest().body("Token error or expired.");
        }
        return ResponseEntity.ok().build();
    }

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章