복붙노트

[PYTHON] pycrypto (RSA)를 사용하여 데이터 서명 및 확인

PYTHON

pycrypto (RSA)를 사용하여 데이터 서명 및 확인

필자는 pycrypto 모듈에 익숙해 지려고 노력하고 있지만 명확한 문서가 없기 때문에 어려운 일이 발생합니다.

먼저 서명하고 데이터를 확인하는 것에 대해 알고 싶습니다. 누군가 어떻게 이것이 작성 될지에 대한 예를 제공해 줄 수 있습니까?

해결법

  1. ==============================

    1.다음은 문서의 예제를 요약 한 것입니다.

    다음은 문서의 예제를 요약 한 것입니다.

    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)
    
  2. ==============================

    2.에서 설명서에 따르면 :

    에서 설명서에 따르면 :

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

    실제 코드에서 PyCrypto의 Crypto.PublicKey.RSA.sign 함수를 사용하면 안됩니다.

    나는 PKCS1_v1_5를 구현 한 RSA 모듈을 사용하여 끝냈다. 서명을위한 문서는 매우 간단했습니다. 다른 사람들은 M2Crypto의 사용을 권장합니다.

  3. ==============================

    3.아래는 모든 필요한 RSA 기능 (암호화, 복호화, 서명, 서명 확인 및 새 키 생성)을 수행하기 위해 만든 도우미 클래스입니다.

    아래는 모든 필요한 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)
    
  4. from https://stackoverflow.com/questions/4232389/signing-and-verifying-data-using-pycrypto-rsa by cc-by-sa and MIT license