Java非对称加密算法rsa

    接下来我们介绍典型的非对称加密算法——RSA



RSA

    这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。

    这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。



流程分析:

甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。

甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。

乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。





按如上步骤给出序列图,如下:











通过java代码实现如下:Coder类见 Java加密技术(一)

Java代码  收藏代码

import java.security.Key; 

import java.security.KeyFactory; 

import java.security.KeyPair; 

import java.security.KeyPairGenerator; 

import java.security.PrivateKey; 

import java.security.PublicKey; 

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; 

 

/**

* RSA安全编码组件

* 

* @author 梁栋

* @version 1.0

* @since 1.0

*/ 

public abstract class RSACoder extends Coder { 

    public static final String KEY_ALGORITHM = "RSA"; 

    public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; 

 

    private static final String PUBLIC_KEY = "RSAPublicKey"; 

    private static final String PRIVATE_KEY = "RSAPrivateKey"; 

 

    /**

     * 用私钥对信息生成数字签名

     * 

     * @param data

     *            加密数据

     * @param privateKey

     *            私钥

     * 

     * @return

     * @throws Exception

     */ 

    public static String sign(byte[] data, String privateKey) throws Exception { 

        // 解密由base64编码的私钥 

        byte[] keyBytes = decryptBASE64(privateKey); 

 

        // 构造PKCS8EncodedKeySpec对象 

        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 

 

        // KEY_ALGORITHM 指定的加密算法 

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 

 

        // 取私钥匙对象 

        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); 

 

        // 用私钥对信息生成数字签名 

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 

        signature.initSign(priKey); 

        signature.update(data); 

 

        return encryptBASE64(signature.sign()); 

    } 

 

    /**

     * 校验数字签名

     * 

     * @param data

     *            加密数据

     * @param publicKey

     *            公钥

     * @param sign

     *            数字签名

     * 

     * @return 校验成功返回true 失败返回false

     * @throws Exception

     * 

     */ 

    public static boolean verify(byte[] data, String publicKey, String sign) 

            throws Exception { 

 

        // 解密由base64编码的公钥 

        byte[] keyBytes = decryptBASE64(publicKey); 

 

        // 构造X509EncodedKeySpec对象 

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); 

 

        // KEY_ALGORITHM 指定的加密算法 

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 

 

        // 取公钥匙对象 

        PublicKey pubKey = keyFactory.generatePublic(keySpec); 

 

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 

        signature.initVerify(pubKey); 

        signature.update(data); 

 

        // 验证签名是否正常 

        return signature.verify(decryptBASE64(sign)); 

    } 

 

    /**

     * 解密<br>

     * 用私钥解密

     * 

     * @param data

     * @param key

     * @return

     * @throws Exception

     */ 

    public static byte[] decryptByPrivateKey(byte[] data, String key) 

            throws Exception { 

        // 对密钥解密 

        byte[] keyBytes = decryptBASE64(key); 

 

        // 取得私钥 

        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 

        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); 

 

        // 对数据解密 

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 

        cipher.init(Cipher.DECRYPT_MODE, privateKey); 

 

        return cipher.doFinal(data); 

    } 

 

    /**

     * 解密<br>

     * 用公钥解密

     * 

     * @param data

     * @param key

     * @return

     * @throws Exception

     */ 

    public static byte[] decryptByPublicKey(byte[] data, String key) 

            throws Exception { 

        // 对密钥解密 

        byte[] keyBytes = decryptBASE64(key); 

 

        // 取得公钥 

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 

        Key publicKey = keyFactory.generatePublic(x509KeySpec); 

 

        // 对数据解密 

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 

        cipher.init(Cipher.DECRYPT_MODE, publicKey); 

 

        return cipher.doFinal(data); 

    } 

 

    /**

     * 加密<br>

     * 用公钥加密

     * 

     * @param data

     * @param key

     * @return

     * @throws Exception

     */ 

    public static byte[] encryptByPublicKey(byte[] data, String key) 

            throws Exception { 

        // 对公钥解密 

        byte[] keyBytes = decryptBASE64(key); 

 

        // 取得公钥 

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 

        Key publicKey = keyFactory.generatePublic(x509KeySpec); 

 

        // 对数据加密 

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 

        cipher.init(Cipher.ENCRYPT_MODE, publicKey); 

 

        return cipher.doFinal(data); 

    } 

 

    /**

     * 加密<br>

     * 用私钥加密

     * 

     * @param data

     * @param key

     * @return

     * @throws Exception

     */ 

    public static byte[] encryptByPrivateKey(byte[] data, String key) 

            throws Exception { 

        // 对密钥解密 

        byte[] keyBytes = decryptBASE64(key); 

 

        // 取得私钥 

        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 

        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); 

 

        // 对数据加密 

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 

        cipher.init(Cipher.ENCRYPT_MODE, privateKey); 

 

        return cipher.doFinal(data); 

    } 

 

    /**

     * 取得私钥

     * 

     * @param keyMap

     * @return

     * @throws Exception

     */ 

    public static String getPrivateKey(Map<String, Object> keyMap) 

            throws Exception { 

        Key key = (Key) keyMap.get(PRIVATE_KEY); 

 

        return encryptBASE64(key.getEncoded()); 

    } 

 

    /**

     * 取得公钥

     * 

     * @param keyMap

     * @return

     * @throws Exception

     */ 

    public static String getPublicKey(Map<String, Object> keyMap) 

            throws Exception { 

        Key key = (Key) keyMap.get(PUBLIC_KEY); 

 

        return encryptBASE64(key.getEncoded()); 

    } 

 

    /**

     * 初始化密钥

     * 

     * @return

     * @throws Exception

     */ 

    public static Map<String, Object> initKey() throws Exception { 

        KeyPairGenerator keyPairGen = KeyPairGenerator 

                .getInstance(KEY_ALGORITHM); 

        keyPairGen.initialize(1024); 

 

        KeyPair keyPair = keyPairGen.generateKeyPair(); 

 

        // 公钥 

        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 

 

        // 私钥 

        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 

 

        Map<String, Object> keyMap = new HashMap<String, Object>(2); 

 

        keyMap.put(PUBLIC_KEY, publicKey); 

        keyMap.put(PRIVATE_KEY, privateKey); 

        return keyMap; 

    } 

} 



