请注明出处。 http://blog.csdn.net/Zhao yanjun6/article/details/120316606
本文来自【dydfj的博客】
本文目录建议RSA概述RSA中常见的加密填充模型的实际操作注意事项RSA/ECB/PKCS1Padding封装类RSA在缺省情况下实现Https证书签名验证过程
推荐
AES加密-详细信息
RSA加密:详细信息
RSA配置文件RSA——不对称加密生成公钥和私钥。 公钥在客户端,私钥在服务器端。 公钥用于加密,私钥用于解密。
RSA其实是三位数学家名字的缩写,1977年,三位数学家Rivest、Shamir、Adleman设计了实现非对称加密的算法。 该算法以三个人的名字命名,称为RSA算法。 从那时到现在,RSA算法是应用最广泛的“不对称加密算法”。 毫不夸张地说,有计算机网络的地方就有RSA算法。
1977年的RSA论文中说,分解75位的十进制数大约需要104天。 人类的技术进步如此惊人!
进攻方的矛盾越来越尖锐,防守方的盾牌就必须越来越厚。 因此,1024位RSA已经不安全,并且APP应用系统不应使用小于2048位的公钥值。 如果需要高安全性,请选择4096位RSA。
RSA中常用的加密填充模式RSA/none/PKcs1padding RSA/ECB/PK CS1 padding Java的默认RSA实现是RSA/none/PK CS1 padding,默认实现是
cipher cipher=cipher.getinstance (RSA ); 使用模式类型Cipher生成的密文总是不匹配。 Bouncy Castle的默认RSA实现为RSA/None/NoPadding。
为什么Java的缺省RSA实现每次生成的密文都不一致呢? 可以每次使用相同的明文、相同的公钥吗? 这是因为RSA的PKCS #1 padding方式在加密前用随机数填充了明文信息。
实际运用上的注意事项1,一般由服务器制作私钥对,私钥保存在服务器上,公钥分发到客户端
2、公钥是二进制数据,怎么发送到客户端?
第一种方法是服务器将二进制数据写入文件,然后将文件传递给客户端。 客户端从文件中读取二进制数据。
第二种方式是服务器将二进制数据转换为base64字符串,客户端获取base64字符串后,转码为二进制数据。
3、用同一公钥加密的数据每次都不同。 这是因为RSA的填充方式在加密前对明文信息进行了随机填充。 但是,不影响解码的结果
4、如果要创建RSA私钥对,则长度优选选择2048的整数倍。 长度为1024,在今天的网络上不安全。
存档实战RSA/ECB/PKCS1Padding包类RSA加密工具类
import javax.crypto.Cipher; 输入Java.security.*; import Java.security.interfaces.RSA private key; import Java.security.interfaces.RSA public key; import Java.security.spec.pkcs8 encodedkeyspec; import Java.security.spec.x509 encodedkeyspec; public class RSA { /** *公钥加密* * @ param data * @ param public key * @ return * @ throws exception */public stic byte [ ] en crycrychen byte [ ]公共密钥(throws exception (/公钥对象x509 encodedkeyspeckeyspec=new x509 encodedkeyspec )公共密钥); keyfactory keyfactory=keyfactory.getinstance (' RSA ); public key pubkey=keyfactory.generate public (key spec ); //加密数据cipher CP=cipher.getinstance (RSA/ECB/PK CS1 padding ); CP.init(cipher.encrypt_mode,pubKey ); returnCP.dofinal(data; } /** *使用私钥解密* * @ param encrypted * @ param private key * @ return * @ throws exception */public static byt
e[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { // 得到私钥对象 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance("RSA"); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 解密数据 Cipher cp = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr = cp.doFinal(encrypted); return arr; } /** * 创建非对称加密RSA秘钥对 * @param keyLength * @return * @throws NoSuchAlgorithmException */ public static KeyPair generateRSAKeyPair(int keyLength) throws NoSuchAlgorithmException { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(keyLength); return kpg.genKeyPair(); } /** * 获取公钥,打印为48-12613448136942-12272-122-913111503-126115048-12...等等一长串用-拼接的数字 */ public static byte[] getPublicKey(KeyPair keyPair) { RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); return rsaPublicKey.getEncoded(); } /** * 获取私钥,同上 */ public static byte[] getPrivateKey(KeyPair keyPair) { RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); return rsaPrivateKey.getEncoded(); }}测试代码
import java.nio.charset.StandardCharsets;import java.security.KeyPair;import java.util.Base64;public class Test { public static void main(String[] args) { String message = "星期二,我好开心哦"; try { //创建秘钥对 KeyPair keyPair = RSA.generateRSAKeyPair(1024); //获取公钥 byte[] publicKey = RSA.getPublicKey(keyPair); //获取私钥 byte[] privateKey = RSA.getPrivateKey(keyPair); //公钥base64编码 String publicBase64 = Base64.getEncoder().encodeToString(publicKey); System.out.println("publicBase64 = " + publicBase64); //加密 byte[] enResult = RSA.encryptByPublicKey(message.getBytes(), publicKey); //解密 byte[] deResult = RSA.decryptByPrivateKey(enResult, privateKey); System.out.println("解密=" + new String(deResult, StandardCharsets.UTF_8)); } catch (Exception e) { e.printStackTrace(); } }}测试结果:
解密=星期二,我好开心哦 RSA 默认实现主要就是下面这一句代码:
Cipher cp = Cipher.getInstance("RSA");完整代码如下:
import javax.crypto.Cipher;import java.security.*;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;public class RSA { /** * 使用公钥加密 * * @param data * @param publicKey * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥对象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey pubKey = keyFactory.generatePublic(keySpec); // 加密数据 Cipher cp = Cipher.getInstance("RSA"); cp.init(Cipher.ENCRYPT_MODE, pubKey); return cp.doFinal(data); } /** * 使用私钥解密 * * @param encrypted * @param privateKey * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { // 得到私钥对象 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance("RSA"); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 解密数据 Cipher cp = Cipher.getInstance("RSA"); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr = cp.doFinal(encrypted); return arr; } /** * 创建非对称加密RSA秘钥对 * * @param keyLength * @return * @throws NoSuchAlgorithmException */ public static KeyPair generateRSAKeyPair(int keyLength) throws NoSuchAlgorithmException { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(keyLength); return kpg.genKeyPair(); } /** * 获取公钥,打印为48-12613448136942-12272-122-913111503-126115048-12...等等一长串用-拼接的数字 */ public static byte[] getPublicKey(KeyPair keyPair) { RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); return rsaPublicKey.getEncoded(); } /** * 获取私钥,同上 */ public static byte[] getPrivateKey(KeyPair keyPair) { RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); return rsaPrivateKey.getEncoded(); }} Https 证书我们看一下百度的 https 证书信息
公钥信息是 RSA 算法。
Https 协议是结合了非对称加密和对称加密一起工作,从而保证数据传输的安全性的。
非对称加密用于确保客户端可以安全地获取到服务器的真实公钥。
对称加密用于确保客户端和服务器之间的数据传输不会被任何人监听和解密,因为对称加密使用的密钥只有客户端和服务器这两者知道,其他任何人在不知道密钥的情况下都无法对传输数据进行解密。
数字签名是什么?
为什么如此安全的https协议却仍然可以被抓包呢?
写一篇最好懂的HTTPS讲解
签名认证过程为什么会有签名认证?