常见的加密算法原理与实现:RSA加密

一、基本背景

RSA算法是是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的,算法的名字就是三人名字首字母拼凑而成的。

RSA是目前应用最为广泛的非对称加密算法之一,这里延伸一下,所谓的非对称加密,通俗来讲就是数据加密和解密用的不是同一个秘钥。维基百科官方解释如下:

公开密钥密码学(英语:Public-key cryptography)也称非对称式密码学(英语:Asymmetric cryptography)是密码学的一种算法,它需要两个密钥,一个是公开密钥,另一个是私有密钥;公钥用作加密,私钥则用作解密。使用公钥把明文加密后所得的密文,只能用相对应的私钥才能解密并得到原本的明文,最初用来加密的公钥不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密;不同于加密和解密都使用同一个密钥的对称加密。公钥可以公开,可任意向外发布;私钥不可以公开,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方。

下图很生动的说明了非对称加密的过程,原文经过公钥加密后,生成密文,而密文的解密只能用私钥完成。而正是因为加密和解密的规则不同,这样就避免了传统加密算法需要传递秘钥可能带来的因秘钥泄露导致不安全问题。
在这里插入图片描述

二、算法原理

RSA算法的加密涉及到几个重要的数学概念,包括我们小学学过的质数(又叫素数)、欧拉定理、欧拉函数、模反元素,当然最核心的还是互质关系,在加密过程中会多次用到。

看很多教程里都已Alice和Bob来作为故事的主人公,外国人名字太拗口了,为了方便自己理解记忆,我这里就用小王和小张了。

2.1、生成公钥和私钥

假设小王要给小张用rsa算法发送一条加密信息,他首先生成公钥和私钥,具体包含以下这么几个步骤:

  1. 随意选择两个不相等的质数 pq,小王选的是3和11(实际应用中,两个数越大越安全);
  2. 计算 pq的乘积 ,n= p* q,n为33,这里的n就是秘钥的长度,33转换成二进制是100001,长度是6位,所以秘钥长度是6位;(注:实际应用中,RSA密钥一般是1024位,重要场合则为2048位。)
  3. 计算n的欧拉函数φ(n),把33带入欧拉函数计算结果为20:
    φ(n) = φ(p * q) = φ( p)* φ(q) =(p-1) * (q-1)
    φ(33) = φ(3 * 11) = φ(3) * φ(11) =(3-1) * (11-1)=20
  4. 随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质,小王在1到20之间选了7;
  5. 计算e对于φ(n)的模反元素d,ed ≡ 1 (mod φ(n)),这个公式的意思就是找到整数d,使得ed被φ(n)除的余数为1。设ed是φ(n)的k的整数倍,余数为1,上式等价于:
    7 * d = 20k + 1,即7d -20k = 1,也就是一个二元一次方程,该公式可以用扩展欧几里得方法进行求解,这里因为数字比较小,所一眼就能看出来d=3,k=1;
  6. 至此,所有计算就完成,将n和e封装成公钥,n和d封装成私钥,即加密公钥为(33,7),私钥为(33,3)。

2.2、加密消息

生成公钥和秘钥以后,小王就要开始用公钥对信息进行加密了。假设他要发送的信息是m,注意m必须是一个整数,且小于n。如果m是字符串的话,就需要使用事先与小张约好的格式将m转换为一个小于n的非负整数 ,通常取字符串的ascii值或unicode值。

加密的过程其实就是算出下式中的c:

小王设定的m是数字2,那加密结果就是2的7次方除以33的余数,也就是29,然后小王把29发送给了小张。

2.3、解密消息

小张收到小王的加密信息后,就用自己的私钥(33,3)进行解密,解密公式如下:

可以得出,29的3次方除以33的余数一定为2,因此小张就得出了加密前的原文是数字2。

三、Python实现RSA算法

目前有很多库支持实现RSA加密,这里介绍两个比较常见的库:pycryptodomersa

3.1、基于pycryptodome库实现RSA加解密

安装对应的库:

pip install pycryptodome

加解密实现过程:


from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii

# 生成公钥和私钥,秘钥长度长度设为512位
keyPair = RSA.generate(1024)

pubKey = keyPair.publickey()
print(f"Public key:  (n={hex(pubKey.n)}, e={hex(pubKey.e)})")
pubKeyPEM = pubKey.exportKey()
print(pubKeyPEM.decode('ascii'))

print(f"Private key: (n={hex(pubKey.n)}, d={hex(keyPair.d)})")
privKeyPEM = keyPair.exportKey()
print(privKeyPEM.decode('ascii'))

# 使用公钥进行加密
msg = b'hello kitty!'
encryptor = PKCS1_OAEP.new(pubKey)
encrypted = encryptor.encrypt(msg)
print("Encrypted:", binascii.hexlify(encrypted))

# 使用私钥进行解密
decryptor = PKCS1_OAEP.new(keyPair)
decrypted = decryptor.decrypt(encrypted)
print('Decrypted:', decrypted)

输出结果:

