實驗四 RSA加密算法、應用及源碼下載

一、實驗目的:

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:

  • nbits – the number of bits required to store n = p*q.
  • accurate – when True, n will have exactly the number of bits you asked for. However, this makes key generation much slower. When False, n` may have slightly less bits.
  • poolsize – the number of processes to use to generate the prime numbers. If set to a number > 1, a parallel algorithm will be used. This requires Python 2.6 or newer.
  • exponent (int) – the exponent for the key; only change this if you know what you’re doing, as the exponent influences how difficult your private key can be cracked. A very common choice for e is 65537.

Returns:

a tuple (rsa.PublicKey, rsa.PrivateKey)

The poolsize parameter was added in Python-RSA 3.1 and requires Python 2.6 or newer.

  1. Time to generate a key

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.

  1. Key size requirements

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:

  • message – the message to encrypt. Must be a byte string no longer than k-11 bytes, where k is the number of bytes needed to encode the n component of the public key.
  • pub_key – the rsa.PublicKey to encrypt with.

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:

  • message – the message to sign. Can be an 8-bit string or a file-like object. If message has a read() method, it is assumed to be a file-like object.
  • priv_key – the rsa.PrivateKey to sign with
  • hash – the hash method used on the message. Use ‘MD5’, ‘SHA-1’, ‘SHA-256’, ‘SHA-384’ or ‘SHA-512’.

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:

  • message – the signed message. Can be an 8-bit string or a file-like object. If message has a read() method, it is assumed to be a file-like object.
  • signature – the signature block, as created with rsa.sign().
  • pub_key – the rsa.PublicKey of the person signing the message.

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,公衆號名稱爲“豆豆諮詢”。掃描以下二維碼,關注“豆豆諮詢”。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章