JAVA RSA加解密工具类Demo

引言

由于原有的处理器效率过低,从Python欲迁移到Java版,这里简单记录一下RSA的加解密以及分段的加解密操作方法。

生成&转换

openssl genrsa -out priv1.pem 4096 # 生成私钥 4096代表位数
openssl pkcs8 -topk8  -in priv.pem -out priv8.pem -nocrypt # 私钥 PKCS1 --> PKCS8
openssl rsa -in priv.pem -pubout -out pub.pem # 私钥生成公钥

代码

引用

如果使用openssl等工具生成的密钥,需PKCS8格式
代码中的密钥部分不包含-----BEGIN RSA PRIVATE KEY-----和-----END RSA PRIVATE KEY-----,需'掐头去尾'

package top.zunmx.sc.algorithm;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;

public class RSAUtil<T> {
    public static String RSA_ALGORITHM = "RSA";
    private static final int KEY_SIZE = 1024;
    private static final int MAX_ENCRYPT_BLOCK = 117;
    private static final int MAX_DECRYPT_BLOCK = 128;

    private byte[] priv_key = Base64.getDecoder().decode("MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMlrJn/STaexYjxmyEShthFd0sluWy49tYQxLXhek2tqLDSf6QGhniO0FJQCdi0iR2Wws0z1FdJljZKYSO44wo4d81T7/oAdipScChrVRL8iDh3WveQ0H9shdRxhia8AqXgZxhZO9Z7kfwut81uuM8BbnJOrI41jFwjnWJhq4lRXAgMBAAECgYBcElUI/RNuYpGrVriZVuqpSaA/X+jiXGcLRIeqjGELKv+GFssmacCmRX1aoz1uKEtG2t07gpU1FiL/Lgm4i82y5aInWyyG1uD1h95+4Mg0h0J1TTOHa683jz5TVlZrvm/9PqQfhzxuucG6HjoHoyEyXVpJ2QiYbv+9qDWq5V9rgQJBAOmlImOwSgeIAmQZhrWLAVOMX3YgAmzhrHcc6upeJ/inCCgKPZPBnNUxeRCvj/AjcDg4yC7M+r8q08fVLaI0BOECQQDcsKpJPtRiVp6ERCDNgrLSbeEtQJz+0OlXjwPPlOypZfVh2n0Uc1ia3GZd/oMDFeOOl/HyAMy3tkxVId8lFkg3AkB3BTksgTxk88MMDPjTeDk3v1VNzmaN4rRBhUiiFU7VWvlLtFPD9igXbnlWp6hyUwsyiLJpLOA7C+0Qaicx7r/hAkAqywb6FPjR6MHsG9nQf9t0+mGDiNfogVH97HlssxAA+QhP5TID2SoBPWOMLmHxIzlw2P3NU2Je7TZ3+41tf5iZAkBmoiXs29LgRz1Q76XD0wiA1TbqQCCbiRCpznLMarBsYS1rPzBLTMfrOeJ4iY4LO/wBfzzIWE3j2TIzywT094Fh");
    private byte[] pub_key = Base64.getDecoder().decode("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJayZ/0k2nsWI8ZshEobYRXdLJblsuPbWEMS14XpNraiw0n+kBoZ4jtBSUAnYtIkdlsLNM9RXSZY2SmEjuOMKOHfNU+/6AHYqUnAoa1US/Ig4d1r3kNB/bIXUcYYmvAKl4GcYWTvWe5H8LrfNbrjPAW5yTqyONYxcI51iYauJUVwIDAQAB");

    public RSAUtil(String pubKey, String privKey) {
        this.pub_key = Base64.getDecoder().decode(pubKey);
        this.priv_key = Base64.getDecoder().decode(privKey);
    }

    public RSAUtil() {

    }

