使用 pycrypto (RSA) 签名和验证数据

发布于 2024-10-03 03:33:39 字数 82 浏览 0 评论 0原文

我试图熟悉 pycrypto 模块,但缺乏清晰的文档使事情变得困难。

首先,我想了解签名和验证数据。有人可以提供一个如何编写的示例吗?

I am trying to familiarize myself with the pycrypto module, but the lack of clear documentation makes things difficult.

To start with, I would like to understand signing and verifying data. Could someone please provide an example for how this would be written?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

随风而去 2024-10-10 03:33:39

这是 示例的充实版本旧的 PyCrypto 文档:

确保您使用的是 pycryptodome 而不是 pycrypto(未维护!)

pycryptodome 可以使用 pip install pycryptodome 安装>

import Crypto.Hash.MD5 as MD5
import Crypto.PublicKey.RSA as RSA
import Crypto.PublicKey.DSA as DSA
import Crypto.PublicKey.ElGamal as ElGamal
import Crypto.Util.number as CUN
import os

plaintext = 'The rain in Spain falls mainly on the Plain'

# Here is a hash of the message
hash = MD5.new(plaintext).digest()
print(repr(hash))
# '\xb1./J\xa883\x974\xa4\xac\x1e\x1b!\xc8\x11'

for alg in (RSA, DSA, ElGamal):
    # Generates a fresh public/private key pair
    key = alg.generate(384, os.urandom)

    if alg == DSA:
        K = CUN.getRandomNumber(128, os.urandom)
    elif alg == ElGamal:
        K = CUN.getPrime(128, os.urandom)
        while CUN.GCD(K, key.p - 1) != 1:
            print('K not relatively prime with {n}'.format(n=key.p - 1))
            K = CUN.getPrime(128, os.urandom)
        # print('GCD({K},{n})=1'.format(K=K,n=key.p-1))
    else:
        K = ''

    # You sign the hash
    signature = key.sign(hash, K)
    print(len(signature), alg.__name__)
    # (1, 'Crypto.PublicKey.RSA')
    # (2, 'Crypto.PublicKey.DSA')
    # (2, 'Crypto.PublicKey.ElGamal')

    # You share pubkey with Friend
    pubkey = key.publickey()

    # You send message (plaintext) and signature to Friend.
    # Friend knows how to compute hash.
    # Friend verifies the message came from you this way:
    assert pubkey.verify(hash, signature)

    # A different hash should not pass the test.
    assert not pubkey.verify(hash[:-1], signature)

This is a fleshed-out version of the example in the old PyCrypto documentation:

Ensure you are using pycryptodome and not pycrypto (which is unmaintained!)

pycryptodome can be installed with pip install pycryptodome

import Crypto.Hash.MD5 as MD5
import Crypto.PublicKey.RSA as RSA
import Crypto.PublicKey.DSA as DSA
import Crypto.PublicKey.ElGamal as ElGamal
import Crypto.Util.number as CUN
import os

plaintext = 'The rain in Spain falls mainly on the Plain'

# Here is a hash of the message
hash = MD5.new(plaintext).digest()
print(repr(hash))
# '\xb1./J\xa883\x974\xa4\xac\x1e\x1b!\xc8\x11'

for alg in (RSA, DSA, ElGamal):
    # Generates a fresh public/private key pair
    key = alg.generate(384, os.urandom)

    if alg == DSA:
        K = CUN.getRandomNumber(128, os.urandom)
    elif alg == ElGamal:
        K = CUN.getPrime(128, os.urandom)
        while CUN.GCD(K, key.p - 1) != 1:
            print('K not relatively prime with {n}'.format(n=key.p - 1))
            K = CUN.getPrime(128, os.urandom)
        # print('GCD({K},{n})=1'.format(K=K,n=key.p-1))
    else:
        K = ''

    # You sign the hash
    signature = key.sign(hash, K)
    print(len(signature), alg.__name__)
    # (1, 'Crypto.PublicKey.RSA')
    # (2, 'Crypto.PublicKey.DSA')
    # (2, 'Crypto.PublicKey.ElGamal')

    # You share pubkey with Friend
    pubkey = key.publickey()

    # You send message (plaintext) and signature to Friend.
    # Friend knows how to compute hash.
    # Friend verifies the message came from you this way:
    assert pubkey.verify(hash, signature)

    # A different hash should not pass the test.
    assert not pubkey.verify(hash[:-1], signature)
泛泛之交 2024-10-10 03:33:39

下面是我创建的 辅助类,用于执行所有必要的 RSA 功能(加密、解密、签名、验证签名并生成新密钥)

rsa.py

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode

hash = "SHA-256"

def newkeys(keysize):
    random_generator = Random.new().read
    key = RSA.generate(keysize, random_generator)
    private, public = key, key.publickey()
    return public, private

def importKey(externKey):
    return RSA.importKey(externKey)

def getpublickey(priv_key):
    return priv_key.publickey()

def encrypt(message, pub_key):
    #RSA encryption protocol according to PKCS#1 OAEP
    cipher = PKCS1_OAEP.new(pub_key)
    return cipher.encrypt(message)

def decrypt(ciphertext, priv_key):
    #RSA encryption protocol according to PKCS#1 OAEP
    cipher = PKCS1_OAEP.new(priv_key)
    return cipher.decrypt(ciphertext)

def sign(message, priv_key, hashAlg="SHA-256"):
    global hash
    hash = hashAlg
    signer = PKCS1_v1_5.new(priv_key)
    if (hash == "SHA-512"):
        digest = SHA512.new()
    elif (hash == "SHA-384"):
        digest = SHA384.new()
    elif (hash == "SHA-256"):
        digest = SHA256.new()
    elif (hash == "SHA-1"):
        digest = SHA.new()
    else:
        digest = MD5.new()
    digest.update(message)
    return signer.sign(digest)

