RSA encryption, decryption, signature and verification of API parameters in Spring Boot

The following is a sample code of the RSAUtil class that uses Spring Boot to implement RSA encryption, decryption, signature and verification:

```
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

public class RSAUtil {

    private static final String RSA_ALGORITHM = "RSA";


    //这个函数是自己随机生成一个rsa的公私密钥对,一般情况下我们是从配置文件或者redis读取密钥对的,也就是这个函数用不到。
    public static Map<String, String> generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        keyPairGenerator.initialize(2048);//2048太长了,一般1024即可
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        String publicKeyString = Base64Utils.encodeToString(publicKey.getEncoded());
        String privateKeyString = Base64Utils.encodeToString(privateKey.getEncoded());
        return Map.of("publicKey", publicKeyString, "privateKey", privateKeyString);
        //这里map.of如果用不了,就老老实实new个map.put去加载<k,v>
    }

    public static String encrypt(String data, String publicKeyString) throws Exception {
        byte[] publicKeyBytes = Base64Utils.decodeFromString(publicKeyString);
        PublicKey publicKey = KeyFactory.getInstance(RSA_ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKeyBytes));
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64Utils.encodeToString(encryptedBytes);
    }

    public static String decrypt(String encryptedData, String privateKeyString) throws Exception {
        byte[] privateKeyBytes = Base64Utils.decodeFromString(privateKeyString);
        PrivateKey privateKey = KeyFactory.getInstance(RSA_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(Base64Utils.decodeFromString(encryptedData));
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    public static String sign(String data, String privateKeyString) throws Exception {
        byte[] privateKeyBytes = Base64Utils.decodeFromString(privateKeyString);
        PrivateKey privateKey = KeyFactory.getInstance(RSA_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));
        byte[] signatureBytes = signature.sign();
        return Base64Utils.encodeToString(signatureBytes);
    }

    public static boolean verify(String data, String signature, String publicKeyString) throws Exception {
        byte[] publicKeyBytes = Base64Utils.decodeFromString(publicKeyString);
        PublicKey publicKey = KeyFactory.getInstance(RSA_ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKeyBytes));
        Signature verifier = Signature.getInstance("SHA256withRSA");
        verifier.initVerify(publicKey);
        verifier.update(data.getBytes(StandardCharsets.UTF_8));
        byte[] signatureBytes = Base64Utils.decodeFromString(signature);
        return verifier.verify(signatureBytes);
    }

    public static String sortParams(Map<String, String> params) {
        String[] keys = params.keySet().toArray(new String[0]);
        Arrays.sort(keys);
        String sortedParams = Arrays.stream(keys)
                .map(key -> key + "=" + params.get(key))
                .collect(Collectors.joining("&"));
        return sortedParams;
    }

}
```

This class has five static methods:

- `generateKeyPair()`
- This method is used to generate an RSA public-private key pair, and the return value is a Map containing the public-private key.

- `encrypt(String data, String publicKeyString)`:

This method is used to encrypt data using the public key and return the encrypted Base64 encoded string.

- `decrypt(String encryptedData, String privateKeyString)`:

This method is used to decrypt the encrypted data using the private key and return the decrypted string.

- `sign(String data, String privateKeyString)`:

This method is used to sign the data with the private key and return the signed Base64 encoded string.

- `verify(String data, String signature, String publicKeyString)`:

This method is used to verify the signature using the public key, and returns true if the verification passes, otherwise returns false.

In addition, this class also has a static method `sortParams(Map<String, String> params)`, which is used to sort the parameters in the Map and return the sorted string for use in signing.

Here is an example of usage:

```
public static void main(String[] args) throws Exception {
    // 生成公私密钥对,或者不生成,直接从配置文件载入pub&pri的2个字符串值
    Map<String, String> keyPair = RSAUtil.generateKeyPair();
    String publicKey = keyPair.get("publicKey");
    String privateKey = keyPair.get("privateKey");

    // 加密解密示例
    String data = "Hello, world!";
    String encryptedData = RSAUtil.encrypt(data, publicKey);
    String decryptedData = RSAUtil.decrypt(encryptedData, privateKey);
    System.out.println("原始数据:" + data);
    System.out.println("加密后数据:" + encryptedData);
    System.out.println("解密后数据:" + decryptedData);

    // 签名验签示例,Map.of可以改成new map.put(k,v)
    Map<String, String> params = Map.of(
            "timestamp", "1621005751",
            "nonce", "123456",
            "data", "Hello, world!"
    );
    String sortedParams = RSAUtil.sortParams(params);
    String signature = RSAUtil.sign(sortedParams, privateKey);
    boolean verified = RSAUtil.verify(sortedParams, signature, publicKey);
    System.out.println("排序后的参数:" + sortedParams);
    System.out.println("签名结果:" + signature);
    System.out.println("验签结果:" + verified);
}
```

This sample code first uses the `generateKeyPair()` method to generate an RSA public-private key pair, and stores the public-private key in the variables `publicKey` and `privateKey`. Then, it uses the `encrypt()` method to encrypt the string "Hello, world!", and then uses the `decrypt()` method to decrypt the encrypted data, and finally outputs the string before and after encryption and the string after decryption . Next, it uses the `sortParams()` method to sort a Map containing three parameters, then uses the `sign()` method to sign the sorted parameters, and uses the `verify()` method to verify the signature . Finally, it outputs the sorted parameters, signature result and signature verification result.

Hope this example can help you achieve your needs.

Guess you like

Origin blog.csdn.net/laolitou_1024/article/details/130344213