    public static HashMap<String, String> generatorKey() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(KEY_SIZE); // 初始化密钥生成器,并指定密钥长度为 1024 位
        KeyPair keyPair = keyGen.generateKeyPair(); // 生成密钥对
        String pubKey = new String(Base64.getEncoder().encode((keyPair.getPublic().getEncoded())));
        String privKey = new String(Base64.getEncoder().encode((keyPair.getPrivate().getEncoded())));
        System.out.println("公钥:" + pubKey);
        System.out.println("私钥:" + privKey);
        HashMap<String, String> keys = new HashMap<>();
        keys.put("pubKey", pubKey);
        keys.put("privKey", privKey);
        return keys;
    }

    public String encryptByPrivateKey(byte[] data) {
        try {
            //取得私钥
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(this.priv_key);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            //生成私钥
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
            //数据加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(data));
        } catch (Exception e) {
            return null;
        }
    }

    public String encryptByPublicKey(byte[] data) {
        try {
            //实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            //初始化公钥,根据给定的编码密钥创建一个新的 X509EncodedKeySpec。
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(this.pub_key);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            //数据加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(data));
        } catch (Exception e) {
            return null;
        }
    }

    public byte[] decryptByPrivateKey(String data) {
        try {
            //取得私钥
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(this.priv_key);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            //生成私钥
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
            //数据解密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(Base64.getDecoder().decode(data));
        } catch (Exception e) {
            return null;
        }
    }

    public byte[] decryptByPublicKey(String data) {
        try {
            //实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            //初始化公钥
            //密钥材料转换
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(this.pub_key);
            //产生公钥
            PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
            //数据解密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, pubKey);
            return cipher.doFinal(Base64.getDecoder().decode(data));
        } catch (Exception e) {
            return null;
        }
    }

    private byte[] segmentDecrypt(byte[] encryptText, Cipher cipher) throws Exception {
        int inputLen = encryptText.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptText, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptText, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] plainText = out.toByteArray();
        out.close();
        return plainText;

    }

    private String segmentEncrypt(byte[] plainTextArray, Cipher cipher) throws Exception {
        int inputLen = plainTextArray.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        int i = 0;
        byte[] cache;
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(plainTextArray, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(plainTextArray, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptText = out.toByteArray();
        out.close();
        return Base64.getEncoder().encodeToString(encryptText);
    }

    public String encryptSegmentByPrivateKey(T plainText) throws Exception {
        String name = plainText.getClass().getName();
        byte[] plainTextArray = null;
        if (name.equals("java.lang.String")) {
            plainTextArray = ((String) plainText).getBytes();
        } else {
            plainTextArray = (byte[]) plainText;
        }
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(this.priv_key);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return segmentEncrypt(plainTextArray, cipher);
    }

    public String encryptSegmentByPublicKey(T plainText) throws Exception {
        String name = plainText.getClass().getName();
        byte[] plainTextArray = null;
        if (name.equals("java.lang.String")) {
            plainTextArray = ((String) plainText).getBytes();
        } else {
            plainTextArray = (byte[]) plainText;
        }
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(this.pub_key);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return segmentEncrypt(plainTextArray, cipher);
    }

    public byte[] decryptSegmentByPrivateKey(String encryptTextHex) throws Exception {
        byte[] encryptText = Base64.getDecoder().decode(encryptTextHex);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(this.priv_key);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return segmentDecrypt(encryptText, cipher);
    }

    public byte[] decryptSegmentByPublicKey(String encryptTextHex) throws Exception {
        byte[] encryptText = Base64.getDecoder().decode(encryptTextHex);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(this.pub_key);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return segmentDecrypt(encryptText, cipher);
    }

}
public class Main {
    public static void main(String[] args) throws Exception {
        HashMap<String, String> keys = RSAUtil.generatorKey();// 生成密钥
        RSAUtil rsaUtil = new RSAUtil(keys.get("pubKey"), keys.get("privKey")); // 使用新生成的密钥
//        RSAUtil rsaUtil = new RSAUtil();
        byte[] text = new byte[]{97, 98, 99}; // 要加密的数据,字节数组

        String enc = rsaUtil.encryptByPublicKey(text);
        byte[] dec = rsaUtil.decryptByPrivateKey(enc);
        System.out.println("公钥加密: " + enc);
        System.out.println("私钥解密: " + new String(dec));

        String s = new String("Hello World"); // 要加密的数据,字符串

        enc = rsaUtil.encryptByPrivateKey(s);
        dec = rsaUtil.decryptByPublicKey(enc);
        System.out.println("私钥加密: " + enc);
        System.out.println("公钥解密: " + new String(dec));

        // 长字符串
        String s1 = new String("Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,Hello World,"); // 要加密的数据
        enc = rsaUtil.encryptSegmentByPublicKey(s1);
        dec = rsaUtil.decryptSegmentByPrivateKey(enc);
        System.out.println("公钥加密: " + enc);
        System.out.println("私钥解密: " + new String(dec));

        // 长字节数组
        byte[] s2 = new byte[]{97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99, 97, 98, 99}; // 要加密的数据,字节数组
        enc = rsaUtil.encryptSegmentByPrivateKey(s2);
        dec = rsaUtil.decryptSegmentByPublicKey(enc);
        System.out.println("私钥加密: " + enc);
        System.out.println("公钥解密: " + new String(dec));
    }
}

image.png

特性

RSA:非对称加密算法
公钥:公开的密钥
私钥:私有的密钥
加密解密:公钥加密一定是私钥解密,私钥加密一定是公钥解密

评论 0

还没有评论,来说点什么吧。

提交后需要审核才会公开。