非对称加密 RSA算法

本文详细介绍了RSA算法的概念和原理,并提供了使用Java JDK和BC库实现RSA加密、解密及数字签名的代码示例。通过示例代码展示了如何生成公钥和私钥,以及如何进行私钥加密公钥解密和公钥加密私钥解密的操作,同时也包含了签名的生成和验证过程。
摘要由CSDN通过智能技术生成

概念

RSA是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的。当时他们三人都在麻省理工学院工作。RSA 就是他们三人姓氏开头字母拼在一起组成的。

RSA算法(可用于加密数字签名)的安全性基于这样的事实:大整数的因式分解 被认为是‘难以破解’的。

原理

  1. 公钥与私钥的产生
    在这里插入图片描述

  2. 加密消息
    在这里插入图片描述

  3. 解密消息
    在这里插入图片描述

java jdk实现

package crypto.rsa;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * 非对称加密 RSA
 */
public class RsaUtils {

    private static final String ALGORITHM = "RSA";

    private static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    public static InnerKey generateKey() throws NoSuchAlgorithmException {
        return generateKey(1024);
    }

    /**
     * 初始化密钥
     * <p>
     * 工作模式 ECB
     * 填充方式 NoPadding PKCS1Padding ...
     *
     * @param keysize 默认1024;范围在 [512~65536] ,且需要为 64 的倍数
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static InnerKey generateKey(int keysize) throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(keysize);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        //RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        return InnerKey.builder()
                .publicKey(keyPair.getPublic().getEncoded())
                .privateKey(keyPair.getPrivate().getEncoded())
                .build();
    }

    private static PublicKey getPublicKey(byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
        PublicKey publicKey = KeyFactory.getInstance(ALGORITHM).generatePublic(x509EncodedKeySpec);
        return publicKey;
    }

    private static PrivateKey getPrivateKey(byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
        PrivateKey privateKey = KeyFactory.getInstance(ALGORITHM).generatePrivate(pkcs8EncodedKeySpec);
        return privateKey;
    }

    /**
     * 私钥加密 公钥解密---加密
     *
     * @param privateKey
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] privateKey, byte[] data) throws Exception {
        return encrypt(true, privateKey, data);
    }

    /**
     * 私钥加密 公钥解密---解密
     *
     * @param publicKey
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] publicKey, byte[] data) throws Exception {
        return decrypt(false, publicKey, data);
    }

    /**
     * 公钥加密 私钥解密---加密
     *
     * @param publicKey
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] publicKey, byte[] data) throws Exception {
        return encrypt(false, publicKey, data);
    }

    /**
     * 公钥加密 私钥解密---解密
     *
     * @param privateKey
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] privateKey, byte[] data) throws Exception {
        return decrypt(true, privateKey, data);
    }

    private static byte[] encrypt(boolean isPrivate, byte[] key, byte[] data) throws Exception {
        Key thisKey = isPrivate ? getPrivateKey(key) : getPublicKey(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, thisKey);
        return cipher.doFinal(data);
    }

    private static byte[] decrypt(boolean isPrivate, byte[] key, byte[] data) throws Exception {
        Key thisKey = isPrivate ? getPrivateKey(key) : getPublicKey(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, thisKey);
        return cipher.doFinal(data);
    }

    /**
     * 用私钥对信息生成数字签名
     *
     * @param privateKey
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] sign(byte[] privateKey, byte[] data) throws Exception {
        //
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(getPrivateKey(privateKey));
        signature.update(data);
        return signature.sign();
    }

    /**
     * 验证签名
     *
     * @param publicKey
     * @param data
     * @param sign
     * @return
     * @throws Exception
     */
    public static boolean verifySign(byte[] publicKey, byte[] data, byte[] sign) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(getPublicKey(publicKey));
        signature.update(data);
        return signature.verify(sign);
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class InnerKey {
        private byte[] publicKey;
        private byte[] privateKey;
    }

}

测试代码

package crypto.rsa;

import org.apache.commons.codec.binary.Base64;

public class RsaUtilsTest {

    public static void main(String[] args) throws Exception {
        RsaUtils.InnerKey innerKey = RsaUtils.generateKey();
        System.out.println("公钥:" + Base64.encodeBase64String(innerKey.getPublicKey()));
        System.out.println("私钥:" + Base64.encodeBase64String(innerKey.getPrivateKey()));

        byte[] data = "你好,世界".getBytes();
        testEncrypt1(innerKey.getPublicKey(), innerKey.getPrivateKey(), data);
        testEncrypt2(innerKey.getPublicKey(), innerKey.getPrivateKey(), data);
        testSign(innerKey.getPublicKey(), innerKey.getPrivateKey(), data);
    }

    private static void testEncrypt1(byte[] publicKey, byte[] privateKey, byte[] data) throws Exception {
        // 私钥加密 公钥解密---加密
        byte[] encryptBytes = RsaUtils.encryptByPrivateKey(privateKey, data);
        System.out.println("私钥加密公钥解密-密文:" + Base64.encodeBase64String(encryptBytes));
        // 私钥加密 公钥解密---解密
        byte[] result = RsaUtils.decryptByPublicKey(publicKey, encryptBytes);
        System.out.println("解密后:" + new String(result));
    }

    private static void testEncrypt2(byte[] publicKey, byte[] privateKey, byte[] data) throws Exception {
        // 公钥加密 私钥解密---加密
        byte[] encryptBytes = RsaUtils.encryptByPublicKey(publicKey, data);
        System.out.println("公钥加密私钥解密-密文:" + Base64.encodeBase64String(encryptBytes));
        // 公钥加密 私钥解密---解密
        byte[] result = RsaUtils.decryptByPrivateKey(privateKey, encryptBytes);
        System.out.println("解密后:" + new String(result));
    }

    private static void testSign(byte[] publicKey, byte[] privateKey, byte[] data) throws Exception {
        byte[] sign = RsaUtils.sign(privateKey, data);
        System.out.println("签名:" + Base64.encodeBase64String(sign));
        boolean result = RsaUtils.verifySign(publicKey, data, sign);
        System.out.println("验签结果:" + result);
    }
}

java bc实现

java jdk实现2 - modulus publicExponent

package crypto.rsa;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

public class RsaTest {
    public static final String ALGORITHM = "RSA";

    public static void main(String[] args) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(512);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

        byte[] data = encrypt(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent(), "Hello 世界".getBytes());
        System.out.println(Base64.encodeBase64String(data));
        data = decrypt(rsaPrivateKey.getModulus(), rsaPrivateKey.getPrivateExponent(), data);
        System.out.println(new String(data));
    }

    public static byte[] encrypt(BigInteger modulus, BigInteger publicExponent, byte[] data) throws Exception {
        PublicKey publicKey = generateRSAPublicKey(modulus.toByteArray(), publicExponent.toByteArray());
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    public static byte[] decrypt(BigInteger modulus, BigInteger privateExponent, byte[] data) throws Exception {
        PrivateKey privateKey = generateRSAPrivateKey(modulus.toByteArray(), privateExponent.toByteArray());
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 根据给定的系数和专用指数构造一个RSA专用的公钥对象。
     *
     * @param modulus        系数。
     * @param publicExponent 专用指数。
     * @return RSA专用公钥对象。
     */
    public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws Exception {
        RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
    }

    /**
     * 根据给定的系数和专用指数构造一个RSA专用的私钥对象。
     *
     * @param modulus         系数。
     * @param privateExponent 专用指数。
     * @return RSA专用私钥对象。
     */
    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws Exception {
        RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
    }
}

code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值