RSA
1. 数学原理
1.1 离散对数问题
我们要想一个加密容易,破解很难的数学运算。
方案:
我们知道?后计算出12很容易,但是知道12反推?只能通过枚举。若取模的数是质数n,那么可能性就有n-1种,比如17就有17-1=16种可能(可参考上面的列举)。如果n是特别大的质数,那么反推就基本不可能了。
1.2 欧拉函数
-
互质关系
如果两个正整数,除了1以外,没有其他公因数,我们就称这两个数是互质关系。
-
欧拉函数
其中,是
的所有质因数。(质因数是一个能整除给定正整数的质数。)
- 当n是质数的时候
。
- 如果n可以分解成两个互质的整数之积,如
则
。
- 特殊的,若N是两个质数P1和P2的乘积,则
。
- 当n是质数的时候
任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?
计算8的欧拉函数,和8互质的1、3、5、7,则。用公式计算8的质因数只有2,
。
计算7的欧拉函数,和7互质的1、2、3、4、5、6,则。
那56的欧拉函数是多少呢?。
-
原根
设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。
即假设一个数a是m的原根,那么
的结果两两不同,且有
。
刚刚举例的
3就是17的原根。
1.3 欧拉定理
-
欧拉定理
如果两个正整数m和n互质,那么m的φ(n)次方减去1,可以被n整除。
-
费马小定理
欧拉定理的特殊情况:如果两个正整数m和n互质,而且n为质数!那么φ(n)结果就是n-1。
我们下面进行一些推导:
由于
由于
-
模反元素
如果两个正整数e和x互质,那么一定可以找到整数d,使得ed-1被x整除。那么d就是e对于x的“模反元素”。
再转译一下:
正整数e和x互质,假设于e互质,那么有:
2. 迪菲赫尔曼秘钥交换
-
假设客户端、服务端规定
,两端的计算公式就是
。
-
客户端生成一个
,服务端生成一个
。
-
客户端计算
发送给服务端,服务端计算
发送给客户端。
-
客户端通过收到的
6计算,服务端通过收到的
12计算。
两端就可以实现秘钥交换,而第三方很难破解。
2.1 原理
那么发送端 接收端。
2.2 RSA的诞生
刚刚的秘钥交换可以看成,两端可以得到相同的值。
那如果满足我们第一节的推导
,即满足d是e的模反元素时,又会发生什么呢?
也就是说:
e和n组成公钥,d和n组成私钥。
2.3 RSA算法
-
n会非常大,长度一般为1024个二进制位。(目前人类已经分解的最大整数,232个十进制位,768个二进制位)
-
由于需要求出φ(n),所以根据欧函数特点,最简单的方式n由两个质数相乘得到:质数p1、p2
-
最终由φ(n)得到e和d。
总共生成6个数字:p1、p2、n、φ(n)、e、d。
加密解密的时候,明文m、密文c,公钥(n, e),私钥(n, d),明文m长度小于n。
关于RSA的安全:
除了公钥用到了n和e其余的4个数字是不公开的。
目前破解RSA得到d的方式如下:
- 要想求出私钥
d。由于,就要知道
e和φ(n); -
e是知道的,但是要得到φ(n),必须知道p1和p2。 - 由于
n=p1*p2。只有将n因数分解才能算出。
3. 终端演示
3.1 生成公钥、私钥
由于Mac系统内置OpenSSL(开源加密库),所以我们可以直接在终端上使用命令来玩RSA。OpenSSL中RSA算法常用指令主要有三个:
- genrsa:生成并输入一个RSA私钥。
- rsautl:使用RSA密钥进行加密、解密、签名和验证等运算。
- rsa:处理RSA密钥的格式转换等问题。
~> openssl genrsa -out private.pem 1024
Generating RSA private key, 1024 bit long modulus
.........++++++
..++++++
e is 65537 (0x10001)
~> openssl rsa -in private.pem -pubout -out public.pem
writing RSA key
~> cat private.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDPk+fVkhFq1gtl67yw/RseHvec/h2xV2XvZa7xQr8c5bHCSSjl
iWUEwZSBRYy6QZrfbcwuZgaIl7wTfYHFsagRDyC6r7rwYz2Ab8i2GPwFslCcugMz
uphvMJ8KsE16rbitzfS1N45yqwhHukOOg/NGRQulmCsTlBWdpfI0dIPooQIDAQAB
AoGAeDddhcfRhIEwGrfbENmVEe23U9mr0qAeLfZCygDw88hnGXELWVwoAAgofHGO
HfSOwCUzog9+ay8NQnBmbtsDzMpi3XGqJqkyUrSgS80QpkAJ/hM3TQJ7dtppZoYz
SKQBYGWCLIV8Ab3PSI2KLl0YFYNdUc3bgPEtfgeCt9OtEpECQQDo0Z6SPzEDl7B4
8gW7G3zPPm4pxWHNL83lxfPdty9ghZg1p5H+qJshQWI27TGEDOjhSwl6HenisXhp
BOorwEH1AkEA5D7o7oyBmiVNxOSl2V15S4iGoRgimNUEZtgVqI+0nQZE3QwqGPiS
IN4hSXLCeUUh3skznJ9wd/S/GCK0+mBkfQJAfPKiy5ImV+s8xmv9L2GdJgw3Syun
RVt2gO4v5rm9L2wDOChqbeVG/B3++8NoY5oaEW8X8vXC4+qi2JnOoxRXUQJAeB8v
wdQKpVB6pGPdcQ9Dtd/tUrz8AEkjnuicRXEUEgvplBhB05CGf2vIQvp1pRMgJzrm
wcgbjdYt+ArUCm1OlQJBAIRz+QSYWTjwebwhSQWwYPua1Kcohh2TG6LHLoGVWuIP
zfF4RZ6iAR5+fNTj9ppr/iaN6MOp5rnc1APz+6YFTz4=
-----END RSA PRIVATE KEY-----
~> cat public.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPk+fVkhFq1gtl67yw/RseHvec
/h2xV2XvZa7xQr8c5bHCSSjliWUEwZSBRYy6QZrfbcwuZgaIl7wTfYHFsagRDyC6
r7rwYz2Ab8i2GPwFslCcugMzuphvMJ8KsE16rbitzfS1N45yqwhHukOOg/NGRQul
mCsTlBWdpfI0dIPooQIDAQAB
-----END PUBLIC KEY-----
公钥和私钥本身是二进制,这里进行了base64编码方便我们查看而已。如果想查看原始信息可以输入:
~> openssl rsa -in private.pem -text -out private.txt
3.2 加密解密
- 加密
创建一个txt文档,比如msg.txt,数据为密码:123456。
~> openssl rsautl -encrypt -in msg.txt -inkey public.pem -pubin -out enc.txt
~> cat enc.txt
���MRnX
�9��=�P��[�>�T�����b�2j oDڛ�6���u®�"*n3�K�
���[I��
Y����w��c�@Ǔ�cb��.-�� ��x�Aa�C9;۩ ��ECd.!7%
- 解密
~> openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
~> cat dec.txt
密码:123456%
3.3 证书
- csr证书
~> openssl req -new -key private.pem -out rsacert.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:CN
State or Province Name (full name) []:SICHUAN
Locality Name (eg, city) []:CHENGDU
Organization Name (eg, company) []:xxx
Organizational Unit Name (eg, section) []:xxx
Common Name (eg, fully qualified host name) []:xxx.com
Email Address []:xxx@email.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
这里无所谓,我们不拿去申请证书的话随便填。
- 签名
~> openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
Signature ok
subject=/C=CN/ST=SICHUAN/L=CHENGDU/O=xxx/OU=xxx/CN=xxx.com/emailAddress=xxx@email.com
Getting Private key
比如HTTPS的证书就可以用这个crt证书。
-
crt导出p12证书
这里密码输入的1234,后面代码演示会用到。
~> openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt
Enter Export Password:
Verifying - Enter Export Password:
-
crt导出drt证书
iOS不能使用crt证书,所以要进行转换。
~> openssl x509 -outform der -in rsacert.crt -out rsacert.der
4. 代码演示
- (void)viewDidLoad {
[super viewDidLoad];
//1.加载公钥
[[RSACryptor sharedRSACryptor] loadPublicKey: [[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]];
//2.加载私钥
[[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"];
}
// 点击屏幕的时候进行加密解密
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//1.加密
NSData * encryptData = [[RSACryptor sharedRSACryptor] encryptData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"加密的结果:\n%@", [encryptData base64EncodedStringWithOptions:0]);
//2.解密
NSData * decryptData = [[RSACryptor sharedRSACryptor] decryptData:encryptData];
NSLog(@"解密的结果:%@", [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding]);
}
//输出
2020-03-22 23:12:51.984584+0800 RSADemo[8902:255062] 加密的结果:
Wy0tkR0b/eA3ZT7IE0Y2x/+h2ugjYSN6ER1pPLj5hTbDF5jS1Vw4hqW0RENOeJyTPcRPcCIyV3ggvpmGFtAFTREbO5bOYtmNi7mK4v2Izber1kO9oxIQ4LSPVWS+I/QYB4Bi83hDHp/uQx6llcVsXNKN/fynYIxZAwcKApt7HBQ=
2020-03-22 23:12:51.986617+0800 RSADemo[8902:255062] 解密的结果:hello
2020-03-22 23:15:56.910986+0800 RSADemo[9007:259734] 加密的结果:
evJDs22zCqx5dq+0BfJ70Oevcw2UVSCzj/lJ5V8Rest5lvk6L55L/2Xo/hZBVONtZBKVIFW4oY8ezl1vPf0YJnjFYv/Tcyk1GNO/zWNz4HQP+NqcS/l6D+Ef+oc1k10vjQKKMSORrsO0/5j9/dMgQHa6PzzEKOGXgQLVg5j/YDY=
2020-03-22 23:15:56.913286+0800 RSADemo[9007:259734] 解密的结果:hello
两次加密结果不一样,这里特别说明一下。加密的时候有一个参数,这里使用了宏定义:
// 填充模式 kSecPaddingPKCS1 每次加密结果是随机变化的
// kSecPaddingNone 每次加密结果是固定的
#define kTypeOfWrapPadding kSecPaddingPKCS1
5. 总结
- RSA数学原理
- 欧拉
- 欧拉函数、欧拉定理、模反元素
- 迪菲赫尔曼秘钥交换:用户交换秘钥。拆分了数学公式。
- RSA公式:加密
和解密
。
-
小于
,
是
相对于
的模反元素。
-
和
是公钥、
和
是私钥、
明文、
密文。
-
长度1024以上(才够安全)。
由
和
两个质数相乘得到。
-
- RSA特点
- 相对来说比较安全(非对称机密的,私钥不用传递)。
- 效率不高。
- 加密数据小。
- 欧拉











网友评论