添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

RSA 简介
RSA——非对称加密,会产生公钥和私钥,公钥在客户端,私钥在服务端。公钥用于加密,私钥用于解密。

RSA 其实是三位数学家名字的缩写,1977年,三位数学家 Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。

在1977年的RSA论文里,提到分解一个75位十进制数字大约需要104天。人类的技术进步是如此惊人!

当攻方的矛越来越锋利时,守方的盾就必须越来越厚重。所以,1024比特RSA已经不安全,应用系统不应该使用少于2048比特的公钥 值。而当需要高安全性时,选择4096比特RSA。

RSA 常用的加密填充模式
RSA/None/PKCS1Padding
RSA/ECB/PKCS1Padding
Java 默认的 RSA 实现是 RSA/None/PKCS1Padding , 默认实现如下:

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加密管理类

package com.phone.common_library.manager;

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class RSAManager {


/**
* 使用公钥加密
*
* @param data
* @param publicKey
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) {
// 得到公钥对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = null;
// 加密数据
Cipher cp = null;
byte[] byteArr = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
// 加密数据
cp = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cp.init(Cipher.ENCRYPT_MODE, pubKey);
byteArr = cp.doFinal(data);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}

return byteArr;
}

/**
* 使用私钥解密
*
* @param encrypted
* @param privateKey
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) {
// 得到私钥对象
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = null;
byte[] byteArr = null;
try {
kf = KeyFactory.getInstance("RSA");
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
// 解密数据
Cipher cp = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cp.init(Cipher.DECRYPT_MODE, keyPrivate);
byteArr = cp.doFinal(encrypted);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return byteArr;
}

/**
* 创建非对称加密RSA秘钥对
*
* @param keyLength
* @return
* @throws NoSuchAlgorithmException
*/
public static KeyPair generateRSAKeyPair(int keyLength) {
KeyPairGenerator kpg = null;
try {
kpg = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

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();
}

}

如何使用?

String message = "Trump is yellow hair";

//创建秘钥对
KeyPair keyPair = RSAManager.generateRSAKeyPair(2048);
//获取公钥
byte[] publicKey = RSAManager.getPublicKey(keyPair);
//获取私钥
byte[] privateKey = RSAManager.getPrivateKey(keyPair);
//公钥base64编码
//            String publicBase64 = Base64.getEncoder().encodeToString(publicKey);
//            String publicBase64 = Base64.encodeToString(publicKey, Base64.DEFAULT);
BASE64Encoder encoder = new BASE64Encoder();
String publicBase64 = encoder.encodeBuffer(publicKey).trim();
LogManager.i(TAG, "publicBase64*****" + publicBase64);

//加密
byte[] encryptResult = RSAManager.encryptByPublicKey(message.getBytes(), publicKey);
//解密
byte[] decryptResult = RSAManager.decryptByPrivateKey(encryptResult, privateKey);
LogManager.i(TAG, "解密*****" + new String(decryptResult, StandardCharsets.UTF_8));

打印的日志如下

2022-07-21 15:43:45.960 3757-3757/com.phone.rxjava2andretrofit2 I/MineActivity: publicBase64*****MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqYP560CfS7gihDI3nABjMehyZ8fmsz/P
V5BtWxFjNU522hMMI1rpqZoPY8mpfcMJMFjMIvjzFHhz5ZbPWNbDNBt4JdiudtYQ49gwdokwuPcA
86kYh28sBM2VcACmWmqS7q9NY6n3mpI8hjFw6VEBAQ6FqR2k81CfvugrdDyJmk87kCuZQaUqkhf2
jT/T7sWNV66Eshh7FCSBDGMYf0MMQKL0NMFqQ7wiJPI5wdvl2TQFy/nkVrBxR3avx7W8IcmkcvXu
bdxv8M2FybIIQvocrN40cnKY84JDyhPFSEllSjhwMKgpjZpCEzi/dGCCvWB3NLe4agAvJwKlLMAH
BH/NIwIDAQAB
2022-07-21 15:43:45.970 3757-3757/com.phone.rxjava2andretrofit2 I/MineActivity: 解密*****Trump is yellow hair
知识拓展
Https 证书
我们看一下百度的 https 证书信息

公钥信息是 RSA 算法。

Https 协议是结合了非对称加密和对称加密一起工作,从而保证数据传输的安全性的。

非对称加密用于确保客户端可以安全地获取到服务器的真实公钥。
对称加密用于确保客户端和服务器之间的数据传输不会被任何人监听和解密,因为对称加密使用的密钥只有客户端和服务器这两者知道,其他任何人在不知道密钥的情况下都无法对传输数据进行解密。

数字签名是什么? - 阮一峰的网络日志

为什么如此安全的https协议却仍然可以被抓包呢?_guolin的博客-CSDN博客

写一篇最好懂的HTTPS讲解_guolin的博客-CSDN博客_https 郭霖

签名认证过程
为什么会有签名认证?

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:RxJava2和Retrofit2项目,添加自动管理token功能,添加RxJava2生命周期管理,使用App架构设计是MVP模式和MVVM模式,同时使用组件化,部分代码使用Kotlin,此项目持续维护中。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/NakajimaFN/article/details/125913821

原文链接: https://blog.csdn.net/NakajimaFN/article/details/125913821 RSA 的 使用 方式 加密 方式解密方式签名方式验签(检验签名)总结说明 一小部分人在学习 RSA 原理之后仍不清楚其 使用 的方式,在 使用 时将其理论讲错。本文厘清其 使用 方式,避免大家的误解。 加密 方式 非对称 加密 的 使用 是非常环境下传输安全信息。换句话来说, 加密 方式的 使用 场景就是我想给你说句话,但别人不知道内容。 经常举例Alice和Bob的通信息过程,如果是Alice想通知Bob一个信息,那么必须 使用 Bob的公钥对信息 加密 ,此时由于只有私钥能解,也就意味着只有Bob能拿到这个信息的真正明文。 但是,这里很多人都以为Bob 1、一般由服务器创建秘钥对,私钥保存在服务器,公钥下发至客户端 2、公钥是二进制数据,怎么下发给客户端呢? 第一种方式:服务器把二进制数据写入文件,然后把文件传给客户端。由客户端从文件读取二进制数据。 第二种方式:服务器把二进制数据转成 base64 字符串,客户端获取到 base64 字符串后,再转码为二进制数据。 我们封存一 原本是不想写的,因为这个APP的这个版本其实很简单,后来想了下觉得还行记录一下吧。主要是记录每一次逆向能加深其中学到的知识点内容。也算是给自己一个交代,无论以后还是菜鸡也好还是成了大牛也罢,至少这一刻我没有虚度。... I am using " RSA /None/PKCS1Padding" as :Cipher RSA Cipher = Cipher.getInstance(" RSA /None/PKCS1Padding");This gives me exception as :java.security.NoSuchAlgorithmException: Cannot find any provider suppo... 前一篇文章:http://blog.csdn.net/qq372848728/article/details/78687876int rsa _key_encrypt(EVP_PKEY *key, const unsigned char *orig_data, size_t orig_data_len, unsigned char *enc_data, size_t &enc_data_len 随着大环境对隐私、数据安全的要求越来越高,我们日常开发工作中遇到数据安全处理的需求也越来越多,多数情况下都会有专门的安全团队提供完整的解决方案,我们按照对应的文档处理就能很好地解决问题。但是有这样的安全团队支持,并不代表我们不需要对安全知识有一定的了解。作为一名优秀的程序员,还是要适当对别人封装好的技术方案有一定的专研精神,一方面是可以拓宽自己的技术边界,另一方面也可以帮助我们在和安全团队对接方案时有更多的共同认知,提高沟通和接入效率。 RSA 是一种非对称 加密 算法, 加密 和解密 使用 不同的密钥。通信双方各握有一对密钥(称为公钥和私钥)中的一把,己方密钥 加密 的数据,只有对方密钥能够解密。 RSA 基于一个数论事实:将两个大素数相乘十分容易,但想要对其乘积进行因式分解却极其困 难,因此可以将乘积公开作为 加密 密钥,即公钥,而两个大素数组合成私钥。公钥是可提供给任何人 使用 ,私钥则为自己所有,供解密之用。 我正在为ios和Android开发应用程序。我对 加密 任务相对来说比较陌生,在过去的3天里,由于无法运行 RSA 加密 ,所以我一直在抨击我的头部。两个客户端都从java服务器接收公钥。在Android中我有(显然,因为它几乎与服务器端的代码相同)没有问题,但是ios部分似乎根本不兼容。我想用公钥来 加密 一小段数据(aes key),这就是我在Java中如何做到的:try {String publickey...