一、密码学概述
密码学的历史大致可以追溯到两千年前,相传古罗马名将凯撒大帝为了防止敌方截获情报,用密码传送情报。凯撒的做法很简单,就是对二十几个罗马字母建立一张对应表。这样,如果不知道密码本,即使截获一段信息也看不懂。 从凯撒大帝时代到上世纪70年代这段很长的时间里,密码学的发展非常的缓慢,因为设计者基本上靠经验。没有运用数学原理。
1977年三位麻省理工学院的数学家 罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起设计了一种算法,可以实现非对称加密。这个算法用他们三个人的名字命名,叫做RSA算法。
上世纪70年代产生的一种加密算法。其加密方式比较特殊,需要两个密钥:公开密钥简称公钥(publickey)和私有密钥简称私钥(privatekey)。公钥加密,私钥解密;私钥加密,公钥解密。这个加密算法就是伟大的RSA
二、离散对数
那么问题来了,如何设计一个加密算法。让加密容易,解密复杂呢?
看图发现 3为17的原根。
一、欧拉函数
什么是欧拉函数
欧拉函数是小于x的整数中与x互质的数的个数,一般用φ(x)表示。特殊的,φ(1)=1。
互质关系
如果两个正整数,除了1以外,没有其他公因数,
我们就称这两个数是互质关系(coprime)。
二、欧拉定理
公式转换
由于 1 ≡ 1 (≡ 恒等于)
由于 1*m ≡ m
如果两个正整数e和x互质,那么一定可以找到整数d,使得 ed-1 被x整除。
那么d就是e对于x的“模反元素”
最后:
三、迪菲赫尔曼密钥交换&最终的RSA
服务器:生成一个随机数 15,只有服务器知道,使用 3∧15 mod 17 = 6 把6发送给客户端
客户端:也生成一个随机数 13,只有服务器知道,使用 3∧13 mod 17 = 12 把12发送给服务端
第三方窃取:只能拿到 6和12 拿不到最终的密钥 15和13.
原理:
服务器: 3∧13 mod 17 = 12 => 12 ^ 15 mod 17 = 3 ^ 15^ 13 mod 17 = 10
客户端: 3∧15 mod 17 = 6 => 6 ^ 13 mod 17 = 3 ^ 13 ^ 15 mod 17 = 10
m,n,c,e,d 分别等于的数:m = 3 , n = 17 c = 10 , e = 15 , d = 13 ;
公钥:en组合成了公钥。
私钥:dn组合成了私钥。
明文: m
密文: c
说明:
1、n会非常大,长度一般为1024个二进制位。(目前人类已经分解的最大整数,232个十进制位,768个二进制位)
2、由于需要求出φ(n),所以根据欧函数特点,最简单的方式n 由两个质数相乘得到: 质数:p1、p2
Φ(n) = (p1 -1) * (p2 - 1)
3、最终由φ(n)得到e 和 d 。
总共生成6个数字:p1、p2、n、φ(n)、e、d
关于RSA的安全:
除了公钥用到了n和e 其余的4个数字是不公开的。
目前破解RSA得到d的方式如下:
1、要想求出私钥 d 。由于e*d = φ(n)k + 1。要知道e和φ(n);
2、e是知道的,但是要得到 φ(n),必须知道p1 和 p2。
3、由于 n=p1p2。只有将n因数分解才能算出。
三、终端演示RSA
由于Mac系统内置OpenSSL(开源加密库),所以我们可以直接在终端上使用命令来玩RSA. OpenSSL中RSA算法常用指令主要有三个:
- genrsa:生成并输入一个RSA私钥
- rsautl:使用RSA密钥进行加密、解密、签名和验证运算
- rsa :处理RSA密钥的格式转换等问题
例子如下:
1.生成RSA私钥,密钥长度为1024bit
openssl genrsa -out private.pem 1024
2.从私钥中提取公钥
openssl rsa -in private.pem -pubout -out public.pem
3.生成的文件如下:
通过cat 命令查看 pem
4.将私钥转换成为明文
openssl rsa -in private.pem -text -out private.txt
//查看文本信息
cat private.txt
5.通过公钥加密数据,私钥解密数据
//生成明文文件
vi message.txt
//查看文件内容
cat message.txt
密码:123456
//通过公钥进行加密
openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt
//通过私钥进行解密
openssl rsautl -decrpt -in enc.txt -inkey private.pem -out dec.txt
四、证书生成
openssl req -new -key private.pem -out rsacert.csr
输入 :
country name:xx
state or province name:
city:
company:
section:
host name:
openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
openssl pkcs12 -export -out p.12 -inkey private.pem -in rsacert.crt
// base64 可以将任意的二进制数据进行编码。 编码成为65个字符组成的文本文件。
// 0 ~ 9 a ~ z, A ~ Z + / =
// $base64 源文件 -o 目标文件 编码
// $base64 源文件 -o 目标文件 -D 解码
// 101001 010101 010100 010101
// A 字节 = =
// 010000 010000 000000 000000
RSADemo例子:
- (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 * result = [[RSACryptor sharedRSACryptor] encryptData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"加密的结果是:%@",[result base64EncodedStringWithOptions:0]);
//2.解密
NSData * jiemi = [[RSACryptor sharedRSACryptor] decryptData:result];
NSLog(@"解密的结果:%@",[[NSString alloc] initWithData:jiemi encoding:NSUTF8StringEncoding]);
}
打印结果: