RSA加密&解密【Java&Scala】
一.简介
RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。
RSA公开密钥密码体制。所谓公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,由于无法计算出大数n的欧拉函数phi(N),所以不能根据PK计算出SK。
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,截止2017年被普遍认为是最优秀的公钥方案之一。
二.代码实现【Java版】
1 package cn.ai; 2 3 import java.io.UnsupportedEncodingException; 4 import java.security.InvalidKeyException; 5 import java.security.KeyFactory; 6 import java.security.KeyPair; 7 import java.security.KeyPairGenerator; 8 import java.security.NoSuchAlgorithmException; 9 import java.security.SecureRandom; 10 import java.security.interfaces.RSAPrivateKey; 11 import java.security.interfaces.RSAPublicKey; 12 import java.security.spec.InvalidKeySpecException; 13 import java.security.spec.PKCS8EncodedKeySpec; 14 import java.security.spec.X509EncodedKeySpec; 15 import java.util.HashMap; 16 import java.util.Map; 17 18 import javax.crypto.BadPaddingException; 19 import javax.crypto.Cipher; 20 import javax.crypto.IllegalBlockSizeException; 21 import javax.crypto.NoSuchPaddingException; 22 23 import org.apache.commons.codec.binary.Base64; 24 25 public class RSACrypt { 26 27 private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); 28 29 /** 30 * 初始化生成公钥和私钥 31 * @throws NoSuchAlgorithmException 32 */ 33 public static void init() throws NoSuchAlgorithmException{ 34 /** 35 * KeyPairGenerator用于生成公钥和私钥对,基于RSA算法生成对象 36 */ 37 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); 38 /** 39 * 初始化秘钥对生成器,秘钥大小为1024位 40 */ 41 keyPairGen.initialize(1024, new SecureRandom()); 42 /** 43 * 生成秘钥 44 */ 45 KeyPair keyPair = keyPairGen.generateKeyPair(); 46 /** 47 * 获取私钥 48 */ 49 RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate(); 50 String privateKeyStr = new String(Base64.encodeBase64(privateKey.getEncoded())); 51 /** 52 * 获取公钥 53 */ 54 RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic(); 55 String publicKeyStr = new String(Base64.encodeBase64(publicKey.getEncoded())); 56 57 /** 58 * 保存公钥,私钥 59 */ 60 keyMap.put(0, publicKeyStr); // 公钥 61 keyMap.put(1, privateKeyStr);// 私钥 62 } 63 64 /** 65 * 公钥加密 66 * @throws NoSuchAlgorithmException 67 * @throws InvalidKeySpecException 68 * @throws Exception 69 */ 70 public static String rsaEncrypt(String content, String publicKey) throws InvalidKeySpecException, NoSuchAlgorithmException, Exception{ 71 //base64编码的公钥 72 byte[] encoded = Base64.decodeBase64(publicKey); 73 RSAPublicKey rsaPublicKey = (RSAPublicKey)KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(encoded)); 74 // RSA加密 75 Cipher cipher = Cipher.getInstance("RSA"); 76 cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey); 77 78 String outPublicKey = Base64.encodeBase64String(cipher.doFinal(content.getBytes("UTF-8"))); 79 80 return outPublicKey; 81 } 82 83 /** 84 * 私钥解密 85 * @throws UnsupportedEncodingException 86 * @throws NoSuchAlgorithmException 87 * @throws InvalidKeySpecException 88 * @throws NoSuchPaddingException 89 * @throws InvalidKeyException 90 * @throws BadPaddingException 91 * @throws IllegalBlockSizeException 92 * @throws Exception 93 */ 94 public static String rsaDecrypt(String content, String privateKey) throws UnsupportedEncodingException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{ 95 //base64位解码加密后的字符串 96 byte[] inputByte = Base64.decodeBase64(content.getBytes("UTF-8")); 97 //base64编码的私钥 98 byte[] decoded = Base64.decodeBase64(privateKey); 99 RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); 100 //RSA解密 101 Cipher cipher = Cipher.getInstance("RSA"); 102 cipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey); 103 String outPrivateKey = new String(cipher.doFinal(inputByte)); 104 return outPrivateKey; 105 } 106 107 public static void main(String[] args) throws Exception { 108 /** 109 * 初始化生成公钥,私钥 110 */ 111 init(); 112 /** 113 * 加密数据 114 */ 115 String message = "abc123"; 116 System.out.println("随机生成的公钥为:" + keyMap.get(0)); 117 System.out.println("随机生成的私钥为:" + keyMap.get(1)); 118 119 System.out.println("加密前的数据:" + message); 120 String messageEncrypt = rsaEncrypt(message, keyMap.get(0)); 121 System.out.println("加密后的数据:" + messageEncrypt); 122 123 //String mid = "MIIc" + keyMap.get(1).substring(4, keyMap.get(1).length()); 124 //System.out.println("随机生成的私钥为:" + mid); 125 String messageDecrypt = rsaDecrypt(messageEncrypt, keyMap.get(1)); 126 System.out.println("解密后的数据:" + messageDecrypt); 127 } 128 129 }
三.结果【Java版】
1 随机生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzveY+Gdrm4gY2IGT+M1yESXHPLSS7Nq/iex4h2oI3x0kSvYOoepQSPUhZvnUJEsrnYHKI9CZPJXNchqQFdR2Zy70GX/58yA700PVpk278z32aZ4OFkqhrmtULRiwF/ILpjucr7dIrgOU+hFTKHHc0fqhtHVWZVYcf1ZyKP8fQBwIDAQAB 2 随机生成的私钥为:MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALO95j4Z2ubiBjYgZP4zXIRJcc8tJLs2r+J7HiHagjfHSRK9g6h6lBI9SFm+dQkSyudgcoj0Jk8lc1yGpAV1HZnLvQZf/nzIDvTQ9WmTbvzPfZpng4WSqGua1QtGLAX8gumO5yvt0iuA5T6EVMocdzR+qG0dVZlVhx/VnIo/x9AHAgMBAAECgYAV9yoRAsXem1aY/MJ60joHLJaM8/5eJqO98L/Q8UwilucWNDTHvRslU3npBb51umczeXTlybh4yaHcd9PJmvNf6LI0LsCAWEqW6Y4/1kX2ro8w/a5uLLZMECa9q0xkn0+QWMMrcHxzUVhlott5lDx9ejiW+a3KpNscQLSxgZSeAQJBAN2N45wUFSvcGFZAOwHL6YpCIrECokdhFFp+eABPYJb+rDFfFyiiK8THk/osD2l0Tqtdl+mPJEAbXU1aK0VdnQECQQDPr9OwC0rpvttzq6TiEJ4S1Dz3kZwS2NkrukbgqWkGpC7HggBjYYyrujoEpEnPvqnm6oTWCDqh+YRWC6RMp4UHAkAJCwiWT0+J6cLoilieOyd+KDLoTLY4+aJuCyl0wcisgRqgLURxuSTWNFs649+BK2kmn3xa4SfWogdN5/dKLocBAkACeZjvNyM8Z97boQcE/qezl73mQWD3xIfKAp1Hnh03TAuWqxDwHkB752s7lO2gQShrLQ5KMqzoMz4FfHwHwdNPAkEAtNG3NONm0f4McwEYyxXkrlLWisf67xkTo6rLfxnf7f+xk8W6u6kf339AZlfOUv5I1BZKfka3hUxaXlpsYmQ0Xg== 3 加密前的数据:abc123 4 加密后的数据:s4P8ihNvDHdqB3libM2lj8eC37TQK/UBrUIKM4If42oMYiCVo/4q07FPLfDYCBMEa9sbdDSFA1mcXiWRvwIH+658Nu+dLSe1SQfuwI+7q0KbP0lQeCh3SkBvTqAt0BmEnpDvSUzn1FH/W8Wlqet9IBsTU7mZioXZ9jCSTvKvU8w= 5 解密后的数据:abc123
四.代码实现【Scala版】
1 package big.data.analyse.encryption 2 3 import java.security.spec.{PKCS8EncodedKeySpec, X509EncodedKeySpec} 4 import java.security.{KeyFactory, SecureRandom, KeyPairGenerator} 5 import javax.crypto.Cipher 6 7 import org.apache.commons.codec.binary.Base64 8 9 /** 10 * Created by zhen on 2019/6/15. 11 */ 12 object RSA { 13 var keyMap : Map[Int, String] = Map() 14 15 /** 16 * 初始化公钥,私钥 17 */ 18 def init(): Unit ={ 19 val keyPairGenerator = KeyPairGenerator.getInstance("RSA") 20 keyPairGenerator.initialize(1024, new SecureRandom()) 21 val keyPair = keyPairGenerator.generateKeyPair() 22 val privateKey = keyPair.getPrivate 23 val privateKeyStr = new String(Base64.encodeBase64(privateKey.getEncoded)) 24 25 val publicKey = keyPair.getPublic 26 val publicKeyStr = new String(Base64.encodeBase64(publicKey.getEncoded)) 27 28 keyMap += (0 -> publicKeyStr) // 0表示公钥 29 keyMap += (1 -> privateKeyStr) // 1表示私钥 30 } 31 32 /** 33 * 公钥加密 34 */ 35 def rsaEncrypt(content : String, publicKey : String): String ={ 36 val encoded = Base64.decodeBase64(publicKey) 37 val rsaPublicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(encoded)) 38 39 val cipher = Cipher.getInstance("RSA") 40 cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey) 41 42 val enContent = Base64.encodeBase64String(cipher.doFinal(content.getBytes("UTF-8"))) 43 44 return enContent 45 } 46 47 /** 48 * 私钥解密 49 */ 50 def rsaDecrypt(content : String, privateKey : String): String ={ 51 val bytes = Base64.decodeBase64(content.getBytes("UTF-8")) 52 val decoded = Base64.decodeBase64(privateKey) 53 val rsaPrivateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)) 54 55 val cipher = Cipher.getInstance("RSA") 56 cipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey) 57 58 val deContent = new String(cipher.doFinal(bytes)) 59 60 return deContent 61 } 62 63 /** 64 * 测试 65 * @param args 66 */ 67 def main(args: Array[String]) { 68 69 /** 70 * 初始化加密算法 71 */ 72 init() 73 println("公钥:" +keyMap.get(0).get+ "\n私钥:" + keyMap.get(1).get) 74 75 /** 76 * 加密内容 77 */ 78 val content = "abc123" 79 println("加密前的数据:" + content) 80 81 /** 82 * 加密 83 */ 84 val enContent = rsaEncrypt(content, keyMap.get(0).get) 85 println("加密后的数据:" + enContent) 86 87 /** 88 * 解密 89 */ 90 val deContent = rsaDecrypt(enContent, keyMap.get(1).get) 91 println("解密后的数据:" + deContent) 92 } 93 }
五.结果【Scala版】
1 公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpWv6go/JB6/fgkFobB8UNG9yGEPEdJnRxy26YISXb2ACRvC1BZ4bKECdnVk5EMwEyIxtfYLbvf0PjVq1CYAimYd6D97teWSQM0ZsdYYzUeSz+KJABugt4A4LNitnfmn1jOToSdjlXZIlrzKQtNxXi4fEFHqg5CMUgrbU40amrcQIDAQAB 2 私钥:MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKla/qCj8kHr9+CQWhsHxQ0b3IYQ8R0mdHHLbpghJdvYAJG8LUFnhsoQJ2dWTkQzATIjG19gtu9/Q+NWrUJgCKZh3oP3u15ZJAzRmx1hjNR5LP4okAG6C3gDgs2K2d+afWM5OhJ2OVdkiWvMpC03FeLh8QUeqDkIxSCttTjRqatxAgMBAAECgYAOIpgqFET+F5Hi3mmG5AkgZPjs/7EAO9twPAiJDgs45Dh38XrdgKSRbPO8/kkeDBvHcYKxXUMnjjm+WdewOI/AIJfhRD4dSW7vLEhDAD/sWN2gop34uFLIwFI4XESvdlObqFU082HqsiC6qP4b2/W5S5JDSx2kQaRLppl1/wX6mQJBANdhmlp2S3aHalKqdViTyLmwqDmQQQDCrdLUs0BCJIJBaRWiN5EbLeCF4EtbCN8Pe6KtiV1R1ZnAlvm7dVlCldMCQQDJS09ybefxe/CApr6ppK7bwSf2vVOqDO2dBm46oapK6otpSSt1USvah0yGNenu7hoPFFyFe3vlrbV3dQJBFdsrAkEAv67Xxma9ZnHCCGw4H2r3G3vDW+esUlbwiFBQb4HuKBa6xUwnk/bSb532LlqInKyU5gT32Zu5NCsYso1JNPVzjQJBAJNruWKnxW/hAlFmTUq21m0Q+HDHVce7siYHOKFuFubJAZL5SH+iFAj2f//m6k3XSXRzyBLmTeX3I2i6ZA1AsYMCQQCXnuh0VjBTqSrvrEWXlnyiQ1cpQdmAhI6YlnKW3Mcd6jjekCjAG7CXU1N845Ax7btTlF1Ca+vwcaVzm0oF80mQ 3 加密前的数据:abc123 4 加密后的数据:jcSjLubNx/1Vk4FEWBwukb8FK3w/QMNZ6UY5lZxLuMxvQ+sl/9cndIh5wNRkzowxmxDQnNcMlUQ5qwIvKnExSVXfBuoRKBH7J+9q7yb1XQR+m+r53djTrNbV15wztHO7KDh4bhlUSbv217OkTdBMb8Exh4aKuih7cUdsD9XQ+60= 5 解密后的数据:abc123