再给出一个测试类:

Java代码  收藏代码

import static org.junit.Assert.*; 

 

import org.junit.Before; 

import org.junit.Test; 

 

import java.util.Map; 

 

/**

* 

* @author 梁栋

* @version 1.0

* @since 1.0

*/ 

public class RSACoderTest { 

    private String publicKey; 

    private String privateKey; 

 

    @Before 

    public void setUp() throws Exception { 

        Map<String, Object> keyMap = RSACoder.initKey(); 

 

        publicKey = RSACoder.getPublicKey(keyMap); 

        privateKey = RSACoder.getPrivateKey(keyMap); 

        System.err.println("公钥: \n\r" + publicKey); 

        System.err.println("私钥: \n\r" + privateKey); 

    } 

 

    @Test 

    public void test() throws Exception { 

        System.err.println("公钥加密——私钥解密"); 

        String inputStr = "abc"; 

        byte[] data = inputStr.getBytes(); 

 

        byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey); 

 

        byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData, 

                privateKey); 

 

        String outputStr = new String(decodedData); 

        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr); 

        assertEquals(inputStr, outputStr); 

 

    } 

 

    @Test 

    public void testSign() throws Exception { 

        System.err.println("私钥加密——公钥解密"); 

        String inputStr = "sign"; 

        byte[] data = inputStr.getBytes(); 

 

        byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey); 

 

        byte[] decodedData = RSACoder 

                .decryptByPublicKey(encodedData, publicKey); 

 

        String outputStr = new String(decodedData); 

        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr); 

        assertEquals(inputStr, outputStr); 

 

        System.err.println("私钥签名——公钥验证签名"); 

        // 产生签名 

        String sign = RSACoder.sign(encodedData, privateKey); 

        System.err.println("签名:\r" + sign); 

 

        // 验证签名 

        boolean status = RSACoder.verify(encodedData, publicKey, sign); 

        System.err.println("状态:\r" + status); 

        assertTrue(status); 

 

    } 

 

} 



控制台输出:

Console代码  收藏代码

公钥:  

 

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J 

EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm 

1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB 

 

私钥:  

 

MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY 

FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3 

GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC 

gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV 

/MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl 

uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D 

rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3 

QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S 

Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV 

o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA 

fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X 

nfpFpBJ2dw== 

 

公钥加密——私钥解密 

加密前: abc 

 

解密后: abc 

公钥:  

 

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF 

9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM 

l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB 

 

私钥:  

 

MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w 

g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI 

PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC 

gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr 

mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY 

j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF 

gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh 

9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW 

9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt 

mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC 

QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2 

I2k1Afmrwyw= 

 

私钥加密——公钥解密 

加密前: sign 

 

解密后: sign 

私钥签名——公钥验证签名 

签名: 

ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+ 

mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn 

i3wwbYWs9wSzIf0UjlM= 

 

状态: 

true 





    简要总结一下,使用公钥加密、私钥解密,完成了乙方到甲方的一次数据传递,通过私钥加密、公钥解密,同时通过私钥签名、公钥验证签名,完成了一次甲方到乙方的数据传递与验证,两次数据传递完成一整套的数据交互!



类似数字签名,数字信封是这样描述的:



数字信封

  数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。

流程:

    信息发送方采用对称密钥来加密信息,然后再用接收方的公钥来加密此对称密钥(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称密钥,然后使用对称密钥再解开信息。

Java加密技术(四)——非对称加密算法RSA的更多相关文章

  1. Java进阶(七)Java加密技术之非对称加密算法RSA

    Java加密技术(四)--非对称加密算法RSA 非对称加密算法--RSA 基本概念 非对称加密算法是一种密钥的保密方法. 非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(priv ...

  2. Java加密技术(四)非对称加密算法RSA

    RSA      这样的算法1978年就出现了.它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作.也非常流行.算法的名字以发明者的名字命名:Ron Rivest, AdiShamir ...

  3. Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC

    Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC 博客分类: Java/Security Javabase64macmd5sha     加密解密,曾经是我一 ...

  4. JAVA 非对称加密算法RSA

    非对称加密算法 RSA过程 : 以甲乙双方为例 1.初始化密钥 构建密钥对,生成公钥.私钥保存到keymap中 KeyPairGenerator ---> KeyPair --> RSAP ...

  5. Java加密技术

    相关链接: Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC Java加密技术(二)——对称加密DES&AES Java加密技术(三)——PBE算法  ...

  6. Java加密技术(八)——数字证书

    原文:http://snowolf.iteye.com/blog/391931 请大家在阅读本篇内容时先阅读 Java加密技术(四),预先了解RSA加密算法. 在构建Java代码实现前,我们需要完成证 ...

  7. 非对称加密算法-RSA算法

    一.概述 1.RSA是基于大数因子分解难题.目前各种主流计算机语言都支持RSA算法的实现 2.java6支持RSA算法 3.RSA算法可以用于数据加密和数字签名 4.RSA算法相对于DES/AES等对 ...

  8. 如何综合运用对称加密技术、非对称加密技术(公钥密码体制)和Hash函数 保证信息的保密性、完整性、可用性和不可否认性?

    一.几个问题 在提出问题之前,先创建一个使用场景,发送方(甲方)要给接收方(乙方)发送投标书.大家知道,投标书都包括发送方的标的,这个标的是不能被竞标者知晓,更不能被竞标者修改的.在传输的投标书时,提 ...

  9. 非对称加密算法——RSA

    RSA     这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作,也很流行.算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和L ...

  10. 非对称加密算法RSA使用注意事项

    原文:非对称加密算法RSA使用注意事项 第一个问题,也是最重要的一个——RSA无法对超过117字节的数据进行加密!切记!其实也勿需要求对更大数据的加密,虽然网上已经有相关解决方案,比如BigInteg ...

随机推荐

  1. 一文搞懂 Vue3 defineModel 双向绑定:告别繁琐代码!

    前言 随着vue3.4版本的发布,defineModel也正式转正了.它可以简化父子组件之间的双向绑定,是目前官方推荐的双向绑定实现方式. vue3.4以前如何实现双向绑定 大家应该都知道v-mode ...

  2. 3.4 CSP-J 补赛游寄

    3.4 CSP-J 补赛游寄 Day -? 听说要去打比赛. Day -7 今天家长会,老师公布成绩 /fn/fn/fn.政治考废了,然后其他都挺好. 语文 $ 95 $,数学 $ 118 $,英语 ...

  3. [Java]Java类中的各元素初始化顺序

    Java类中各元素的初始化顺序 初始化的原则是: 先初始化静态部分,再初始化动态部分:(先静再动) 先初始化父类部分,后初始化子类部分:(先父再子) 先初始化变量,次初始化代码块,再初始化构造器:(先 ...

  4. 探索C语言的内存魔法:动态内存管理解析

    欢迎大家来到贝蒂大讲堂 养成好习惯,先赞后看哦~ 所属专栏:C语言学习 贝蒂的主页:Betty's blog 1. 静态开辟内存 通过前面的学习,我们已经掌握了两种开辟内存的方法,分别是: #incl ...

  5. Linux中查看dmesg中 ata1对应的盘符,以及SATA/NVME SSD的rescan/delete操作方法

    1.查看dmesg 中ata1 对应的盘符: Step1;  lsscsi -s 查看盘符(bdf) 对应的host Id: Step2: ll /sys/class/scsi_host  可以找到不 ...

  6. 欧拉公式 Euler's Formula

    欧拉公式是数学中最重要的公式之一, 它涉及到了复数, 无理数, 三角函数, 简单优美 \(e^{i\theta} = cos(\theta) + isin(\theta)\) 欧拉公式代表的含义并不是 ...

  7. STM32的串口通信UART/TTL

    常用的串口pin STM32的串口是基础通信方式, 每个型号都带多组串口, 一般都使用默认的组, 可以参考芯片的datasheet, 去看pinout and pin definitions, stm ...

  8. 【Unity3D】地形Terrain

    1 前言 ​ Terrain 是 Unity3D 提供的用于绘制地形的游戏对象,可以在其上绘制山地.江海.池塘.草树等. ​ 用户可以通过[GameObject → 3D Object → Terra ...

  9. 掌握云容器网络:何为ipvs

    本文分享自华为云社区<[理解云容器网络]2-基础篇-ipvs介绍>,作者: 可以交个朋友. IPVS简介 ipvs是工作在Linux内核态的4层负载均衡:和用户态的负载均衡软件(如ngin ...

  10. Flink本地模式安装和使用

    Flink官方主页:https://flink.apache.org/ . 安装部署 不同版本的Flink对JDK版本要求不尽相同,需要根据具体的Flink版本要求先安装好JDK环境. 通常,在Fli ...