请注意这里是加签验签,如有加密解密需求的,还请移步

JDK中JCA的简单使用(三)---RSA加密解密

Signature 类

Signature类是一个引擎类,提供加密的数字签名算法,例如DSA或RSAwithMD5。加密安全签名算法采用任意大小的输入和私钥,并生成一个相对较短(通常是固定大小)的字节串——签名。

  • 只有私钥/公钥对的所有者才能创建签名。对于拥有公钥的任何人来说,恢复私钥在计算上是不可行的。
  • 用于生成签名的私钥相对应的公钥,可以验证输入的真实性和完整性。
  • 签名和公钥不会泄露有关私钥的任何信息。

简而言之,
1.创建一对Key:私钥&公钥。
2.使用私钥创建签名
3.使用公钥对数据的真实性进行校验。

值得注意的是,Signature算法目的并不在于对原数据加密,而是使用原数据和私钥/公钥生成签名,验签时,使用公钥/私钥,签名,原数据进行校验。

应用场景:用于需要使用这份数据,又不能确定接收数据的可靠性。

使用流程:

1.获取公私钥对,代码如下:

/**
     * 获取公私钥对
     *
     * @return
     */
    private static Map<String, String> getKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator generator = null;
        generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化秘钥size,最小为512
        generator.initialize(1024);
        KeyPair keyPair = generator.generateKeyPair();
        String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        Map<String, String> keyMap = new HashMap<>();
        keyMap.put(PRIVATE_KEY, privateKey);
        keyMap.put(PUBLIC_KEY, publicKey);
        return keyMap;
    }

2.使用私钥对数据进行加签,获得签名字符串,代码如下:

/**
     * 根据私钥加签
     *
     * @param privateKey
     * @param data
     * @return
     */
    public static String sign(PrivateKey privateKey, String data) throws Exception {
        //加签算法,加签算法有很多种,这里选择 MD5WithRSA
        Signature signature = Signature.getInstance(ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        byte[] signByte = signature.sign();
        return Base64.getEncoder().encodeToString(signByte);
    }

3.根据公钥验签

/**
     * 根据公钥验签
     *
     * @param publicKey
     * @param signStr
     * @param data
     * @return
     */
    public static boolean vertify(PublicKey publicKey, String signStr, String data) throws Exception {
        Signature signature = Signature.getInstance(ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        return signature.verify(Base64.getDecoder().decode(signStr));
    }

完整的方法如下:

public final static String KEY_ALGORITHM = "RSA";

    public final static String ALGORITHM = "MD5WithRSA";

    public final static String PRIVATE_KEY = "privateKey";

    public final static String PUBLIC_KEY = "publicKey";

    /**
     * 获取公私钥对
     *
     * @return
     */
    private static Map<String, String> getKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator generator = null;
        generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化秘钥size,最小为512
        generator.initialize(1024);
        KeyPair keyPair = generator.generateKeyPair();
        String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        Map<String, String> keyMap = new HashMap<>();
        keyMap.put(PRIVATE_KEY, privateKey);
        keyMap.put(PUBLIC_KEY, publicKey);
        return keyMap;
    }

    /**
     * 根据字符串获取私钥
     *
     * @param privateKeyStr
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        return privateKey;
    }

    /**
     * 根据字符串获取公钥
     *
     * @param publicKeyStr
     * @return
     */
    public static PublicKey getPublickey(String publicKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 根据keyMap获取私钥字符串
     *
     * @param keyMap
     * @return
     */
    public static String getPrivateKeyStr(Map<String, String> keyMap) {
        return keyMap.get(PRIVATE_KEY);
    }

    /**
     * 根据私钥获取私钥字符串
     *
     * @param privateKey
     * @return
     */
    public static String getPrivateKeyStr(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }

    /**
     * 根据keyMap获取公钥字符串
     *
     * @param keyMap
     * @return
     */
    public static String getPublicKeyStr(Map<String, String> keyMap) {
        return keyMap.get(PUBLIC_KEY);
    }

    /**
     * 根据公钥获取公钥字符串
     *
     * @param publicKey
     * @return
     */
    public static String getPublicKeyStr(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    /**
     * 根据私钥字符串加签
     *
     * @param privateKeyStr 私钥字符串
     * @param data          需要加签的数据
     * @return
     */
    public static String sign(String privateKeyStr, String data) throws Exception {
        PrivateKey privateKey = getPrivateKey(privateKeyStr);
        return sign(privateKey, data);
    }

    /**
     * 根据私钥加签
     *
     * @param privateKey
     * @param data
     * @return
     */
    public static String sign(PrivateKey privateKey, String data) throws Exception {
        //加签算法,加签算法有很多种,这里选择 MD5WithRSA
        Signature signature = Signature.getInstance(ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        byte[] signByte = signature.sign();
        return Base64.getEncoder().encodeToString(signByte);
    }

    /**
     * 根据公钥字符串验签
     *
     * @param publicKeyStr
     * @param signStr
     * @param data
     * @return
     */
    public static boolean vertify(String publicKeyStr, String signStr, String data) throws Exception {
        PublicKey publicKey = getPublickey(publicKeyStr);
        return vertify(publicKey, signStr, data);
    }

    /**
     * 根据公钥验签
     *
     * @param publicKey
     * @param signStr
     * @param data
     * @return
     */
    public static boolean vertify(PublicKey publicKey, String signStr, String data) throws Exception {
        Signature signature = Signature.getInstance(ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        return signature.verify(Base64.getDecoder().decode(signStr));
    }