Signing and verifying data using pycrypto (RSA)

后端 未结 3 1438
梦毁少年i
梦毁少年i 2020-12-04 12:38

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 sig

相关标签:
3条回答
  • 2020-12-04 13:28

    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.

    0 讨论(0)
  • 2020-12-04 13:32

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

    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)
    
    0 讨论(0)
  • 2020-12-04 13:32

    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)
    
    0 讨论(0)
提交回复
热议问题