前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RSA非对称加密

RSA非对称加密

作者头像
会跳舞的机器人
发布2018-09-03 16:09:47
1.5K0
发布2018-09-03 16:09:47
举报
一、对称加密与非对称加密
  • 对称加密:加密和解密使用的是同一个密钥,加解密双方必须使用同一个密钥才能进行正常的沟通。
  • 非对称加密:需要两个密钥来进行加密和解密,公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥) ,公钥加密的信息只有私钥才能解开,私钥加密的信息只有公钥才能解开。

需要注意的一点,这个公钥和私钥必须是一对的,如果用公钥对数据进行加密,那么只有使用对应的私钥才能解密,所以只要私钥不泄露,那么我们的数据就是安全的。

常用的加密算法:

  • 对称加密:DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES。
  • 非对称加密:RSA、ECC(椭圆曲线加密算法)、Diffie-Hellman、El Gamal、DSA(数字签名用)
  • Hash 算法:MD2、MD4、MD5、HAVAL、SHA-1、SHA256、SHA512、RipeMD、WHIRLPOOL、SHA3、HMAC
二、非对称加密工作过程

甲乙双方使用非对称加密算法的方式进行数据传输

  • 乙方生成一对密钥(公钥与私钥),并将公钥向甲方公开
  • 甲方获取到公钥后,将需要传输的数据用公钥进行加密发送给乙方
  • 乙方获取到甲方加密数据后,用私钥进行解密
  • 在数据传输过程中,即使数据被攻击者截取并获取了公钥,攻击者也无法破解密文,因为只有乙方的私钥才能解密
三、非对称加密中,究竟是公钥加密还是私钥加密?
  • 对于加密:公钥加密,私钥加密。毕竟公钥可以公开,但是私钥只有你自已知道,你也同样希望只有你自已才能解密
  • 对于签名:私钥加密,公钥解密。好比你的签名只有你自已签的才是真的,别人签的都是假的。
四、RSA非对称加密代码示例

RSA 算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

1、添加jar包

<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcpkix-jdk15on</artifactId>
	<version>1.56</version>
</dependency>

2、RSAUtil.java

package com.kimeng.weipan.utils;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

/**
 * @author: 会跳舞的机器人
 * @date: 2017/9/18 15:00
 * @description: RSA工具类
 */
