RSA算法加密/解密和签名/验签工具类

简介: RSA算法加密/解密和签名/验签工具类

public class RsaUtils {

/**
 * 算法名称
 */
private static final String ALGORITHM = "RSA";
/**
 * 签名算法 MD5withRSA 或 SHA1WithRSA 等
 */
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
 * 密钥长度默认是1024位:
 * 加密的明文最大长度 = 密钥长度 - 11(单位是字节,即byte)
 */
private static final int KEY_SIZE = 1024;
/**
 * RSA最大加密明文大小
 */
private static final int MAX_ENCRYPT_BLOCK = 117;

/**
 * RSA最大解密密文大小
 */
private static final int MAX_DECRYPT_BLOCK = 128;


/**
 * 获取密钥对
 *
 * @return 密钥对
 */
public static KeyPair getKeyPair() throws Exception {
    KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);
    generator.initialize(KEY_SIZE);
    return generator.generateKeyPair();
}

/**
 * 私钥字符串转PrivateKey实例
 *
 * @param privateKey 私钥字符串
 * @return
 */
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
    KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    byte[] decodedKey = Base64.getDecoder().decode(privateKey.getBytes("UTF-8"));// 对私钥进行Base64编码解密
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
    return keyFactory.generatePrivate(keySpec);
}

/**
 * 公钥字符串转PublicKey实例
 *
 * @param publicKey 公钥字符串
 * @return
 */
public static PublicKey getPublicKey(String publicKey) throws Exception {
    KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    byte[] decodedKey = Base64.getDecoder().decode(publicKey.getBytes("UTF-8")); // 对公钥进行Base64编码解密
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
    return keyFactory.generatePublic(keySpec);
}

/**
 * 公钥加密
 *
 * @param data      待加密数据
 * @param publicKey 公钥
 * @return
 */
public static String encryptByPublicKey(String data, PublicKey publicKey) {
    try (
            ByteArrayOutputStream out = new ByteArrayOutputStream();
    ) {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int inputLen = data.getBytes("UTF-8").length;
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data.getBytes("UTF-8"), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes("UTF-8"), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        // 获取加密内容使用Base64进行编码加密,并以UTF-8为标准转化成字符串
        // 加密后的字符串
        //return new String(Base64.encodeBase64String(encryptedData));
        return new String(Base64.getEncoder().encode(encryptedData), "UTF-8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * 私钥解密
 *
 * @param data       待解密数据
 * @param privateKey 私钥
 * @return
 */
public static String decryptByPrivateKey(String data, PrivateKey privateKey) {
    try (
            ByteArrayOutputStream out = new ByteArrayOutputStream();
    ) {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 对待解密数据进行Base64编码解密
        byte[] dataBytes = Base64.getDecoder().decode(data.getBytes("UTF-8"));
        int inputLen = dataBytes.length;
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        // 解密后的内容
        return new String(decryptedData, "UTF-8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * 私钥签名
 *
 * @param data       待签名数据
 * @param privateKey 私钥
 * @return 签名
 */
public static String sign(String data, PrivateKey privateKey) throws Exception {
    byte[] keyBytes = privateKey.getEncoded();
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    PrivateKey key = keyFactory.generatePrivate(keySpec);
    Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    signature.initSign(key);
    signature.update(data.getBytes());
    return new String(Base64.getEncoder().encode(signature.sign()));  // 对签名内容进行Base64编码加密
}

/**
 * 公钥验签
 *
 * @param srcData   原始字符串
 * @param publicKey 公钥
 * @param sign      签名
 * @return 是否验签通过
 */
public static boolean verify(byte[] srcData, PublicKey publicKey, String sign) throws Exception {
    byte[] keyBytes = publicKey.getEncoded();
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    PublicKey key = keyFactory.generatePublic(keySpec);
    Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    signature.initVerify(key);
    signature.update(srcData);
    return signature.verify(Base64.getDecoder().decode(sign));
}

public static void main(String[] args) {
    try {
        // 生成密钥对
        KeyPair keyPair = getKeyPair();
        String privateKey = new String(Base64.getEncoder().encode(keyPair.getPrivate().getEncoded()), "UTF-8");
        String publicKey = new String(Base64.getEncoder().encode(keyPair.getPublic().getEncoded()), "UTF-8");
        System.out.println("私钥:" + privateKey);
        System.out.println("公钥:" + publicKey);
        // RSA加密
        String data = "签名算法可以是NIST标准DSA,使用DSA和SHA-1。 使用SHA-1消息摘要算法的DSA算法可以指定为SHA1withDSA 。 在RSA的情况下,\n" +
                "存在对消息多个选择摘要算法,所以签名算法可被指定为,例如, MD2withRSA , MD5withRSA ,或SHA1withRSA 。 必须指定算法名称,因为没有默认值。";
        String encryptData = encryptByPublicKey(data, getPublicKey(publicKey));
        System.out.println("加密后内容:" + encryptData);
        // RSA解密
        String decryptData = decryptByPrivateKey(encryptData, getPrivateKey(privateKey));
        System.out.println("解密后内容:" + decryptData);

        // RSA签名
        String sign = sign(data, getPrivateKey(privateKey));
        System.out.println("签名内容:" + sign);
        // RSA验签
        boolean result = verify(data.getBytes(), getPublicKey(publicKey), sign);
        System.out.print("验签结果:" + result);

    } catch (Exception e) {
        e.printStackTrace();
        System.out.print("加密解密异常");
    }
}

}

相关文章
|
9天前
|
算法 安全 网络安全
非对称加密算法RSA
RSA是一种基于数论的非对称加密算法,依赖大整数质因数分解的困难性保证安全性。它生成公钥和私钥,公钥加密,私钥解密,适用于数据加密、数字签名和互联网安全等领域。尽管计算效率低、适合小量数据处理,但由于其兼容性、安全性和广泛应用于SSL/TLS、数字签名等,RSA仍是主流加密算法之一。
13 2
|
11天前
|
算法 数据安全/隐私保护
对称密钥加密算法和公开密钥加密算法有什么区别
【4月更文挑战第19天】对称密钥和公开密钥加密算法各有特点:对称密钥加密速度快,适用于大量数据,但密钥管理困难;公开密钥加密安全性高,密钥管理方便,但速度慢,常用于数字签名和身份验证。两者在不同场景下有不同优势。
26 6
|
2月前
|
数据安全/隐私保护
使用加密工具类进行有效的字符串加密——CSDN博客
使用加密工具类进行有效的字符串加密——CSDN博客
16 0
|
2月前
|
数据安全/隐私保护
常用的字符串加密解密工具类
常用的字符串加密解密工具类
15 0
|
3月前
|
JSON 小程序 数据安全/隐私保护
小程序动态调试-解密加密数据与签名校验
本文主要讲解微信小程序加密、验签的情况下如何进行动态调试已获取签名以及加密信息
|
3月前
|
存储 算法 安全
【加密算法】AES对称加密算法简介
【加密算法】AES对称加密算法简介
|
3月前
|
机器学习/深度学习 算法 安全
【加密算法】RSA非对称加密算法简介
【加密算法】RSA非对称加密算法简介
|
7天前
|
安全 算法 网络安全
|
15天前
|
存储 算法 安全
加密解密(RSA)非对称加密算法
加密解密(RSA)非对称加密算法
|
Java 数据安全/隐私保护
Java实现最电话号码的简单加密源码
Java实现最电话号码的简单加密源码
18 0