聊聊公钥私钥的那点事儿

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xufive/article/details/80564763

聊聊公钥私钥的那点事儿

前言

加密技术是个好东西,可以有效地保证我们在沟通和存储过程中的信息安全。但我敢打赌,没有程序员喜欢加密。一想到公钥私钥、数字证书就开始头晕,一见到https开头的url就额头冒汗,这是大多数程序员的常见病症。如果看官不幸染有此疾,请先调息凝神,心中默念三声阿弥陀佛,然后一口气读完本文,保你沉疴尽除、遍体通泰。什么?疗效不明显?请执行以下代码:

while 症状存在:
    调息凝神
    心中默念三声阿弥陀佛
    一口气读完本文

对称加密和非对称加密

通常,对信息加密时需要遵循某种规则,而解密也需要这个规则,所以,这个规则——我们称之为密钥,就需要妥善保管,不能让除参与方之外的其他人知道。加密和解密使用同一个密钥,这就是对称加密。对称加密的最大弊端就是密钥的分发比较困难,因为在对称加密算法中,加密方和解密方都需要知道这个密钥,如果把密钥一起发送,则就存在泄露的风险。对称加密算法的优势是加密速度非常快。常见的对称加密算法有DES, AES等。

在非对称加密算法中,加密和解密分别使用不同的两个密钥。这两个密钥,我们称之为公钥和私钥,其使用规则如下:

  • 公钥和私钥总是成对使用的
  • 用公钥加密的数据只有对应的私钥可以解密
  • 用私钥加密的数据只有对应的公钥可以解密

据此,我们可以得到另外两条规则:

  • 如果可以用公钥解密,则必然是对应的私钥加密的(逆反命题)
  • 如果可以用私钥解密,则必然是对应的公钥加密的(逆反命题)

RSA算法

RSA算法是使用最广泛的非对称加密算法,Elgamal是另一种常用的非对称加密算法。RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

以下关于算法的描述,程序员可以直接跳过。

  1. 随机选取两个大素数p和q,使得p != q
  2. 计算 n = p*q
  3. 选取一个与Θ互质的小奇数e,其中Θ(n)=(p-1)*(q-1)
  4. 对模Θ(n),计算出e的乘法逆元d的值(e 关于模 r 的模反元素)
  5. 将P = (e,n)公开,作为参与者的RSA公钥
  6. 使对S = (d, n)保密,并作为参与者的RSA密钥

这才是程序员喜欢的方式。什么?没有rsa模块?你要是不熟悉pip,那我就再重复一遍:pip install rsa

import rsa
public_key, private_key = rsa.newkeys(1024)

只用一行代码,我们就得到了一对相互关联的公钥和私钥。先让我们看看它们长什么样。

>>> public_key
PublicKey(125968803660251260195528775390603096934906910755340024716838945293498197087123543996690495899984002021535588663718986183052477185264509927082435284758064639584219248273108674870162260560435719668689505872005586121682696277467991602764991911763147507514947276291101276753421029488214739040404319301529357871213, 65537)
>>> public_key.save_pkcs1()
u'-----BEGIN RSA PUBLIC KEY-----\nMIGJAoGBALNisib5xlsWt3ef9dBAd9Qlz1zT1sQKtbCYKVGthBYb2BiQKbtTNNtI\nz2FS0IE+97sFpOsToQsruY1YIZij8SYGgDmhqCJllBNNqPsK9WKfT1uFQSgvDYD5\nPDuRk7ATKDIE0Vizx7jCXuQA7OiTNwVXFxiyNWk+fXlpbNk/bWhtAgMBAAE=\n-----END RSA PUBLIC KEY-----\n'

加密通讯

程序员小林受命参与一项商业谈判,临行前,业务经理浩克交给他一个U盘,里面保存了一个公钥,对应的私钥则保存在浩克的电脑里。

import rsa

# 生成公钥、私钥
public_key, private_key = rsa.newkeys(1024)

# 保存公钥到U盘
with open('public_hulk.pem', 'w') as fp:
    fp.write(public_key.save_pkcs1().decode())

