教你用Java实现RSA非对称加密算法

一、非对称加密

非对称加密算法是一种密钥的保密方法。

非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方;甲方再用自己私钥对加密后的信息进行解密。甲方想要回复乙方时正好相反,使用乙方的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密。

另一方面,甲方可以使用自己的私钥对机密信息进行签名后再发送给乙方;乙方再用甲方的公钥对甲方发送回来的数据进行验签。

甲方只能用其私钥解密由其公钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

非对称密码体质的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

二、RSA算法

简介:

RSA公开密钥密码体质是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。

在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK 。

正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要 。

RSA是被研究得最广泛的公钥算法,从提出到现在已近三十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。1983年麻省理工学院在美国为RSA算法申请了专利。

算法原理:

RSA公开密钥密码体制的原理是:根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥 。

算法描述:

(1)任意选取两个不同的大素数p和q计算乘积

(2)任意选取一个大整数e,满足

整数e用做加密钥(注意:e的选取是很容易的,例如,所有大于p和q的素数都可用)

(3)确定的解密钥d,满足

是一个任意的整数;所以,若知道e和则很容易计算出d

(4)公开整数n和e,秘密保存d

(5)将明文m(m<n是一个整数)加密成密文c,加密算法为

(6)将密文c解密为明文m,解密算法为

RSA允许你选择公钥的大小。512位的密钥被视为不安全的;768位的密钥不用担心受到除了国家安全管理(NSA)外的其他事物的危害;1024位的密钥几乎是安全的。RSA在一些主要产品内部都有嵌入,像 Windows、网景 Navigator、 Quicken和 Lotus Notes 。

三、RSA算法Java语言实现

RSA算法工具类源码:

package com.ljt.rsa.util;

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

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: RSAUtil
 * @Description:  RSA非对称加密算法工具类
 * @Author: 寒山月初°C
 * @Date 2021/5/16 17:47
 * @Version 1.0
 */

public class RSAUtil {

    public static final String CHARSET = "UTF-8";
    public static final String RSA_ALGORITHM = "RSA";

