o a?@sUdZddlZddlZddlZddlZddlmZddlmZm Z m Z m Z ej r,ej ZnejZdddd d d d Zejejejejejejd Zejeejgeffed <ejdkroeddddeejejej dGddde!Z"Gddde"Z#Gddde"Z$de%de&de%fddZ'de%de&de%fddZ(de%d e j)de%fd!d"Z*d#e%d$e j+de%fd%d&Z,d'e%d$e j+d(ede%fd)d*Z-de%d$e j+d(ede%fd+d,Z.de%d-e%d e j)defd.d/Z/d-e%d e j)defd0d1Z0d2ej1d3e&dej2e%fd4d5Z3dej4e%ej1fd6ede%fd7d8Z5d9e%defd:d;Z6gd<Z7e8d=krNe9d>ddl:Z:e;d?D]ZZ?e>r6ne>> block = _pad_for_encryption(b'hello', 16) >>> len(block) 16 >>> block[0:2] b'\x00\x02' >>> block[-6:] b'\x00hello' ;%i bytes needed for message, but there is only space for %ir N)len OverflowErrorosurandomreplacejoin)rr max_msglength msglengthpaddingpadding_length needed_bytes new_paddingrrr_pad_for_encryption]s$      r-cCsJ|d}t|}||krtd||f||d}dd|dd|gS)ajPads the message for signing, returning the padded message. The padding is always a repetition of FF bytes. :return: 00 01 PADDING 00 MESSAGE >>> block = _pad_for_signing(b'hello', 16) >>> len(block) 16 >>> block[0:2] b'\x00\x01' >>> block[-6:] b'\x00hello' >>> block[2:-6] b'\xff\xff\xff\xff\xff\xff\xff\xff' rrr rsr)r!r"r&)rrr'r(r*rrr_pad_for_signings r/pub_keycCsBt|j}t||}t|}t||j|j}t ||}|S)aEncrypts the given message using PKCS#1 v1.5 :param message: the message to encrypt. Must be a byte string no longer than ``k-11`` bytes, where ``k`` is the number of bytes needed to encode the ``n`` component of the public key. :param pub_key: the :py:class:`rsa.PublicKey` to encrypt with. :raise OverflowError: when the message is too large to fit in the padded block. >>> from rsa import key, common >>> (pub_key, priv_key) = key.newkeys(256) >>> message = b'hello' >>> crypto = encrypt(message, pub_key) The crypto text should be just as long as the public key 'n' component: >>> len(crypto) == common.byte_size(pub_key.n) True ) r byte_sizenr-r bytes2intr encrypt_inte int2bytes)rr0 keylengthpaddedpayload encryptedblockrrrencrypts    r<cryptopriv_keyc Cst|j}t|}||}t||}t||kr tdt |ddd }| dd}|dk}||B} | r>td||ddS)aaDecrypts 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(b'hello', pub_key) >>> decrypt(crypto, priv_key) b'hello' And with binary data: >>> crypto = encrypt(b'\x00\x00\x00\x00\x01', pub_key) >>> decrypt(crypto, priv_key) b'\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(b'hello', pub_key) >>> crypto = crypto[0:5] + b'X' + crypto[6:] # change a byte >>> decrypt(crypto, priv_key) Traceback (most recent call last): ... rsa.pkcs1.DecryptionError: Decryption failed zDecryption failedNr r r) rr1r2rr3blinded_decryptr6r!rrfind) r=r> blocksizer: decrypted cleartextcleartext_marker_badsep_idx sep_idx_bad anything_badrrrdecrypts 3     rJ hash_value hash_methodc Cs^|tvr td|t|}||}t|j}t||}t|}||}t ||} | S)abSigns a precomputed hash with the private key. Hashes the message, then signs the hash with the given key. This is known as a "detached signature", because the message itself isn't altered. :param hash_value: A precomputed hash to sign (ignores message). :param priv_key: the :py:class:`rsa.PrivateKey` to sign with :param hash_method: the hash method used on the message. Use 'MD5', 'SHA-1', 'SHA-224', SHA-256', 'SHA-384' or 'SHA-512'. :return: a message signature block. :raise OverflowError: if the private key is too small to contain the requested hash. Invalid hash method: %s) HASH_ASN1 ValueErrorrr1r2r/rr3blinded_encryptr6) rKr>rLasn1coderEr7r8r9r:r;rrr sign_hashs      rRcCst||}t|||S)aSigns the message with the private key. Hashes the message, then signs the hash with the given key. This is known as a "detached signature", because the message itself isn't altered. :param message: the message to sign. 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 priv_key: the :py:class:`rsa.PrivateKey` to sign with :param hash_method: the hash method used on the message. Use 'MD5', 'SHA-1', 'SHA-224', SHA-256', 'SHA-384' or 'SHA-512'. :return: a message signature block. :raise OverflowError: if the private key is too small to contain the requested hash. ) compute_hashrR)rr>rLmsg_hashrrrsign?s  rU signaturec Cst|j}t|}t||j|j}t||}t |}t ||}t ||} t | |} t ||kr8td| |kr@td|S)aJVerifies 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. Verification failed)rr1r2rr3r decrypt_intr5r6_find_method_hashrSrNr/r!r) rrVr0r7r:rDclearsig method_name message_hashrEexpectedrrrverifyUs       r^cCs<t|j}t|}t||j|j}t||}t |S)aReturns 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. ) rr1r2rr3rrXr5r6rY)rVr0r7r:rDrZrrrfind_signature_hash{s  r_infilerCccs6 ||}t|}|dkrdS|V||krdSq)zGenerator, yields each block of ``blocksize`` bytes in the input file. :param infile: file to read and separate in blocks. :param blocksize: block size in bytes. :returns: a generator that yields the contents of each block TrN)readr!)r`rCr; read_bytesrrryield_fixedblockss rcr[cCsz|tvr td|t|}|}t|tr|||St|dr*t|jds,Jt|dD]}||q1|S)a4Returns the message digest. :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 method_name: the hash method, must be a key of :py:const:`HASH_METHODS`. rMra__call__i) r rO isinstancebytesupdatehasattrrarcdigest)rr[methodhasherr;rrrrSs    rSrZcCs*tD] \}}||vr|Sqtd)zFinds the hash method. :param clearsig: full padded ASN1 and hash. :return: the used hash method. :raise VerificationFailed: when the hash method cannot be found rW)rNitemsr)rZhashnamerQrrrrYs rY)r<rJrUr^rrr __main__z'Running doctests 1000x or until failureidz%i timesz Doctests done)@rhashlibr#systypinghmacrrrrr TYPE_CHECKING_HashHashTypeAnyrNmd5sha1sha224sha256sha384sha512r DictstrCallable__annotations__ version_inforgsha3_256sha3_384sha3_512 Exceptionr rrrfintr-r/ PublicKeyr< PrivateKeyrJrRrUr^r_BinaryIOIteratorrcUnionrSrY__all__rprintdoctestrangecounttestmodfailurestestsrrrrs  "  -! S!&"