def verify(message, signature, pub_key):
    signer = PKCS1_v1_5.new(pub_key)
    if (hash == "SHA-512"):
        digest = SHA512.new()
    elif (hash == "SHA-384"):
        digest = SHA384.new()
    elif (hash == "SHA-256"):
        digest = SHA256.new()
    elif (hash == "SHA-1"):
        digest = SHA.new()
    else:
        digest = MD5.new()
    digest.update(message)
    return signer.verify(digest, signature)

示例用法

import rsa
from base64 import b64encode, b64decode

msg1 = "Hello Tony, I am Jarvis!"
msg2 = "Hello Toni, I am Jarvis!"
keysize = 2048
(public, private) = rsa.newkeys(keysize)
encrypted = b64encode(rsa.encrypt(msg1, public))
decrypted = rsa.decrypt(b64decode(encrypted), private)
signature = b64encode(rsa.sign(msg1, private, "SHA-512"))
verify = rsa.verify(msg1, b64decode(signature), public)

print(private.exportKey('PEM'))
print(public.exportKey('PEM'))
print("Encrypted: " + encrypted)
print("Decrypted: '%s'" % decrypted)
print("Signature: " + signature)
print("Verify: %s" % verify)
rsa.verify(msg2, b64decode(signature), public)

Below is the helper class I created to perform all necessary RSA functions (encryption, decryption, signing, verifying signature & generating new keys)

rsa.py

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode

hash = "SHA-256"

def newkeys(keysize):
    random_generator = Random.new().read
    key = RSA.generate(keysize, random_generator)
    private, public = key, key.publickey()
    return public, private

def importKey(externKey):
    return RSA.importKey(externKey)

def getpublickey(priv_key):
    return priv_key.publickey()

def encrypt(message, pub_key):
    #RSA encryption protocol according to PKCS#1 OAEP
    cipher = PKCS1_OAEP.new(pub_key)
    return cipher.encrypt(message)

def decrypt(ciphertext, priv_key):
    #RSA encryption protocol according to PKCS#1 OAEP
    cipher = PKCS1_OAEP.new(priv_key)
    return cipher.decrypt(ciphertext)

def sign(message, priv_key, hashAlg="SHA-256"):
    global hash
    hash = hashAlg
    signer = PKCS1_v1_5.new(priv_key)
    if (hash == "SHA-512"):
        digest = SHA512.new()
    elif (hash == "SHA-384"):
        digest = SHA384.new()
    elif (hash == "SHA-256"):
        digest = SHA256.new()
    elif (hash == "SHA-1"):
        digest = SHA.new()
    else:
        digest = MD5.new()
    digest.update(message)
    return signer.sign(digest)

def verify(message, signature, pub_key):
    signer = PKCS1_v1_5.new(pub_key)
    if (hash == "SHA-512"):
        digest = SHA512.new()
    elif (hash == "SHA-384"):
        digest = SHA384.new()
    elif (hash == "SHA-256"):
        digest = SHA256.new()
    elif (hash == "SHA-1"):
        digest = SHA.new()
    else:
        digest = MD5.new()
    digest.update(message)
    return signer.verify(digest, signature)

Sample Usage

import rsa
from base64 import b64encode, b64decode

msg1 = "Hello Tony, I am Jarvis!"
msg2 = "Hello Toni, I am Jarvis!"
keysize = 2048
(public, private) = rsa.newkeys(keysize)
encrypted = b64encode(rsa.encrypt(msg1, public))
decrypted = rsa.decrypt(b64decode(encrypted), private)
signature = b64encode(rsa.sign(msg1, private, "SHA-512"))
verify = rsa.verify(msg1, b64decode(signature), public)

print(private.exportKey('PEM'))
print(public.exportKey('PEM'))
print("Encrypted: " + encrypted)
print("Decrypted: '%s'" % decrypted)
print("Signature: " + signature)
print("Verify: %s" % verify)
rsa.verify(msg2, b64decode(signature), public)
辞慾 2024-10-10 03:33:39

根据文档:

https: //www.dlitz.net/software/pycrypto/api/current/Crypto.PublicKey.RSA._RSAobj-class.html

你不应该在实际代码中使用 PyCrypto 中的 Crypto.PublicKey.RSA.sign 函数:

注意:此函数执行简单、原始的 RSA 解密(教科书)。在实际应用中,您始终需要使用适当的加密填充,并且不应使用此方法直接对数据进行签名。否则可能会导致安全漏洞。建议使用模块 Crypto.Signature.PKCS1_PSS 或 Crypto.Signature.PKCS1_v1_5 代替。

我最终使用了实现 PKCS1_v1_5 的 RSA 模块签名文档非常简单。其他人建议使用 M2Crypto

According to the documentation at:

https://www.dlitz.net/software/pycrypto/api/current/Crypto.PublicKey.RSA._RSAobj-class.html

you should not use Crypto.PublicKey.RSA.sign function from PyCrypto in real code:

Attention: this function performs the plain, primitive RSA decryption (textbook). In real applications, you always need to use proper cryptographic padding, and you should not directly sign data with this method. Failure to do so may lead to security vulnerabilities. It is recommended to use modules Crypto.Signature.PKCS1_PSS or Crypto.Signature.PKCS1_v1_5 instead.

I ended up using the RSA module that implements PKCS1_v1_5. The documentation for signing was pretty straight forward. Others have recommended use M2Crypto.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文