用Python进行RSA加解密


=Start=

缘由:

简单整理一下 RSA 算法的相关知识,方便后面需要的时候参考。

正文:

参考解答:

一点历史

对称加密算法

1976年以前,所有的加密方法都是同一种模式:

  (1)甲方选择某一种加密规则,对信息进行加密;
  (2)乙方使用同一种规则,对信息进行解密。

由于加密和解密使用同样规则(简称”密钥”),这被称为”对称加密算法”(Symmetric-key algorithm)。

这种加密模式有一个最大弱点:甲方必须把加密规则告诉乙方,否则无法解密。保存和传递密钥,就成了最头疼的问题。

非对称加密算法

1976年,两位美国计算机学家Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完成解密。这被称为”Diffie-Hellman密钥交换算法”。这个算法启发了其他科学家。人们认识到,加密和解密可以使用不同的规则,只要这两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。

这种新的加密模式被称为”非对称加密算法”。

  (1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
  (2)甲方获取乙方的公钥,然后用它对信息加密。
  (3)乙方得到加密后的信息,用私钥解密。

如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。

RSA算法

1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的”非对称加密算法”。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。

这种算法非常可靠,密钥越长,它就越难破解。

RSA算法介绍

RSA 加密算法是一种非对称加密算法。在公开密钥加密和电子商业中 RSA 被广泛使用。RSA 是 1977 年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。RSA 就是他们三人姓氏开头字母拼在一起组成的。

对极大整数做因数分解的难度决定了 RSA 算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA 算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用 RSA 加密的信息的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的 RSA 钥匙才可能被强力方式破解。到2020年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被破解的。

基本原理是将两个很大的质数相乘很容易得到乘积,但是该乘积分解质因数却很困难。

RSA算法的速度与安全性

比起AES等其它对称算法来说,RSA运算更为复杂,所以要慢得多。速度一直是RSA的缺陷。通常只用于少量数据加密。

从安全角度来讲,一般建议RSA密钥长度至少为2048位。世界上还没有任何可靠的攻击RSA算法的方式,如果密钥足够长或者没有密钥,想要RSA解密或者破解RSA解密基本是不可能的。RSA从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

RSA存储格式

DER是RSA密钥的二进制格式,PEM是DER转码为Base64的字符格式,由于DER是二进制格式,不便于阅读和理解。一般而言,密钥都是通过PEM的格式进行存储的。

PKCS #1 标准主要用于 RSA密钥,其RSA公钥和RSA私钥PEM格式:

// PKCS#1公钥格式
-----BEGIN RSA PUBLIC KEY-----
BASE64 DATA...
-----END RSA PUBLIC KEY-----

// PKCS#1私钥格式
-----BEGIN RSA PRIVATE KEY-----
BASE64 DATA...
-----END RSA PRIVATE KEY-----

PKCS#8 标准定义了一个密钥格式的通用方案,其公钥和私钥PEM格式:

// PKCS#8公钥格式
-----BEGIN PUBLIC KEY-----
BASE64 DATA...
-----END PUBLIC KEY-----

// PKCS#8私钥格式
-----BEGIN PRIVATE KEY-----
BASE64 DATA...
-----END PRIVATE KEY-----

经过对比,我们可以明显看到,PKCS #8 格式是没有 RSA 字样的,因为PKCS#8是一个通用型的密钥格式方案,它不仅为RSA算法所使用,同样也可以被其它加密解密算法所使用。

用Python进行RSA加解密

  1. 生成密钥
  2. 公钥加密
  3. 私钥解密
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64

def gen_rsa_key():
    key = RSA.generate(2048)
    private_key = key.exportKey('PEM') #bytes 直接 exportKey 返回的是私钥
    public_key = key.publickey().exportKey('PEM') #bytes
    #将公私钥信息以文件形式进行保存
    with open('rsa-private.pem','wb') as f1, open('rsa-public.pem','wb') as f2:
        f1.write(private_key)
        f2.write(public_key)

def rsa_str(encrypt_or_decrypt, msg, key):
    if encrypt_or_decrypt == "encrypt":
        #用公钥加密
        with open('rsa-public.pem','rb') as fp:
            public_key = fp.read()
        rsa_public_key = RSA.importKey(public_key)
        rsa_public_key = PKCS1_OAEP.new(rsa_public_key)
        encrypted_text = rsa_public_key.encrypt(msg.encode('utf-8'))
        encrypted_text = base64.b64encode(encrypted_text)
        print('your encrypted_text is : {}'.format(encrypted_text))
        return encrypted_text

    elif encrypt_or_decrypt == "decrypt":
        #用私钥解密
        with open('rsa-private.pem','rb') as fp:
            private_key = fp.read()
        rsa_private_key = RSA.importKey(private_key)
        rsa_private_key = PKCS1_OAEP.new(rsa_private_key)
        msg = base64.b64decode(msg)
        decrypted_text = rsa_private_key.decrypt(msg)
        print('your decrypted_text is : {}'.format(decrypted_text))
        return decrypted_text

def encrypt_decrypt_rsa():
    #生成key,并拿到公私钥
    gen_rsa_key()

    plaintext = input('plain text for RSA encryption and decryption:') #从命令行中读取字符串作为要进行加密的明文
    # with open('raw_data.txt') as fp: #ValueError: Plaintext is too long.
    #     plaintext = fp.read() #从文件中读取明文时会提示明文太长了,还是建议从命令行里面读取短长度的字符串作为明文

    ciphertext = rsa_str('encrypt', plaintext, 'key')
    with open('data_rsa_encrypt.txt','w') as fp:
        fp.write(ciphertext.decode())

    decrypt_data = rsa_str('decrypt', ciphertext, 'key')
    with open('data_rsa_decrypt.txt','w') as fp:
        fp.write(decrypt_data.decode())
#encrypt_decrypt_rsa
参考链接:

RSA加密算法
https://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95

RSA算法原理(一)
https://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

RSA算法原理(二)
https://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

RSA算法原理
https://zhuanlan.zhihu.com/p/48249182

RSA加密/解密
https://try8.cn/tool/cipher/rsa

RSA 介绍
https://ctf-wiki.org/crypto/asymmetric/rsa/rsa_theory/

RSA 的原理与实现
https://cjting.me/2020/03/13/rsa/

PKCS#1 OAEP is an asymmetric cipher based on RSA and the OAEP padding
https://stackoverflow.com/questions/30056762/rsa-encryption-and-decryption-in-python/55274503#55274503

这个里面的加解密操作中的 PKCS1_OAEP.new 接收的 key 都是同一个,相对来说没有上面 55274503 这个回答的步骤清晰
https://stackoverflow.com/questions/30056762/rsa-encryption-and-decryption-in-python/68187535#68187535

Encrypt data with RSA
https://pycryptodome.readthedocs.io/en/latest/src/examples.html#encrypt-data-with-rsa

RSA Encrypt / Decrypt – Examples #清晰明了,nice
https://cryptobook.nakov.com/asymmetric-key-ciphers/rsa-encrypt-decrypt-examples

基于PKCS1_OAEP的RSA加解密 #提供了一个在只提供公钥文件没有提供私钥文件的情况下,如何通过一些其它信息计算还原出私钥,然后解密密文得到结果的步骤
https://blog.csdn.net/jianpanliu/article/details/123757546

RSA算法的一些知识
https://ixyzero.com/blog/archives/761.html

=END=


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注