def verify(message, signature, pub_key): '''Verifies that the signature matches the message. The hash method is detected automatically from the signature. @param message: the signed message @param signature: the signature block, as created with ``sign(...)``. @param pub_key: the public key of the person signing the message. @raise VerificationError: when the signature doesn't match the message. ''' blocksize = common.byte_size(pub_key['n']) encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key['e'], pub_key['n']) clearsig = transform.int2bytes(decrypted, blocksize) # If we can't find the signature marker, verification failed. if clearsig[0:2] != '\x00\x01': raise VerificationError('Verification failed') # Find the 00 separator between the padding and the payload try: sep_idx = clearsig.index('\x00', 2) except ValueError: raise VerificationError('Verification failed') # Get the hash and the hash method (method_name, signature_hash) = _find_method_hash(clearsig[sep_idx+1:]) message_hash = _hash(message, method_name) # Compare the real hash to the hash in the signature if message_hash != signature_hash: raise VerificationError('Verification failed')
def verify(message, signature, pub_key): """Verifies that the signature matches the message. The hash method is detected automatically from the signature. :param 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. :param signature: the signature block, as created with :py:func:`rsa.sign`. :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message. :raise VerificationError: when the signature doesn't match the message. """ keylength = common.byte_size(pub_key.n) encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) clearsig = transform.int2bytes(decrypted, keylength) # Get the hash method method_name = _find_method_hash(clearsig) message_hash = _hash(message, method_name) # Reconstruct the expected padded hash cleartext = HASH_ASN1[method_name] + message_hash expected = _pad_for_signing(cleartext, keylength) # Compare with the signed one if expected != clearsig: raise VerificationError('Verification failed') return True
def decrypt(crypto, priv_key): blocksize = common.byte_size(priv_key.n) encrypted = transform.bytes2int(crypto) decrypted = core.decrypt_int(encrypted, priv_key.d, priv_key.n) cleartext = transform.int2bytes(decrypted, blocksize) if cleartext[0:2] != b('\x00\x02'): raise DecryptionError('Decryption failed') try: sep_idx = cleartext.index(b('\x00'), 2) except ValueError: raise DecryptionError('Decryption failed') return cleartext[sep_idx + 1:]
def verify(message, signature, pub_key): blocksize = common.byte_size(pub_key.n) encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) clearsig = transform.int2bytes(decrypted, blocksize) if clearsig[0:2] != b('\x00\x01'): raise VerificationError('Verification failed') try: sep_idx = clearsig.index(b('\x00'), 2) except ValueError: raise VerificationError('Verification failed') method_name, signature_hash = _find_method_hash(clearsig[sep_idx + 1:]) message_hash = _hash(message, method_name) if message_hash != signature_hash: raise VerificationError('Verification failed')
def verify(message, signature, pub_key): '''Verifies that the signature matches the message. The hash method is detected automatically from the signature. :param 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. :param signature: the signature block, as created with :py:func:`rsa.sign`. :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message. :raise VerificationError: when the signature doesn't match the message. .. warning:: Never display the stack trace of a :py:class:`rsa.pkcs1.VerificationError` 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. ''' blocksize = common.byte_size(pub_key.n) encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) clearsig = transform.int2bytes(decrypted, blocksize) # If we can't find the signature marker, verification failed. if clearsig[0:2] != b('\x00\x01'): raise VerificationError('Verification failed') # Find the 00 separator between the padding and the payload try: sep_idx = clearsig.index(b('\x00'), 2) except ValueError: raise VerificationError('Verification failed') # Get the hash and the hash method (method_name, signature_hash) = _find_method_hash(clearsig[sep_idx+1:]) message_hash = _hash(message, method_name) # Compare the real hash to the hash in the signature if message_hash != signature_hash: raise VerificationError('Verification failed') return True
def find_signature_hash(signature, pub_key): """Returns the hash name detected from the signature. If you also want to verify the message, use :py:func:`rsa.verify()` instead. It also returns the name of the used hash. :param signature: the signature block, as created with :py:func:`rsa.sign`. :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message. :returns: the name of the used hash. """ keylength = common.byte_size(pub_key.n) encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) clearsig = transform.int2bytes(decrypted, keylength) return _find_method_hash(clearsig)
def decrypt(crypto, priv_key): r'''Decrypts the given message using PKCS1 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. @param crypto: the crypto text as returned by ``encrypt(message, pub_key)`` @param priv_key: the private key to decrypt with. @raise 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. >>> from rsa import key, common >>> (pub_key, priv_key) = key.newkeys(256) It works with strings: >>> decrypt(encrypt('hello', pub_key), priv_key) 'hello' And with binary data: >>> decrypt(encrypt('\x00\x00\x00\x00\x01', pub_key), priv_key) '\x00\x00\x00\x00\x01' ''' blocksize = common.byte_size(priv_key['n']) encrypted = transform.bytes2int(crypto) decrypted = core.decrypt_int(encrypted, priv_key['d'], priv_key['n']) cleartext = transform.int2bytes(decrypted, blocksize) # If we can't find the cleartext marker, decryption failed. if cleartext[0:2] != '\x00\x02': raise DecryptionError('Decryption failed') # Find the 00 separator between the padding and the message try: sep_idx = cleartext.index('\x00', 2) except ValueError: raise DecryptionError('Decryption failed') return cleartext[sep_idx+1:]
def verify_hhj(after_hash, signature, publickey, encoding='utf8'): after_hash1 = str(after_hash) signature_full = base64.b64decode(signature) pubder = base64.b64decode(publickey) pub_key = rsa.PublicKey.load_pkcs1(pubder, 'DER') keylength = common.byte_size(pub_key.n) decrypted_hash = b'' while signature_full: signature = signature_full[:keylength] signature_full = signature_full[keylength:] encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) clearsig = transform.int2bytes(decrypted, keylength) if clearsig[0:2] != b'\x00\x01': return False clearsig = clearsig[2:] if b'\x00' not in clearsig: return False sep_idx = clearsig.index(b'\x00') clearsig = clearsig[sep_idx + 1:] decrypted_hash += clearsig decrypted_hash = str(decrypted_hash, 'utf-8') return decrypted_hash == after_hash1
def verify(message, signature, pub_key): """Verifies that the signature matches the message. The hash method is detected automatically from the signature. :param 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. :param signature: the signature block, as created with :py:func:`rsa.sign`. :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message. :raise VerificationError: when the signature doesn't match the message. :returns: the name of the used hash. """ keylength = common.byte_size(pub_key.n) encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) clearsig = transform.int2bytes(decrypted, keylength) # Get the hash method method_name = _find_method_hash(clearsig) message_hash = compute_hash(message, method_name) # Reconstruct the expected padded hash cleartext = HASH_ASN1[method_name] + message_hash expected = _pad_for_signing(cleartext, keylength) if len(signature) != keylength: raise VerificationError('Verification failed') # Compare with the signed one if expected != clearsig: raise VerificationError('Verification failed') return method_name
def verify(message, signature, pub_key): """Verifies that the signature matches the message. The hash method is detected automatically from the signature. :param 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. :param signature: the signature block, as created with :py:func:`rsa.sign`. :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message. :raise VerificationError: when the signature doesn't match the message. .. warning:: Never display the stack trace of a :py:class:`rsa.pkcs1.VerificationError` 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. """ blocksize = common.byte_size(pub_key.n) encrypted = transform.bytes2int(signature) decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) clearsig = transform.int2bytes(decrypted, blocksize) if clearsig[0:2] != b('\x00\x01'): raise VerificationError('Verification failed') try: sep_idx = clearsig.index(b('\x00'), 2) except ValueError: raise VerificationError('Verification failed') method_name, signature_hash = _find_method_hash(clearsig[sep_idx + 1:]) message_hash = _hash(message, method_name) if message_hash != signature_hash: raise VerificationError('Verification failed')
def decrypt(crypto, priv_key): r'''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. :param crypto: the crypto text as returned by :py:func:`rsa.encrypt` :param priv_key: the :py:class:`rsa.PrivateKey` to decrypt with. :raise 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('hello', pub_key) >>> decrypt(crypto, priv_key) 'hello' And with binary data: >>> crypto = encrypt('\x00\x00\x00\x00\x01', pub_key) >>> decrypt(crypto, priv_key) '\x00\x00\x00\x00\x01' Altering the encrypted information will *likely* cause a :py:class:`rsa.pkcs1.DecryptionError`. If you want to be *sure*, use :py:func:`rsa.sign`. .. warning:: Never display the stack trace of a :py:class:`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('hello', pub_key) >>> crypto = crypto[0:5] + 'X' + crypto[6:] # change a byte >>> decrypt(crypto, priv_key) Traceback (most recent call last): ... DecryptionError: Decryption failed ''' blocksize = common.byte_size(priv_key.n) encrypted = transform.bytes2int(crypto) decrypted = core.decrypt_int(encrypted, priv_key.d, priv_key.n) cleartext = transform.int2bytes(decrypted, blocksize) # If we can't find the cleartext marker, decryption failed. if cleartext[0:2] != b('\x00\x02'): raise DecryptionError('Decryption failed') # Find the 00 separator between the padding and the message try: sep_idx = cleartext.index(b('\x00'), 2) except ValueError: raise DecryptionError('Decryption failed') return cleartext[sep_idx + 1:]
def decrypt(crypto, priv_key): r'''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. :param crypto: the crypto text as returned by :py:func:`rsa.encrypt` :param priv_key: the :py:class:`rsa.PrivateKey` to decrypt with. :raise 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('hello', pub_key) >>> decrypt(crypto, priv_key) 'hello' And with binary data: >>> crypto = encrypt('\x00\x00\x00\x00\x01', pub_key) >>> decrypt(crypto, priv_key) '\x00\x00\x00\x00\x01' Altering the encrypted information will *likely* cause a :py:class:`rsa.pkcs1.DecryptionError`. If you want to be *sure*, use :py:func:`rsa.sign`. .. warning:: Never display the stack trace of a :py:class:`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('hello', pub_key) >>> crypto = crypto[0:5] + 'X' + crypto[6:] # change a byte >>> decrypt(crypto, priv_key) Traceback (most recent call last): ... DecryptionError: Decryption failed ''' blocksize = common.byte_size(priv_key.n) encrypted = transform.bytes2int(crypto) decrypted = core.decrypt_int(encrypted, priv_key.d, priv_key.n) cleartext = transform.int2bytes(decrypted, blocksize) # If we can't find the cleartext marker, decryption failed. if cleartext[0:2] != b('\x00\x02'): raise DecryptionError('Decryption failed') # Find the 00 separator between the padding and the message try: sep_idx = cleartext.index(b('\x00'), 2) except ValueError: raise DecryptionError('Decryption failed') return cleartext[sep_idx+1:]
def verify_sign(message, public_key, signature): signature_int = int.from_bytes(signature, sys.byteorder) decrypted_hash = decrypt_int(signature_int, public_key.e, public_key.n) hash_int = int.from_bytes(md5(message).digest(), sys.byteorder) return hash_int == decrypted_hash