    public static Map<String, String> createKeys(int keySize){
        //为RSA算法创建一个KeyPairGenerator对象(KeyPairGenerator,密钥对生成器,用于生成公钥和私钥对)
        KeyPairGenerator kpg;
        try{
            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        }catch(NoSuchAlgorithmException e){
            throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
        }

        //初始化KeyPairGenerator对象,密钥长度
        kpg.initialize(keySize);
        //生成密匙对
        KeyPair keyPair = kpg.generateKeyPair();
        //得到公钥
        Key publicKey = keyPair.getPublic();
        String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded()); //返回一个publicKey经过二次加密后的字符串
        //得到私钥
        Key privateKey = keyPair.getPrivate();
        String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded()); 返回一个privateKey经过二次加密后的字符串

        Map<String, String> keyPairMap = new HashMap<String, String>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);

        return keyPairMap;
    }

    /**
     * 得到公钥
     * @param publicKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过X509编码的Key指令获得公钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
    }

    /**
     * 得到私钥
     * @param privateKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过PKCS#8编码的Key指令获得私钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    /**
     * 公钥加密
     * @param data
     * @param publicKey
     * @return
     */
    public static String publicEncrypt(String data, RSAPublicKey publicKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
        }catch(Exception e){
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥解密
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateDecrypt(String data, RSAPrivateKey privateKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
        }catch(Exception e){
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥加密
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateEncrypt(String data, RSAPrivateKey privateKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
        }catch(Exception e){
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 公钥解密
     * @param data
     * @param publicKey
     * @return
     */

    public static String publicDecrypt(String data, RSAPublicKey publicKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
        }catch(Exception e){
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
        int maxBlock = 0;
        if(opmode == Cipher.DECRYPT_MODE){
            maxBlock = keySize / 8;
        }else{
            maxBlock = keySize / 8 - 11;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try{
            while(datas.length > offSet){
                if(datas.length-offSet > maxBlock){
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                }else{
                    buff = cipher.doFinal(datas, offSet, datas.length-offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        }catch(Exception e){
            throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);
        }
        byte[] resultDatas = out.toByteArray();
        IOUtils.closeQuietly(out);
        return resultDatas;
    }
}

编写测试类:

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

        System.out.println("公钥加密——私钥解密");
        String str = "寒山月初℃";
        System.out.println("\r明文:\r\n" + str);
        System.out.println("\r明文大小:\r\n" + str.getBytes().length);
        String encodedData = RSAUtil.publicEncrypt(str, RSAUtil.getPublicKey(publicKey));
        System.out.println("密文:\r\n" + encodedData);
        String decodedData = RSAUtil.privateDecrypt(encodedData, RSAUtil.getPrivateKey(privateKey));
        System.out.println("解密后文字: \r\n" + decodedData);
    }

}

运行结果:

公钥:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyrF0HBVsYdA2fTy1iYIWh7j1OoCDzLiBWomWO3Ngn1ajl2wSPk05E7yINxLiTaQSA0H86EWv0jRJrGSdg6kwqzhWv53hza4xEXozLNgDR5L0bxEAmtv1abFALwpMHMPr8NzbpvXHwNaHer6mBrhXDVuyPdgZkWuh0kLrpvXHetQIDAQAB
私钥:
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALKsXQcFWxh0DZ9PLWJghaHuPU6gIPMuIFaiZY7c2CfVqOXbBI-TTkTvIg3EuJNpBIDQfzoRa_SNEmsZJ2DqTCrOFa_neHNrjERejMs2ANHkvRvEQCa2_VpsUAvCkwcw-vw3Num9cfA1od6vqYGuFcNW7I92BmRa6HSQuum9cd61AgMBAAECgYA5KNch9d6stgPdoVDdlg9qPHM0ghnIcks6K_3ddF1acQn1btnIrNFvUClOyk5aKlCcfRcWlpg4xiDMTmHAqXPv_H2AQTqqLdhKC6cz0AZDuiv_itO40rqmvi9n0lcJWP0zq3cJyNlE8ogNsb9heHn_XdPIxD4tdl3QztZQHBfOgQJBAObDr9SBD0EsiGCeULMEj-hEOHsMh0NANpHvNdzKj9xNb28fAZ4H8reRG5frUqpCSTkxgigBwsMhYeQu_ebNoAUCQQDGNl8iVw219K0e3Awwd7TUmM8Ugt8intD1rbYObsYDZlss6rzsm0XzUgkJE9X6xcdu_O5jWZ49mgC3i-jg7HLxAkBZ9h283VdiFAdSi0VwlK25YacXKUouCIF9oODBo2I0AygXDOJnhje0Imi8b-v5HgBHwKo6CH2x7nioKT2oVa81AkByl8KedtfNZ1yjJ7LAXqSj-IhYImVgfZLvRnOnmnFOS-HQcRGydP6W8smYfuhJ6Agp6X7k30317VAWzYNgbjLxAkEAvOYGU33Ll871QFzWTW8eHg1SJMP4oTL3jKuQi5lVMrZTWoCQF_wvuHKAKgIs0AzFwh5vrkNN1fv5QASzwtIGzg
公钥加密——私钥解密
明文:
寒山月初℃
明文大小:
15
密文:
pnQYCefqnlYLZ2wuMcxsbkD9feA3WFcDXShYx6HajvlsriQGWzb4Xxdwz0KTzjz3nqho9AxUc2bZmBhq05v-DCyB14u2NyabENuMXoiKft4QGKNVG3WxGps55xRHr3lVt4Rj59mDBX_manNsQDwxj7gy_Brv6Uv_NRzd6M91aGk
解密后文字:
寒山月初℃                                                                                                                                                                                      Process finished with exit code 0

到此这篇关于教你用Java实现RSA非对称加密算法的文章就介绍到这了,更多相关Java实现RSA非对称加密算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们

(0)

相关推荐

  • Java编程实现非对称加密的方法详解

    本文实例讲述了Java编程实现非对称加密的方法.分享给大家供大家参考,具体如下: 对称加密算法在加密和解密时使用的是同一个秘钥:而非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥). 是一种 高级的双保险加密方式,一般的实现加密方式有DH密钥交换算法,RSA基于因子分解算法,ElGamal离散对数算法及ECC椭圆曲线加密等. DH加密解密 /** * 非对称加密之:DH加密 * 非对称DH,是安全性基于

  • java 非对称加密算法RSA实现详解

    现在就为大家介绍一种基于因子分解的RSA算法,这种加密算法有两种实现形式:1.公钥加密,私钥解密:2.私钥加密,公钥解密.下面就为大家分析一下实现代码,相对于DH算法,RSA显得有些简单. 初始化密钥: KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(512); KeyPair keyPair = keyPairGenerator.g

  • Java 实现常见的非对称加密算法

    概述 非对称加密算法与对称加密算法的主要差别在于非对称加密算法用于加密和解密的密钥不相同,非对称加密算法密钥分为公钥和私钥,公钥加密只能用私钥解密,反之私钥加密只能用公钥解密.相比对称加密算法,非对称加密算法加/解密效率低,但安全性高,这两种算法一般结合使用.常见非对称加密算法有RSA.ECC.Elgamal等. 使用RSA实现加密解密 公钥加密,私钥解密. package com.ss.utils; import javax.crypto.Cipher; import java.securit

  • java 中DH的方式实现非对称加密的实例

    java 中DH的方式实现非对称加密的实例 实现代码: package com.sahadev; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.X509Enco

  • java 非对称加密算法DH实现详解

    非对称加密算法是相对于对称加密算法来说的,对于对称加密算法请查阅之前的总结,今天为大家介绍一下DH算法,DH是一种密钥交换算法,接收方根据发送方加密时的密钥,生成接收方解密密钥.下面就一起来学习一下吧: 初始化发送方密钥: KeyPairGenerator sendKeyPairGenerator = KeyPairGenerator.getInstance("DH"); sendKeyPairGenerator.initialize(512); KeyPair sendKeyPair

  • 解决JAVA非对称加密不同系统加密结果不一致的问题

    最近在做一个项目,需要用到非对称加密,但是出现一个很诡异的情况,本地开发环境是Windows环境,测试环境是Linux环境,出现一个问题, 那就是本地环境与开发环境同一个私钥字符串加密加密同一个信息,得到的加密结果不一样. 经过查询网络得知,这是由于填充的规则不同导致. 原来的加密的部分代码 byte[] keyBytes = Base64.decodeBase64(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedK

  • java结合keytool如何实现非对称加密与解密详解

    前言 参考:java结合keytool实现非对称签名与验证 那一篇讲签名,这一篇将加密解密.在java安全体系中,签名属于JAAS模块,加解密属于JCE模块. keytool的使用 keytool是JDK自带的一个密钥库管理工具.这里只用到了keytool的部分功能,包括生成密钥对,导出公钥等.keytool生成的公钥/私钥对存放到一个到了一个文件中,这个文件有密码保护,通称为keystore. 生成密钥对 $ keytool -genkey -alias signLegal -keystore

  • java 中RSA的方式实现非对称加密的实例

    java 中RSA的方式实现非对称加密的实例 RSA通俗理解: 你只要去想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密:同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证. 实现代码: package com.sahadev; import java.security.KeyFactory; import java.security.KeyPair; import java.se

  • JAVA加密算法- 非对称加密算法(DH,RSA)的详细介绍

    非对称密码概念 1.与对称加密算法的主要差别在于,加密和解密的密钥不相同,一个公开(公钥),一个保密(私钥).主要解决了对称加密算法密钥分配管理的问题,提高了算法安全性. 2.非对称加密算法的加密.解密的效率比较低.在算法设计上,非对称加密算法对待加密的数据长度有着苛刻的要求.例如RSA算法要求待加密的数据不得大于53个字节. 3.非对称加密算法主要用于 交换对称加密算法的密钥,而非数据交换 4.java6提供实现了DH和RSA两种算法.Bouncy Castle提供了E1Gamal算法支持.除

  • 教你用Java实现RSA非对称加密算法

    一.非对称加密 非对称加密算法是一种密钥的保密方法. 非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥).公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密.因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法. 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方:甲方再用自己私钥对加密

  • Java 实现RSA非对称加密算法

    目录 公钥与私钥 Java实现 公钥与私钥 公钥与私钥是成对的,一般的,我们认为的是公钥加密.私钥解密.私钥签名.公钥验证,有人说成私钥加密,公钥解密时不对的. 公钥与私钥的生成有多种方式,可以通过程序生成(下文具体实现),可以通过openssl工具: # 生成一个私钥,推荐使用1024位的秘钥,秘钥以pem格式保存到-out参数指定的文件中,采用PKCS1格式 openssl genrsa -out rsa.pem 1024 # 生成与私钥对应的公钥,生成的是Subject Public Ke

  • C#实现简单的RSA非对称加密算法示例

    本文实例讲述了C#实现简单的RSA非对称加密算法.分享给大家供大家参考,具体如下: 界面控件 namespace RSA算法 { partial class Form1 { /// <summary> /// 必需的设计器变量. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源. /// </summary

  • c# 实现RSA非对称加密算法

    目录 公钥与私钥 C#实现 公钥与私钥 公钥与私钥是成对的,一般的,我们认为的是公钥加密.私钥解密.私钥签名.公钥验证,有人说成私钥加密,公钥解密时不对的. 公钥与私钥的生成有多种方式,可以通过程序生成(下文具体实现),可以通过openssl工具: # 生成一个私钥,推荐使用1024位的秘钥,秘钥以pem格式保存到-out参数指定的文件中,采用PKCS1格式 openssl genrsa -out rsa.pem 1024 # 生成与私钥对应的公钥,生成的是Subject Public Key,

  • 使用openssl实现rsa非对称加密算法示例

    复制代码 代码如下: <?php/** * 使用openssl实现非对称加密 * @since 2010-07-08 */class Rsa{    /**     * private key     */        private $_privKey; /**         * public key         */        private $_pubKey; /**         * the keys saving path         */        privat

  • Python3非对称加密算法RSA实例详解

    本文实例讲述了Python3非对称加密算法RSA.分享给大家供大家参考,具体如下: python3 可以使用 Crypto.PublicKey.RSA 和 rsa 生成公钥.私钥. 其中 python3.6 Crypto 库的安装方式请参考前面一篇<Python3对称加密算法AES.DES3> rsa 加解密的库使用 pip3 install rsa 就行了 C:\WINDOWS\system32>pip3 install rsa Collecting rsa   Downloading

  • 详解PHP使用非对称加密算法RSA

    加密的类型 在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文.目前主流加密手段大致可分为单向加密和双向加密. 单向加密:通过对数据进行摘要计算生成密文,密文不可逆推还原.算法代表:Base64,MD5,SHA; 双向加密:与单向加密相反,可以把密文逆推还原成明文,双向加密又分为对称加密和非对称加密. 对称加密:指数据使用者必须拥有相同的密钥才可以进行加密解密,就像彼此约定的一串暗号.算法代表:DES,3DES,AES,IDEA,RC4,RC5; 非

随机推荐