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. Java执行Shell和传输文件

    特性: 多线程批量执行 多密码尝试 引入依赖: <dependency> <groupId>ch.ethz.ganymed</groupId> <artifa ...

  2. 零基础入门学习Java之注解与反射

    Java反射 Java的程序为什么能在JVM虚拟机中跑起来?接下来将深入探讨下Java虚拟机类加载的机制 1.类的加载 整个Java内存可以分为三大板块 堆 存放new的数组.对象等 栈 存基本变量类 ...

  3. Linux C/C++ 获取进程号、线程号和设置线程名

    1 前言 在Linux开发过程中,设计多线程开发时可以将进程和线程的 id 打印出来,方便开发调试和后期查问题使用,同时也包括设置线程名. 2 函数及头文件 2.1 进程ID #include < ...

  4. SPFA -----队列优化的Bellman-Ford

    SPFA ------队列优化的Bellman-Ford 由Bellman-Ford算法实现带有负权边的单源最短路,时间复杂度是O(VE),也就是边数乘顶点数.但是根据Bellman-Ford的状态转 ...

  5. 洛谷P1308统计单词数,strtok函数的使用以及对于单词分割的一些思考

    [NOIP2011 普及组] 统计单词数 题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能 ...

  6. Delphi TStringList 有趣的CommaText和DelimitedText

    CommaText 在没有指定StrictDelimiter=true的情况下,当列表中项中 包含 空格和逗号的时候就默认的 在这个字符串上面 增加 双引号 很智能吧 例子1: var MyList: ...

  7. NC17890 方格填色

    题目链接 题目 题目描述 给一个m x n的方格,Applese想要给方格填上颜色,每个格子可以是黑色或者白色.他要求左右相邻两格不能同为白色且相邻两列不能全为黑色. 求满足条件的方案数. 输入描述 ...

  8. Linux下csv转Excel xlsx文件保持身份证号后三位不被省略

    在Win下, 可以用Excel 或 WPS Spreadsheet里面的Data->Import, 将csv内容正确导入. 但是在Linux下, WPS的Spreadsheet不提供Data-& ...

  9. 使用html+css+js实现一个仿钉钉打卡按钮

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Spring Boot图书管理系统项目实战-9.归还图书

    导航: pre:  8.续借图书 next:10.借还统计 只挑重点的讲,具体的请看项目源码. 1.项目源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.页面设计 2.1 bookRetur ...