# 保存私钥到浩克的电脑上
with open('private_hulk.pem', 'w') as fp:
    fp.write(private_key .save_pkcs1().decode())

谈判过程中,小林获得一条绝密信息,需要安全发给浩克。信息内容是:绝不能让第三者知道!小林使用存储在U盘上的浩克的公钥加密该信息,然后通过电子邮件发送给了浩克。

message = u'绝不能让第三者知道!'

# 导入公钥
with open('public_hulk.pem', 'r') as f:
    pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())

# 使用公钥加密信息
crypto = rsa.encrypt(message.encode('utf-8'), pubkey)

浩克收到邮件后,邮件内容显示为:

{P`ᄋxモᄌýôᄍ}VEᄋヘgÛDkᄁjᄎüWÉd.W$ヌᄇN\kÙʞÑwフpi_ユᄌèqヨõG

没关系,浩克只需要用自己的私钥解密就可以正确显示信息了。

# 导入私钥
with open('private_hulk.pem', 'r') as f:
    privkey= rsa.PrivateKey.load_pkcs1(f.read().encode())

message = rsa.decrypt(crypto, privkey).decode('utf-8')

解密后,邮件内容显示为:

绝不能让第三者知道!

数字签名

商务谈判进行到第二天,浩克决定先不着急答应对方提出的条件。他需要发邮件通知小林,邮件内容为:按兵不动,不露声色。浩克写完信息后,先用Hash函数,生成信件的摘要(digest),然后,使用私钥对这个摘要加密,生成”数字签名”(signature),最终把加密的信息和数字签名一同发给了小林。

这里写图片描述

message = u'按兵不动,不露声色。'

# 导入私钥
with open('private_hulk.pem', 'r') as f:
    privkey= rsa.PrivateKey.load_pkcs1(f.read().encode())

# 生成摘要
digest = str(hash(message.encode('utf-8')))

# 生成签名
signature = rsa.encrypt(digest, privkey)

# 加密邮件内容
crypto = rsa.encrypt(message.encode('utf-8'), privkey)

正在会议室谈判的小林收到了一封“浩克”的邮件,除了内容,还附有“浩克”的数字签名。他先解密邮件内容,得到“接受条件,立即签约”的指示,然后使用hash函数,生成信件的摘要(digest1),再使用浩克的公钥解密数字签名,得到原始的信件摘要(digest0)。比较两个摘要,完全一致,很显然,这封邮件的确是“浩克”本人发出的。但是,敏感的小林总觉得有些奇怪,因为现在签约,明显有损于公司的利益。他冷静地思考了一分钟,终于发现了问题:有人冒充浩克给他发了这封邮件,并且他U盘里的公钥被人掉包了!

果然,几分钟之后,小林又收到了浩克的邮件。这次,他使用自己备份的公钥解密,并验证了浩克的数字签名,正确解读了浩克发出的指令:按兵不动,不露声色。

这里写图片描述

# 导入公钥
with open('public_hulk.pem', 'r') as f:
    pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())

# 解密邮件内容:按兵不动,不露声色。
message = rsa.decrypt(crypto, pubkey ).decode('utf-8')

# 生成摘要1
digest1 = str(hash(message.encode('utf-8')))

# 解密数字签名,得到生成摘要0
digest0 = rsa.decrypt(signature , pubkey)

if digest0 == digest1:
    print message 

数字证书

事实上,我们有比U盘更好的方法保存公钥,这就是certificate authority,简称CA。浩克可以去CA证书中心为自己的公钥做认证。CA证书中心用自己的私钥,对浩克的公钥和一些相关信息一起加密,生成”数字证书”(Digital Certificate)。

这里写图片描述

有了数字证书,在需要数字签名的场合,浩克只要在签名的同时,再附上数字证书就行了。

收件人收到浩克签名的邮件后,用CA的公钥解开数字证书,就可以拿到浩克真实的公钥了,然后就能证明”数字签名”是否真的是浩克签署的。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/xufive/article/details/80564763