Public key:  (n=0xd3357728da47ae241c59bf1956d0f47f291e236c32c134a04cf2e86c75200a57ffbf99bdf9e3633595b8e188ed5463ca6e274a6a9a9d7bcf6714180c9edfdc86f59db3bcd226f10b58b383d1429466e5ddae92c891ce122d52443ca7ec1b845c1e09784d0b26b0482fcb9a605fdc073ae6f6d773d114524768b2cf7733ea7b19, e=0x10001)
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTNXco2keuJBxZvxlW0PR/KR4j
bDLBNKBM8uhsdSAKV/+/mb3542M1lbjhiO1UY8puJ0pqmp17z2cUGAye39yG9Z2z
vNIm8QtYs4PRQpRm5d2uksiRzhItUkQ8p+wbhFweCXhNCyawSC/LmmBf3Ac65vbX
c9EUUkdoss93M+p7GQIDAQAB
-----END PUBLIC KEY-----
Private key: (n=0xd3357728da47ae241c59bf1956d0f47f291e236c32c134a04cf2e86c75200a57ffbf99bdf9e3633595b8e188ed5463ca6e274a6a9a9d7bcf6714180c9edfdc86f59db3bcd226f10b58b383d1429466e5ddae92c891ce122d52443ca7ec1b845c1e09784d0b26b0482fcb9a605fdc073ae6f6d773d114524768b2cf7733ea7b19, d=0x2e7efa23bbf055e60cabfa87b583af6d5abbedea874fbc6e66356e16f0262f6d8f6ccbbae468ee892b7ea24c2aced281a5a64e0022fa16c62ef1b53ab64ce385b13e7aa44c246a046c69d7c9c58ae8d9cee1f1256170d55df3de3657f14606763e04ed9a1ac652ccc234df80ede1f420cf54d551d0dd0aaea25e85d430278a5)
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDTNXco2keuJBxZvxlW0PR/KR4jbDLBNKBM8uhsdSAKV/+/mb35
42M1lbjhiO1UY8puJ0pqmp17z2cUGAye39yG9Z2zvNIm8QtYs4PRQpRm5d2uksiR
zhItUkQ8p+wbhFweCXhNCyawSC/LmmBf3Ac65vbXc9EUUkdoss93M+p7GQIDAQAB
AoGAAufvoju/BV5gyr+oe1g69tWrvt6odPvG5mNW4W8CYvbY9sy7rkaO6JK36iTC
rO0oGlpk4AIvoWxi7xtTq2TOOFsT56pEwkagRsadfJxYro2c7h8SVhcNVd8942V/
FGBnY+BO2aGsZSzMI034Dt4fQgz1TVUdDdCq6iXoXUMCeKUCQQDc4eX8MD3gCH0l
CVnM3oCokfrkMnKMdWbfPiAZ2d4+qYqSFxthh8pFHKag7Sroj6JB1Df/LmOIjge1
DA14Tii1AkEA9MnYQUMWoeVHdgHRyJfnt5nhBVELkihrkandiGoHoPZ++oCRd+lC
AhPUeMbi48nXWsfB9aeBCyfCtrowq8h7VQJATbMxggs+WObjjvnBGy5SN/pSNaAB
Z6OM8o8aH73iTky5sDZsrVxlLPatLwL/CxwrydhrclrRLKI519hLjLyB2QJAZFcY
viex70r8r/Ku+3rJEQmSo4tFIvROo7btiC1uUxy3kBeDiZOj6xYV0iw0dQsXq66W
Ywv2aYwy1JQdv0y+wQJBAIdKhGaw+1FPXsYkxE8FTFZKYyPPPm1WeHml4Sxnoefq
HLuIv5/J1ZmThRtFrtMrUi4CLIN+T/P8QyW0CRbMyeE=
-----END RSA PRIVATE KEY-----
Encrypted: b'328ad919abfaddb41ef23a1edcdfa082e5d06a3c6f069711ea2f9acb065e010d336ac05f6e3d8a8b654c313cf8c45fed6cab63f072f088b58f5e60a63238987a8538ee9febcb475687bd052d8e0b0c73f485e4de2cc6fe01507a3a7c202b1e8cca54e3e1cd86ee7a3cbac9037e287b2b0bd30236fec6ff5d51c609f9ac07ddb5'
Decrypted: b'hello kitty!'

3.2、基于rsa库实现RSA加解密

安装对应的库:

pip install rsa

加解密实现过程:

import rsa

#生成公钥和私钥,秘钥长度长度设为512位
(pub_key, priv_key) = rsa.newkeys(512)

#对要加密的信息先做编码预处理
message = 'hello kitty!'.encode('utf8')

#使用公钥进行加密
crypto = rsa.encrypt(message, pub_key)

#使用私钥进行解密
message = rsa.decrypt(crypto, priv_key)

print('公钥:',pub_key)
print('公钥:',priv_key)
print('加密结果:',crypto)
print('解密结果:',message.decode('utf8'))

输出结果:

公钥: PublicKey(7314317358276496179673675826113974816867276788014695748377826142338549872987934756025496125702108198463672589083200012256019911170396983233914797109169127, 65537)
公钥: PrivateKey(7314317358276496179673675826113974816867276788014695748377826142338549872987934756025496125702108198463672589083200012256019911170396983233914797109169127, 65537, 943181653032556711696022619382779211397307721371319922632116342354747469961338103051165777010084765246227308796305985673201500446076915010752259511551713, 4468680789217211695491298837720072527208283405518529890430453910323843023628553431, 1636795668181472565104977515834979867527383910843535218329587708682536817)
加密结果: b'\x0e\xd7\x02|\x17>\xb1\xd0\xebyD\x18\x9f\xdf\xa8\xe7n\xe0\xd3\xe3~#\xa8\xbe\xcdA\xa8k\xef\xc3T\xb70\xdd\x85\xcc\x9e\xf518\x83\xf2\n\x1c\xf5\xf2\x89\xaaDp\x1d\xb5\x90\xe8\x1c\x96\xfc\xd2\xb0\xf7H*\xcc;'
解密结果: hello kitty!

四、参考文献

1、维基百科,RSA加密算法
2、RSA Encrypt / Decrypt - Examples
3、Python-RSA 4.7 documentation
4、阮一峰,RSA算法原理(一)
5、阮一峰,RSA算法原理(二)
6、五分钟知识科普:什么是 RSA 算法

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值