RSA及Openssl

300 阅读5分钟

一、密码学概述

密码学的历史大致可以追溯到两千年前,相传古罗马名将凯撒大帝为了防止敌方截获情报,用密码传送情报。凯撒的做法很简单,就是对二十几个罗马字母建立一张对应表。这样,如果不知道密码本,即使截获一段信息也看不懂。 从凯撒大帝时代到上世纪70年代这段很长的时间里,密码学的发展非常的缓慢,因为设计者基本上靠经验。没有运用数学原理。

1977年三位麻省理工学院的数学家 罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起设计了一种算法,可以实现非对称加密。这个算法用他们三个人的名字命名,叫做RSA算法。

上世纪70年代产生的一种加密算法。其加密方式比较特殊,需要两个密钥:公开密钥简称公钥(publickey)和私有密钥简称私钥(privatekey)。公钥加密,私钥解密;私钥加密,公钥解密。这个加密算法就是伟大的RSA

二、离散对数

那么问题来了,如何设计一个加密算法。让加密容易,解密复杂呢?

image.png 看图发现 3为17的原根。

一、欧拉函数

什么是欧拉函数

欧拉函数是小于x的整数中与x互质的数的个数,一般用φ(x)表示。特殊的,φ(1)=1。

image.png

互质关系

如果两个正整数,除了1以外,没有其他公因数, 我们就称这两个数是互质关系(coprime)。

二、欧拉定理

image.png

公式转换

由于 1 ≡ 1 (≡ 恒等于)

由于 1*m ≡ m

如果两个正整数e和x互质,那么一定可以找到整数d,使得 ed-1 被x整除。
那么d就是e对于x的“模反元素”

最后: image.png

三、迪菲赫尔曼密钥交换&最终的RSA

image.png 服务器:生成一个随机数 15,只有服务器知道,使用 3∧15 mod 17 = 6 把6发送给客户端

客户端:也生成一个随机数 13,只有服务器知道,使用 3∧13 mod 17 = 12 把12发送给服务端

第三方窃取:只能拿到 6和12 拿不到最终的密钥 15和13.

image.png 原理:

服务器: 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

image.png 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=p1
p2。只有将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.生成的文件如下: image.png 通过cat 命令查看 pem

image.png

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

打印结果: image.png