public class RSAUtil {
    /**
     * 定义加密方式
     */
    private final static String KEY_RSA = "RSA";
    /**
     * 定义签名算法
     */
    private final static String KEY_RSA_SIGNATURE = "MD5withRSA";
    /**
     * 定义公钥算法
     */
    private final static String KEY_RSA_PUBLICKEY = "RSAPublicKey";
    /**
     * 定义私钥算法
     */
    private final static String KEY_RSA_PRIVATEKEY = "RSAPrivateKey";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 初始化密钥
     */
    public static Map<String, Object> init() {
        Map<String, Object> map = null;
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_RSA);
            generator.initialize(2048);
            KeyPair keyPair = generator.generateKeyPair();
            // 公钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            // 私钥
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            // 将密钥封装为map
            map = new HashMap<>();
            map.put(KEY_RSA_PUBLICKEY, publicKey);
            map.put(KEY_RSA_PRIVATEKEY, privateKey);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 公钥加密
     *
     * @param data 待加密数据
     * @param key  公钥
     */
    public static byte[] encryptByPublicKey(String data, String key) {
        byte[] result = null;
        try {
            byte[] bytes = decryptBase64(key);
            // 取得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");

            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] encode = cipher.doFinal(data.getBytes());
            // 再进行Base64加密
            result = Base64.encode(encode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 私钥解密
     *
     * @param data 加密数据
     * @param key  私钥
     */
    public static String decryptByPrivateKey(byte[] data, String key) {
        String result = null;
        try {
            // 对私钥解密
            byte[] bytes = decryptBase64(key);
            // 取得私钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据解密
            Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 先Base64解密
            byte[] decoded = Base64.decode(data);
            result = new String(cipher.doFinal(decoded));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 获取公钥
     */
    public static String getPublicKey(Map<String, Object> map) {
        String str = "";
        try {
            Key key = (Key) map.get(KEY_RSA_PUBLICKEY);
            str = encryptBase64(key.getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 获取私钥
     */
    public static String getPrivateKey(Map<String, Object> map) {
        String str = "";
        try {
            Key key = (Key) map.get(KEY_RSA_PRIVATEKEY);
            str = encryptBase64(key.getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 用私钥对信息生成数字签名
     *
     * @param data       加密数据
     * @param privateKey 私钥
     */
    public static String sign(byte[] data, String privateKey) {
        String str = "";
        try {
            // 解密由base64编码的私钥
            byte[] bytes = decryptBase64(privateKey);
            // 构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取私钥对象
            PrivateKey key = factory.generatePrivate(pkcs);
            // 用私钥对信息生成数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initSign(key);
            signature.update(data);
            str = encryptBase64(signature.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 校验数字签名
     *
     * @param data      加密数据
     * @param publicKey 公钥
     * @param sign      数字签名
     * @return 校验成功返回true,失败返回false
     */
    public static boolean verify(byte[] data, String publicKey, String sign) {
        boolean flag = false;
        try {
            // 解密由base64编码的公钥
            byte[] bytes = decryptBase64(publicKey);
            // 构造X509EncodedKeySpec对象
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取公钥对象
            PublicKey key = factory.generatePublic(keySpec);
            // 用公钥验证数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initVerify(key);
            signature.update(data);
            flag = signature.verify(decryptBase64(sign));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }


    /**
     * BASE64 解密
     *
     * @param key 需要解密的字符串
     * @return 字节数组
     */
    public static byte[] decryptBase64(String key) throws Exception {
        return Base64.decode(key);
    }

    /**
     * BASE64 加密
     *
     * @param key 需要加密的字节数组
     * @return 字符串
     */
    public static String encryptBase64(byte[] key) throws Exception {
        return new String(Base64.encode(key));
    }


    public static void main(String[] args) throws Exception {
        String publicKey = "";
        String privateKey = "";
        Map<String, Object> keyMap = RSAUtil.init();
        publicKey = RSAUtil.getPublicKey(keyMap);
        privateKey = RSAUtil.getPrivateKey(keyMap);
        System.out.println("公钥:\n\r" + publicKey);
        System.out.println("私钥:\n\r" + privateKey);

        System.out.println("公钥加密======私钥解密");
        String str = "会跳舞的机器人";
        byte[] enStr = RSAUtil.encryptByPublicKey(str, publicKey);
        String decStr = RSAUtil.decryptByPrivateKey(enStr, privateKey);
        System.out.println("加密前:" + str + "\n\r解密后:" + decStr);

        System.out.println("\n\r");
        System.out.println("私钥签名======公钥验证");
        String sign = RSAUtil.sign(str.getBytes(), privateKey);
        System.out.println("签名:\n\r" + sign);
        boolean flag = RSAUtil.verify(str.getBytes(), publicKey, sign);
        System.out.println("验签结果:\n\r" + flag);
    }
}


公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkmIH1vvK8A+EDak84WOuOrN2IgzlarfDu6vp4i/vv/4Edezr1J5kWGf9WpGx2lfpZPS80bN03nxeA1utRoktJvqu++oXkoU3oDLlm/MciTV2lpSiDf8BiZfZ298FKQsG7CKI1Tj9ii9MlHWCsIDHfEJBsQTYONgDSjM6yecfRu0Xg0ZCNklNNeDki60oFa20hiUdLthSopuCWmxAGQL7uuOwlj07xzBXGEJkh8ixGF9v+CDMQLLU6ezk8ZWnPsOwS7OiJZkndyw13NKx8PMmaHX+cOYL5b6Vi7UQ+yizpGejV36XuX0Zpxb2AZee/IZCRGt/cOg0QKmEcN5KeKG6qQIDAQAB
私钥:
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCSYgfW+8rwD4QNqTzhY646s3YiDOVqt8O7q+niL++//gR17OvUnmRYZ/1akbHaV+lk9LzRs3TefF4DW61GiS0m+q776heShTegMuWb8xyJNXaWlKIN/wGJl9nb3wUpCwbsIojVOP2KL0yUdYKwgMd8QkGxBNg42ANKMzrJ5x9G7ReDRkI2SU014OSLrSgVrbSGJR0u2FKim4JabEAZAvu647CWPTvHMFcYQmSHyLEYX2/4IMxAstTp7OTxlac+w7BLs6IlmSd3LDXc0rHw8yZodf5w5gvlvpWLtRD7KLOkZ6NXfpe5fRmnFvYBl578hkJEa39w6DRAqYRw3kp4obqpAgMBAAECggEAcZ0onJGddylzwu6h1AX8Co+TluYPgf7TKmxKAUZXfNp5N9YFTGcLVxqPJ6aBNgiZm8PgcZopkS1SAqU7Hc4Gf4R+IAQW+5/uBqa6U4ojkdMvEbyW8uoDlXmInADDDpICc3ByZ5vuHTyM4YU7RCcPrb/3IJ+z+pqeIw8UB/Uc73yUkao+KwL1alpKY8YTkHGMvIwgQDzhRSrfw7Nc5ZLZlkulWfgPN6B51peAqi8ZHGlyECtheEaS/Ws5O/Ju3y7V50WIs/rKT9DFpUZ8nueUPyn1+m+arMFPP3fKd2+9lUotQIIFgkyhLCdX6j7fxhDy2mQk7F68RhZPcGehg86SSQKBgQDM4uK6LCJ8BNURaaOospuOw0nmxeRmDxGMtGDIuTiOLccxwYJPQDQadZ76bfQpn7WmWyQrJWeKmDuvPZ+Mi+RHSL1W0mJnY9/0nLkgsu7fFFq5TDDBnEfNgqfyrozHZa6Eg89exjfH7WQTDbBI2/JXiNHA1iRwRsLIe+RJM/QsYwKBgQC25tBsLoDNUdyaXL9tf2kCG6vepUfdOdfSpby1pU4zpdONJXMenZglh3wIAKWoLVlhchRn/us1ClNasDqJX2O6WgXYh1OL88wFY8B04VnpV3o73vSJhxibZnm6KOzdonHiDAaP5+p/2jVRKewOoEmMFCITzDgSLqcKhA35wxosgwKBgAPUZdqHAqoAyR7HM7juhbvYaKQ4pLlHpNNVd82osKbvsh56+H2UvKSV+D/EGGFCy/ltELMBwvqzN8Jhy36sCrtOX8OksRQvqLsAxvEWhyKCVePKycqEqk7sF0mQ+66qduWhNRoXaGmDRXCZu+bQvannM8x/9DRpDjEDJ9Q6dWDzAoGBAK5GdCYAkX4SGG+FHGnLU1VM5JE7T6R97yWqAovaPQ99XHxLSMvNQiHQXOCLLU14GIh/WO5WuetKMW5iKQSoPbBdAuD04SijXq1sBP/ZkgCC99eAc+VvMoUwOaCmSjxNAtJuvvnz8z9rvg3eMi0lka7FqErQ9kRs64Fbnq1zt8bdAoGABbMMrAgeDvfkQId/1GsFP/xdgUicnXrLhD/cn6NlAqcU9lAubsRDewIQtfw377OsutK6gzbFdrLnaigRDgwf+y0XACdhldE8vTVOPtBaUIqSjTSjuRlp4ZBN1vx2or6QBG7Om061EuaL625YguAjeHpSxTiAbk5tejBnICXPFhY=
公钥加密======私钥解密
加密前:会跳舞的机器人
解密后:会跳舞的机器人


私钥签名======公钥验证
签名:
DqSegeOz0lIESAd7J7tlkYHsm/81vITAS9RWEmTtOtz5+NVtcD1RGgau2hMVDhNsIr7F0qP2SJSCu0SlAJxvN0pYYrRo5Cy1aLUCfsv/BEoLi32IcNN8cDClCxLa/uIDzyRd3+q8yMDuAhvX2eojiiu6cT3jwrajK4mtxncIbXvNFJ9/po36q8NYujvOhI0ujEFlDC5o5GwskXsJgk/gKf9raiGS9O7Pm8XejsSyDPITre86tuntWQppqWHIku/uN8Cf2n7AlD2HVBryQrma922iIxE3ykfNGoxF4wwof3AGXG4P12nC0rDB/V/7twFZvKmYBWAejni7bDJaV3+pUg==
验签结果:
true
五、RSA非对称加密的缺点

加解密速度较慢,不太适用于高并发的业务场景,一般用它做少量的数据加密。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-11-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、对称加密与非对称加密
  • 二、非对称加密工作过程
  • 三、非对称加密中,究竟是公钥加密还是私钥加密?
  • 四、RSA非对称加密代码示例
  • 五、RSA非对称加密的缺点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档