一、实验目的:
RSA是经典的现代非对称加密算法,本次实验的目的是了解RSA算法原理,掌握RSA公钥与私钥加密技术,能够应用RC4进行加解密及其应用。
二、实验原理
2.1 RSA算法
RSA算法理论基础是大数分解理论,具体见RSA.docx。
2.2 rsa类及其函数
1.rsa.newkeys(keysize)
Generates public and private keys, and returns them as (pub, priv). The public key is also known as the ‘encryption key’, and is a rsa.PublicKey object. The private key is also known as the ‘decryption key’ and is a rsa.PrivateKey object.
Parameters: |
|
Returns: |
a tuple (rsa.PublicKey, rsa.PrivateKey) |
The poolsize parameter was added in Python-RSA 3.1 and requires Python 2.6 or newer.
Generating a keypair may take a long time, depending on the number of bits required. The number of bits determines the cryptographic strength of the key, as well as the size of the message you can encrypt. If you don’t mind having a slightly smaller key than you requested, you can pass accurate=False to speed up the key generation process.
Another way to speed up the key generation process is to use multiple processes in parallel to speed up the key generation. Use no more than the number of processes that your machine can run in parallel; a dual-core machine should use poolsize=2; a quad-core hyperthreading machine can run two threads on each core, and thus can use poolsize=8.
>>> (pubkey, privkey) = rsa.newkeys(512, poolsize=8)
These are some average timings from my desktop machine (Linux 2.6, 2.93 GHz quad-core Intel Core i7, 16 GB RAM) using 64-bit CPython 2.7. Since key generation is a random process, times may differ even on similar hardware. On all tests, we used the default accurate=True.
Keysize (bits) |
single process |
eight processes |
128 |
0.01 sec. |
0.01 sec. |
256 |
0.03 sec. |
0.02 sec. |
384 |
0.09 sec. |
0.04 sec. |
512 |
0.11 sec. |
0.07 sec. |
1024 |
0.79 sec. |
0.30 sec. |
2048 |
6.55 sec. |
1.60 sec. |
3072 |
23.4 sec. |
7.14 sec. |
4096 |
72.0 sec. |
24.4 sec. |
Python-RSA version 3.0 introduced PKCS#1-style random padding. This means that 11 bytes (88 bits) of your key are no longer usable for encryption, so keys smaller than this are unusable. The larger the key, the higher the security.
Creating signatures also requires a key of a certain size, depending on the used hash method:
Hash method |
Suggested minimum key size (bits) |
MD5 |
360 |
SHA-1 |
368 |
SHA-256 |
496 |
SHA-384 |
624 |
SHA-512 |
752 |
2. rsa.encrypt(message, pub_key)
Encrypts the given message using PKCS#1 v1.5
Parameters: |
|
Raises: |
OverflowError – when the message is too large to fit in the padded block. |
>>> from rsa import key, common
>>> (pub_key, priv_key) = key.newkeys(256)
>>> message = b'hello'
>>> crypto = encrypt(message, pub_key)
The crypto text should be just as long as the public key ‘n’ component:
>>> len(crypto) == common.byte_size(pub_key.n)
True
3. rsa.decrypt(crypto, priv_key)
Decrypts the given message using PKCS#1 v1.5
The decryption is considered ‘failed’ when the resulting cleartext doesn’t start with the bytes 00 02, or when the 00 byte between the padding and the message cannot be found.
Parameters: |
|
Raises: |
DecryptionError – when the decryption fails. No details are given as to why the code thinks the decryption fails, as this would leak information about the private key. |
>>> import rsa
>>> (pub_key, priv_key) = rsa.newkeys(256)
It works with strings:
>>> crypto = encrypt(b'hello', pub_key)
>>> decrypt(crypto, priv_key)
b'hello'
And with binary data:
>>> crypto = encrypt(b'\x00\x00\x00\x00\x01', pub_key)
>>> decrypt(crypto, priv_key)
b'\x00\x00\x00\x00\x01'
Altering the encrypted information will likely cause a rsa.pkcs1.DecryptionError. If you want to be sure, use rsa.sign().
Warning
Never display the stack trace of a rsa.pkcs1.DecryptionError exception. It shows where in the code the exception occurred, and thus leaks information about the key. It’s only a tiny bit of information, but every bit makes cracking the keys easier.
>>> crypto = encrypt(b'hello', pub_key)
>>> crypto = crypto[0:5] + b'X' + crypto[6:] # change a byte
>>> decrypt(crypto, priv_key)
Traceback (most recent call last):
...
rsa.pkcs1.DecryptionError: Decryption failed
4. rsa.sign(message, priv_key, hash)
Signs the message with the private key.
Hashes the message, then signs the hash with the given key. This is known as a “detached signature”, because the message itself isn’t altered.
Parameters: |
|
Returns: |
a message signature block. |
Raises: |
OverflowError – if the private key is too small to contain the requested hash. |
5. rsa.verify(message, signature, pub_key)
Verifies that the signature matches the message.
The hash method is detected automatically from the signature.
Parameters: |
|
Raises: |
VerificationError – when the signature doesn’t match the message. |
三、实验过程
3.1 RSA编程
1、生成秘钥及保存
实例1 生成秘钥并保存,包括私钥和公钥。
import rsa
# 生成密钥
(pubkey, privkey) = rsa.newkeys(1024)
# =================================
# 场景〇:密钥保存导入
# =================================
# 保存密钥
with open('public.pem','w+') as f:
f.write(pubkey.save_pkcs1().decode())
with open('private.pem','w+') as f:
f.write(privkey.save_pkcs1().decode())
# 导入密钥
with open('public.pem','r') as f:
pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())
with open('private.pem','r') as f:
privkey = rsa.PrivateKey.load_pkcs1(f.read().encode())
3.2 RSA应用场景与实例
实例2 Python下的RSA加密/解密
# =================================
# 场景一:数据泄密问题
# 为了开拓市场,公司经理分派了一群业务员到世界各地考察商机。
# 业务员们都很精明强干,很快就各自发现了很好的商机。
# 时间就是金钱!他们必须马上用email向经理汇报。
# 这就麻烦来了:网络是及其不安全的!
# 各种数据被抓包、邮箱密码泄露...太可怕了!商业竞争对手的各种手段太可怕了!
# 如何让业务员的email安全地送到公司经理的手里?(即使数据被抓包、邮箱密码泄露...)
# 太不安全了,怎么办?
#
# 没错!聪明的您一定想到了:加密。
# =================================
# 明文:业务员发现的商机
message = '这是商机:...'
# 业务员用公司经理事先给的公钥对明文加密,得到密文
crypto_email_text = rsa.encrypt(message.encode(), pubkey)
# 然后,业务员用email发送密文
# 。。。
# email在网络传输中 。。。(各种数据被抓包、邮箱密码泄露)
# 没办法,还是被有心人看到了这封email:
print(crypto_email_text) # 什么鬼?看不懂啊!
# 最后,公司经理也收到了业务员们发了的email。打开,也只看到一堆奇怪的字符!
# 没问题,公司经理用自己的私钥对收到的密文进行解密,就可得到明文
message = rsa.decrypt(crypto_email_text, privkey).decode()
# 然后,就可以看到重要的商机信息了
print(message)
实例3 Python下的RSA签名/验证
# =================================
# 场景二:身份确认问题
# 为了开拓市场,公司经理分派了一群业务员到各地考察商机。
# 在这过程中,公司经理常常通过email向业务员下达重要指令
# 然而,网络是及其不安全的!譬如:数据包被修改、邮箱密码泄露...
# 商业竞争对手可以通过各种手段伪造/修改公司经理的重要指令!
#
# 话说这天早上,业务员照常打开邮箱,发现公司经理的一封email:命令他马上回国。
# 不对啊。昨天说要在这边扩大业务,怎么今天就变了?
# 这封email是公司经理本人发的吗?
# 怎么办?
#
# 没错!聪明的您一定也想到了:签名。
# =================================
# 明文:公司经理的指令
message = '这是重要指令:...'
# 公司经理私钥签名
crypto_email_text = rsa.sign(message.encode(), privkey, 'SHA-1')
# 业务员同时收到指令明文、密文,然后用公钥验证,进行身份确认
rsa.verify(message.encode(), crypto_email_text, pubkey)
四、实验扩展
1、根据RSA的python算法,分析大数是如何存储的。
2、实现如下功能:采用文件进行加密,用email传送文件,接收方对文件进行解密。
五、实验总结
六、参考文献及程序下载
1.参考文献
[1] https://www.cnblogs.com/hhh5460/p/5243410.html
[2] https://stuvel.eu/python-rsa-doc/usage.html#generating-keys
2. 程序下载
公众号提供源码下载,包括RSA加解密算法源码以及应用案例代码(test.py),编译和调试工具:pycharm。
1)在“豆豆咨询”公众号里,输入彩蛋号即可获得下载地址:
源代码及仿真环境下载的彩蛋号:9200;
2)如果有疑问或者需要帮助,请加入QQ群(群名称:豆豆咨询,群号:625686304);或者公众号douAsk,公众号名称为“豆豆咨询”。扫描以下二维码,关注“豆豆咨询”。