本文概览:介绍了RSA的简单使用,即“公钥加密-私钥解密”和“私钥加密-公钥解密”。
1 RSA公钥和私钥介绍
1、为什么使用RSA?
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密算法。
RSA是一种非对称加密算法,是对对称加密算法的改进。对称加密算法,是指使用同一个秘钥进行加密和解密,这样一旦秘钥泄漏,那么此时就可以通过这个秘钥把密文生成明文数据。非对称加密算法是指加密和解密的秘钥不一样,如:我们常用RSA的一种方式是“公钥加密-私钥解密”,在这种式下,即使有人获取到公钥,也无法破解数据,因为只有获取到私钥才能解密使用公钥加密的数据,而私钥一般保留在服务器端,不会被窃取。
2、 解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文。RSA使用的流程如下:
流程图源码:
1 2 3 4 5 6 |
title RSA加密解密流程 server->client:生成RSA公钥和RSA私钥。 server->client:将公钥传给使用方 clinet->client:利用公钥对信息进行加密 client->server:将加密后信息发送给server server->server:使用秘钥对密文进行解密 |
2 应用场景
1、加密敏感数据
前端传来的银行卡号、支付密码等信息时,进行加密,后端接受到这些数据再进行解密。一般选择公钥加密-私钥解密的方式。
2、实现签名
数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。参考
3 在项目中使用场景
3 通过java使用RSA
使用RSA加密机密时,经常使用的两种方式为:“私钥加密–公钥解密”和“公钥加密–私钥解密”。
3.1 生成公钥和秘钥
1、生成公钥和私钥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class RsaUtils { /** * 可以把生成的public_key和private_key保存起来 * * @throws Exception */ public static void generatePrivateAndPublicKey() throws Exception { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); // 1.动态生成秘钥对,类似于使用"sh-keygen -t rsa" KeyPair keyPair = keyPairGenerator.generateKeyPair(); //公钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); //私钥 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 2.获取公钥和私钥字符串 // 通过BASE64Encoder#encodeBufferer进行编码,使用的时候通过BASE64Decoder#decodeBuffer进行解码 System.out.println("publicKey=" + (new BASE64Encoder()).encodeBuffer(publicKey.getEncoded())); System.out.println("privateKey=" + (new BASE64Encoder()).encodeBuffer(privateKey.getEncoded())); } } |
执行结果为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsSe0aYcEg6nkDBlT9kd/c4JOI4WtOQCr/NVlB BE1YG4Sd/ri4SajK+Tgz9u6fFDJx9X9iT1vVFkBV87pdL/KJJ7gHADyd0oTB0oMsUxWL1EFXcr4b d2OTsYbreBIHf8o4QQo10VsNT9KNYe2kG93X4LjcboSDt/zgOEuMkComiQIDAQAB privateKey=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKxJ7RphwSDqeQMGVP2R39zgk4jh a05AKv81WUEETVgbhJ3+uLhJqMr5ODP27p8UMnH1f2JPW9UWQFXzul0v8oknuAcAPJ3ShMHSgyxT FYvUQVdyvht3Y5Oxhut4Egd/yjhBCjXRWw1P0o1h7aQb3dfguNxuhIO3/OA4S4yQKiaJAgMBAAEC gYEAp6+EEAtY11qe0SzWh7307pu9vJn5wL1/m8kmx7sSNFEEMGp9CxDWMkeCRkFuWnJj7rqMcvje XnU7xOxlVNGX8gFfFYyrAvC2K5IJ4R4CV4xEQ05Zn8m4+K+jF2PiNaJWxaqHLaxIXFCXmB2/gCt9 vLnNdNv2Cp+cxw/2z0wm/iECQQDTIsNIkz7OGcdevoIbN7HYVUmgRi3HhMQDgRmOMZ7ouBb97ork yMf7P7dNavw4ToSEfgbqYeurFlADLl0nMW8FAkEA0OX8m9ByiBf+6AHRF7imHLhzfuOn9+6poU8i DLTnr1WWZIEeO1i9dMsui+tPYYiQ754wB3Vpm8XTwBdaRwyItQJAcBFJmmIdugPQ4Sc5o/zB91P9 yoa1keuUp0+FIwaPlHLyMULGkn1IOMIvJ3ab/b8fc7v5K7th/ePQAIBBjaYdiQJAc+tbrN8T3x9p rTbs33vwebmFJaGQ4M0IRmISI/jzI+GbjfP0YbxRjZD+KFiQeS/+NWmTf2ARFYbGhS6wQwLajQJA G09GPGWnzbLLXIcMzMtlmR7I2zwHM5ZL1cDddZVFTaw9jdm63fo10AcHY7D18rUzhmaSrX1m5mPY MiMQcfBBmQ== |
2、 为什么要设置为1024位
从网络上摘录如下:
“目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。”
3.2 公钥加密和私钥解密
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
public class RsaUtils { /** * 公钥 */ private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsSe0aYcEg6nkDBlT9kd/c4JOI4WtOQCr/NVlB\n" + "BE1YG4Sd/ri4SajK+Tgz9u6fFDJx9X9iT1vVFkBV87pdL/KJJ7gHADyd0oTB0oMsUxWL1EFXcr4b\n" + "d2OTsYbreBIHf8o4QQo10VsNT9KNYe2kG93X4LjcboSDt/zgOEuMkComiQIDAQAB"; /** * 私钥 */ private static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKxJ7RphwSDqeQMGVP2R39zgk4jh\n" + "a05AKv81WUEETVgbhJ3+uLhJqMr5ODP27p8UMnH1f2JPW9UWQFXzul0v8oknuAcAPJ3ShMHSgyxT\n" + "FYvUQVdyvht3Y5Oxhut4Egd/yjhBCjXRWw1P0o1h7aQb3dfguNxuhIO3/OA4S4yQKiaJAgMBAAEC\n" + "gYEAp6+EEAtY11qe0SzWh7307pu9vJn5wL1/m8kmx7sSNFEEMGp9CxDWMkeCRkFuWnJj7rqMcvje\n" + "XnU7xOxlVNGX8gFfFYyrAvC2K5IJ4R4CV4xEQ05Zn8m4+K+jF2PiNaJWxaqHLaxIXFCXmB2/gCt9\n" + "vLnNdNv2Cp+cxw/2z0wm/iECQQDTIsNIkz7OGcdevoIbN7HYVUmgRi3HhMQDgRmOMZ7ouBb97ork\n" + "yMf7P7dNavw4ToSEfgbqYeurFlADLl0nMW8FAkEA0OX8m9ByiBf+6AHRF7imHLhzfuOn9+6poU8i\n" + "DLTnr1WWZIEeO1i9dMsui+tPYYiQ754wB3Vpm8XTwBdaRwyItQJAcBFJmmIdugPQ4Sc5o/zB91P9\n" + "yoa1keuUp0+FIwaPlHLyMULGkn1IOMIvJ3ab/b8fc7v5K7th/ePQAIBBjaYdiQJAc+tbrN8T3x9p\n" + "rTbs33vwebmFJaGQ4M0IRmISI/jzI+GbjfP0YbxRjZD+KFiQeS/+NWmTf2ARFYbGhS6wQwLajQJA\n" + "G09GPGWnzbLLXIcMzMtlmR7I2zwHM5ZL1cDddZVFTaw9jdm63fo10AcHY7D18rUzhmaSrX1m5mPY\n" + "MiMQcfBBmQ=="; /** * 使用公钥进行加密 * * @param data 明文数据 * @param key 公钥 * @return * @throws Exception */ public static byte[] encryptWithPublicKey(byte[] data, String key) throws Exception { //对公钥解密 byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key); //取公钥 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 私钥解密 * * @param data 密文 * @param key 私钥 * @return */ public static byte[] decryptWithPrivateKey(byte[] data, String key) throws Exception{ //对私钥解密 byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } public static void main(String[] args) throws Exception { // 公钥加密 byte[] screct = RsaUtils.encryptWithPublicKey("12332421eeec".getBytes(), RsaUtils.PUBLIC_KEY); // 私钥解密 byte[] message = RsaUtils.decryptWithPrivateKey(screct,RsaUtils.PRIVATE_KEY); System.out.println("明文为="+new String(message)); } } |
执行结果为:
明文=12332421eeec
3.3 私钥加密和公钥解密
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.Cipher; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; /** * Created by wuzhonghu on 17/2/9. */ public class RsaUtils { /** * 公钥 */ private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsSe0aYcEg6nkDBlT9kd/c4JOI4WtOQCr/NVlB\n" + "BE1YG4Sd/ri4SajK+Tgz9u6fFDJx9X9iT1vVFkBV87pdL/KJJ7gHADyd0oTB0oMsUxWL1EFXcr4b\n" + "d2OTsYbreBIHf8o4QQo10VsNT9KNYe2kG93X4LjcboSDt/zgOEuMkComiQIDAQAB"; /** * 私钥 */ private static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKxJ7RphwSDqeQMGVP2R39zgk4jh\n" + "a05AKv81WUEETVgbhJ3+uLhJqMr5ODP27p8UMnH1f2JPW9UWQFXzul0v8oknuAcAPJ3ShMHSgyxT\n" + "FYvUQVdyvht3Y5Oxhut4Egd/yjhBCjXRWw1P0o1h7aQb3dfguNxuhIO3/OA4S4yQKiaJAgMBAAEC\n" + "gYEAp6+EEAtY11qe0SzWh7307pu9vJn5wL1/m8kmx7sSNFEEMGp9CxDWMkeCRkFuWnJj7rqMcvje\n" + "XnU7xOxlVNGX8gFfFYyrAvC2K5IJ4R4CV4xEQ05Zn8m4+K+jF2PiNaJWxaqHLaxIXFCXmB2/gCt9\n" + "vLnNdNv2Cp+cxw/2z0wm/iECQQDTIsNIkz7OGcdevoIbN7HYVUmgRi3HhMQDgRmOMZ7ouBb97ork\n" + "yMf7P7dNavw4ToSEfgbqYeurFlADLl0nMW8FAkEA0OX8m9ByiBf+6AHRF7imHLhzfuOn9+6poU8i\n" + "DLTnr1WWZIEeO1i9dMsui+tPYYiQ754wB3Vpm8XTwBdaRwyItQJAcBFJmmIdugPQ4Sc5o/zB91P9\n" + "yoa1keuUp0+FIwaPlHLyMULGkn1IOMIvJ3ab/b8fc7v5K7th/ePQAIBBjaYdiQJAc+tbrN8T3x9p\n" + "rTbs33vwebmFJaGQ4M0IRmISI/jzI+GbjfP0YbxRjZD+KFiQeS/+NWmTf2ARFYbGhS6wQwLajQJA\n" + "G09GPGWnzbLLXIcMzMtlmR7I2zwHM5ZL1cDddZVFTaw9jdm63fo10AcHY7D18rUzhmaSrX1m5mPY\n" + "MiMQcfBBmQ=="; /** * 用私钥进行加密 * * @param data 明文数据 * @param key 私钥 * @return */ public static byte[] encryptWithPrivateKey(byte[] data, String key) throws Exception { // 1.对私使用BASEDecoder钥解密 byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key); // 2.获取私钥 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); // 3.对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 使用公钥进行解密 * * @param data 明文 * @param key 公钥 * @return * @throws Exception */ public static byte[] decryptWithPublicKey(byte[] data, String key) throws Exception { // 1.对私使用BASEDecoder钥解密 byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key); // 2.获取公钥 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); // 3.对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } public static void main(String[] args) throws Exception { // 公钥加密 byte[] screct = RsaUtils.encryptWithPrivateKey("12332421eeec".getBytes(), RsaUtils.PRIVATE_KEY); // 私钥解密 byte[] message = RsaUtils.decryptWithPublicKey(screct, RsaUtils.PUBLIC_KEY); System.out.println("明文为=" + new String(message)); } } |
执行结果为
明文=12332421eeec
4 参考文献
1、RSA算法原理(一) http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
2、 RSA算法原理(二)http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
(==全文完==)