def rsa_decrypt_bytes(rsa_private_key_pem, data): rsa_private_key = serialization.load_pem_private_key( data=rsa_private_key_pem, password=None, backend=default_backend()) pad = padding.OAEP(mgf=padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) return rsa_private_key.decrypt(data, pad)
def kdf_tls11(self, cr, sr, secret, cipher_params, flow_key): label = b'key expansion' secret_md5 = secret[:len(secret) / 2] secret_sha = secret[-len(secret) / 2:] md5_material = b'' cur_hash = self.hmac(secret_md5, MD5(), b'%s%s%s' % (label, sr, cr)) for i in range(16): md5_material += self.hmac(secret_md5, MD5(), b'%s%s%s%s' % (cur_hash, label, sr, cr)) cur_hash = self.hmac(secret_md5, MD5(), cur_hash) sha_material = b'' cur_hash = self.hmac(secret_sha, SHA1(), b'%s%s%s' % (label, sr, cr)) for i in range(16): sha_material += self.hmac(secret_sha, SHA1(), b'%s%s%s%s' % (cur_hash, label, sr, cr)) cur_hash = self.hmac(secret_sha, SHA1(), cur_hash) output = b'' for i in range(min(len(md5_material), len(sha_material))): output += chr(ord(md5_material[i]) ^ ord(sha_material[i])) key_material_lengths = [cipher_params['mac_key_length']]*2 + \ [cipher_params['enc_key_length']]*2 + \ [cipher_params['fixed_iv_length']]*2 offset = 0 key_material = [] for l in key_material_lengths: key_material.append(output[offset:offset + l]) offset += l return key_material
def __decrypt_with_rsa(self, content, user_sk): """ Decrypt RSAES-OAEP encrypted content (single block) @developer: vsmysle This method decrypts a single RSA ciphertext block only :param content: bytes content to decrypt :param user_sk: instance of cryptography.hazmat.primitives.rsa .RSAPrivateKey to use for a decryption :return: string decryption of an input content """ # TODO: add exceptions self.logger.debug("rsa decryption") try: plaintext = user_sk.decrypt( content, asym_padding.OAEP(mgf=asym_padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) except InvalidKey: self.logger.warning("Invalid key!") return return plaintext
def __sign_content(self, content, user_sk): """ Produce a signature of an input content using RSASSA-PSS scheme @developer: vsmysle :param content: bytes content to sign :param user_sk: instance of cryptography.hazmat.primitives.rsa. RSAPrivateKey :return: bytes of signature of the input content """ # TODO: add exceptions self.logger.debug("generating a signature of an input content") # creating signer that will sign our content try: signer = user_sk.signer( # we use RSASSA-PSS padding for the signature scheme asym_padding.PSS(mgf=asym_padding.MGF1(SHA1()), salt_length=asym_padding.PSS.MAX_LENGTH), SHA1()) except InvalidKey: self.logger.warning("Invalid key!") return signer.update(content) signature = signer.finalize() self.logger.info("signature generation finished") return signature
def __encrypt_with_rsa(self, content, recipient_pk): """ Encrypt content with RSAES-OAEP scheme @developer: vsmysle This method handles an encryption of a *single* RSA block with a specified above scheme. It does not handle splitting of a header into several blocks. It has to be done by other method that would use this one only for single block encryption purpose. TODO: what is a maximum size of a content that can be padded and encrypted given a particular size of RSA key? :param content: bytes content to encrypt (probably a part of ASN.1 DER-encoded MPHeader block) :param recipient_pk: instance of cryptography.hazmat.primitives.rsa .RSAPublicKey to use for a content encryption :return: string encryption of an input content """ # TODO: add exceptions self.logger.debug("rsa encryption") ciphertext = recipient_pk.encrypt( content, asym_padding.OAEP(mgf=asym_padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) self.logger.info("encrypted") return ciphertext
def tap_handshake(payload, onion_key): pk_enc = payload[:PK_ENC_LEN] sym_enc = payload[PK_ENC_LEN:TAP_C_HANDSHAKE_LEN] decrypted = onion_key.decrypt(pk_enc, OAEP(MGF1(SHA1()), SHA1(), None)) sym_key = decrypted[:KEY_LEN] dh_first_part = decrypted[KEY_LEN:PK_ENC_LEN] initial_counter = "\x00" * 16 dh_second_part = Cipher( AES(sym_key), modes.CTR(initial_counter), backend=_default_backend).decryptor().update(sym_enc) y = dh_first_part + dh_second_part privkey = DH_PARAM.generate_private_key() shared_key = privkey.exchange( DHPublicNumbers(bytes_to_long(y), DH_PARAM_NUMBERS).public_key(backend=_default_backend)) encoded_privkey = EncodedDHPublicKey(privkey) return (encoded_privkey, kdf_tor(shared_key))
class PassportKey: _padding: Final[OAEP] = OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) def __init__(self, private_key: RSAPrivateKey) -> None: if not isinstance(private_key, RSAPrivateKey): raise RuntimeError('Key is not RSA private key') self._private_key: Final[RSAPrivateKey] = private_key public_key = self._private_key.public_key() public_bytes = public_key.public_bytes( serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo) self._public_key_pem: Final[str] = public_bytes.decode() @staticmethod def load_der(private_bytes: bytes) -> 'PassportKey': private_key = serialization.load_der_private_key(private_bytes, password=None) return PassportKey(cast(RSAPrivateKey, private_key)) @staticmethod def load_pem(private_text: str) -> 'PassportKey': private_key = serialization.load_pem_private_key(private_text.encode(), password=None) return PassportKey(cast(RSAPrivateKey, private_key)) def decrypt(self, ciphertext: bytes) -> bytes: return self._private_key.decrypt(ciphertext, self._padding) @property def public_key_pem(self) -> str: return self._public_key_pem
def __verify_signature(self, signature, signer_pk, content): """ Verify RSASSA-PSS signature @developer: vsmysle :param signature: signature bytes to verify :param signer_pk: instance of cryptography.hazmat.primitives. rsa.RSAPublicKey that is a public key of a signer :param content: content to verify a signature of :return: bool verification result """ self.logger.debug("starting signature verification routine") try: signer_pk.verify( signature, content, asym_padding.PSS(mgf=asym_padding.MGF1(SHA1()), salt_length=asym_padding.PSS.MAX_LENGTH), SHA1()) except InvalidSignature: self.logger.warn("signature verification failed") return False self.logger.info("signature OK") return True
def decrypted_secret(self): """ :obj:`str`: Lazily decrypt and return secret. Raises: telegram.TelegramDecryptionError: Decryption failed. Usually due to bad private/public key but can also suggest malformed/tampered data. """ if self._decrypted_secret is None: # Try decrypting according to step 1 at # https://core.telegram.org/passport#decrypting-data # We make sure to base64 decode the secret first. # Telegram says to use OAEP padding so we do that. The Mask Generation Function # is the default for OAEP, the algorithm is the default for PHP which is what # Telegram's backend servers run. try: self._decrypted_secret = self.bot.private_key.decrypt( b64decode(self.secret), OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) except ValueError as e: # If decryption fails raise exception raise TelegramDecryptionError(e) return self._decrypted_secret
def rsa_decrypt(ciphertext, private_key): data = private_key.decrypt(ciphertext=b64decode(ciphertext), padding=OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) result = data.decode('UTF-8') return result
def decrypted_secret(self) -> str: """ :obj:`str`: Lazily decrypt and return secret. Raises: telegram.error.PassportDecryptionError: Decryption failed. Usually due to bad private/public key but can also suggest malformed/tampered data. """ if self._decrypted_secret is None: if not CRYPTO_INSTALLED: raise RuntimeError( "To use Telegram Passports, PTB must be installed via `pip install " "python-telegram-bot[passport]`." ) # Try decrypting according to step 1 at # https://core.telegram.org/passport#decrypting-data # We make sure to base64 decode the secret first. # Telegram says to use OAEP padding so we do that. The Mask Generation Function # is the default for OAEP, the algorithm is the default for PHP which is what # Telegram's backend servers run. try: self._decrypted_secret = self.get_bot().private_key.decrypt( # type: ignore b64decode(self.secret), OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None), # skipcq ) except ValueError as exception: # If decryption fails raise exception raise PassportDecryptionError(exception) from exception return self._decrypted_secret
def wrap_key(self, key, algorithm='RSA'): if algorithm == 'RSA': return self.public_key.encrypt( key, OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) raise ValueError(_ERROR_UNKNOWN_KEY_WRAP_ALGORITHM)
def rsa_encrypt_bytes(rsa_public_key_pem, data): rsa_public_key = serialization.load_pem_public_key( rsa_public_key_pem, backend=default_backend()) pad = padding.OAEP(mgf=padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) return rsa_public_key.encrypt(data, pad)
def process_header(self, data): if self._cipher_key_len is None: if data[0:6] != FILEMAGIC: raise EncryptorError("Invalid magic bytes") self._cipher_key_len = struct.unpack(">H", data[6:8])[0] else: pad = padding.OAEP(mgf=padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) try: plainkey = self.rsa_private_key.decrypt(data, pad) except AssertionError: raise EncryptorError("Decrypting key data failed") if len(plainkey) != 64: raise EncryptorError("Integrity check failed") key = plainkey[0:16] nonce = plainkey[16:32] auth_key = plainkey[32:64] self._header_size = 8 + len(data) self.cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend()).decryptor() self.authenticator = HMAC(auth_key, SHA256(), backend=default_backend())
def decrypt_encryption_key_fallback(self): """Decrypts the encryption key using the FALLBACK method. In this method, the context string, usually "CredEncryption" or "PSEEncryption", is encrypted using a derivation of a fixed key hardcoded in CommonCryptoLib, and used as key to encrypt the actual encryption key used in the file with the AES cipher. :return: Encryption key decrypted :rtype: string """ log_lps.debug("Obtaining encryption key with FALLBACK LPS mode") digest = Hash(SHA1(), backend=default_backend()) digest.update(cred_key_lps_fallback) hashed_key = digest.finalize() hmac = HMAC(hashed_key, SHA1(), backend=default_backend()) hmac.update(self.context) default_key = hmac.finalize()[:16] iv = "\x00" * 16 decryptor = Cipher(algorithms.AES(default_key), modes.CBC(iv), backend=default_backend()).decryptor() encryption_key = decryptor.update( self.encrypted_key) + decryptor.finalize() return encryption_key
def unwrap_key(self, key, algorithm): if algorithm == 'RSA': return self.private_key.decrypt( key, OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) else: raise ValueError(_ERROR_UNKNOWN_KEY_WRAP_ALGORITHM)
def rsa_encrypt(text, certificate): data = text.encode('UTF-8') public_key = certificate.public_key() cipherbyte = public_key.encrypt(plaintext=data, padding=OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) return b64encode(cipherbyte).decode('UTF-8')
def unwrap_key(self, key, algorithm): if algorithm == 'RSA': return self.private_key.decrypt( key, OAEP( mgf=MGF1(algorithm=SHA1()), # nosec algorithm=SHA1(), # nosec label=None)) raise ValueError('Unknown key wrap algorithm.')
def wrap_key(self, key, algorithm='RSA'): if algorithm == 'RSA': return self.public_key.encrypt( key, OAEP( mgf=MGF1(algorithm=SHA1()), # nosec algorithm=SHA1(), # nosec label=None)) raise ValueError('Unknown key wrap algorithm.')
def asymmetric_decrypt(ciphertext, private_key): """Asymmetrically decrypt a message""" size = DECRYPTION_BLOCK_SIZE blocks = [ciphertext[i:i + size] for i in range(0, len(ciphertext), size)] plaintext = [] for block in blocks: plaintext.append( private_key.decrypt( block, OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None))) return b''.join(plaintext)
def generate_session_key(hmac_secret=b''): """ :param hmac_secret: optional HMAC :type hmac_secret: :class:`bytes` :return: (session_key, encrypted_session_key) tuple :rtype: :class:`tuple` """ session_key = random_bytes(32) encrypted_session_key = UniverseKey.Public.encrypt(session_key + hmac_secret, OAEP(MGF1(SHA1()), SHA1(), None) ) return (session_key, encrypted_session_key)
def asymmetric_encrypt(msg, public_key): """Asymmmetrically encrypts a message""" size = ENCRYPTION_BLOCK_SIZE blocks = [msg[i:i + size] for i in range(0, len(msg), size)] ciphertext = [] for block in blocks: ciphertext.append( public_key.encrypt( block, OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None))) return b''.join(ciphertext)
def rsa_decrypt(data, rsa_priv_key_bytes): """ When given some `data` and an RSA private key, decrypt the data """ if isinstance(data, text_type): data = data.encode('utf-8') if isinstance(rsa_priv_key_bytes, text_type): rsa_priv_key_bytes = rsa_priv_key_bytes.encode('utf-8') if rsa_priv_key_bytes.startswith(b'-----'): key = serialization.load_pem_private_key(rsa_priv_key_bytes, password=None, backend=default_backend()) else: key = serialization.load_der_private_key(rsa_priv_key_bytes, password=None, backend=default_backend()) return key.decrypt(data, OAEP(MGF1(SHA1()), SHA1(), label=None))
def rsa_encrypt(data, rsa_pub_key_bytes): """ `rsa_pub_key_bytes` is a byte sequence with the public key """ if isinstance(data, text_type): data = data.encode('utf-8') if isinstance(rsa_pub_key_bytes, text_type): rsa_pub_key_bytes = rsa_pub_key_bytes.encode('utf-8') if rsa_pub_key_bytes.startswith(b'-----'): key = serialization.load_pem_public_key(rsa_pub_key_bytes, backend=default_backend()) elif rsa_pub_key_bytes.startswith(b'ssh-rsa '): key = serialization.load_ssh_public_key(rsa_pub_key_bytes, backend=default_backend()) else: key = serialization.load_der_public_key(rsa_pub_key_bytes, backend=default_backend()) return key.encrypt(data, OAEP(MGF1(SHA1()), SHA1(), label=None))
def setup_cipher_rc4(salt, password, encrypt=False): hash = Hash(SHA1(), default_backend()) hash.update(salt + bytes(password, 'ascii')) cipher = Cipher(algorithms.ARC4(hash.finalize()), None, default_backend()) cryptor = cipher.encryptor() if encrypt else cipher.decryptor() cryptor.update(bytes(RC4_SKIP)) return cryptor
def create_self_signed_certificate(self): self.private_key = self.generate_private_key() subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"WA"), x509.NameAttribute(NameOID.LOCALITY_NAME, u"Seattle"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Amazon Alexa"), x509.NameAttribute(NameOID.COMMON_NAME, u"{}".format(self.PREPOPULATED_CERT_URL)), ]) self.mock_certificate = x509.CertificateBuilder( ).subject_name(name=subject).issuer_name(name=issuer).public_key( key=self.private_key.public_key()).serial_number( number=x509.random_serial_number()).not_valid_before( time=datetime.utcnow() - timedelta(minutes=1)).not_valid_after( time=datetime.utcnow() + timedelta(minutes=1)).add_extension( x509.SubjectAlternativeName([ x509.DNSName(u"{}".format(CERT_CHAIN_DOMAIN)) ]), critical=False).sign( private_key=self.private_key, algorithm=SHA1(), backend=default_backend()) # type: Certificate self.request_verifier._cert_cache[ self.PREPOPULATED_CERT_URL] = self.mock_certificate
def build(payload, signing_key, key, iv, backend): backend = signing_key._backend signature = signing_key.sign( payload.decode('utf-8').encode('utf-16-le'), PKCS1v15(), SHA1()) sign_doc = etree.Element('SIGNATURE') etree.SubElement(sign_doc, 'VERSION').text = '1.0' etree.SubElement( sign_doc, 'DIGEST').text = binascii.hexlify(signature).decode().upper() _key_to_xml(signing_key.public_key(), sign_doc) signed = b'\xef\xbb\xbf' + payload + etree.tostring(sign_doc) compressor = zlib.compressobj(wbits=16 + zlib.MAX_WBITS) compressed = compressor.compress(signed) + compressor.flush() padder = PKCS7(len(iv) * 8).padder() padded = padder.update(compressed) + padder.finalize() encryptor = Cipher(AES(key), CBC(iv), backend=backend).encryptor() encrypted = encryptor.update(padded) + encryptor.finalize() doc = etree.Element('ARCHIVE') doc.set('TYPE', 'GEMSTONE') node = etree.SubElement(doc, 'RADIO') node.set('VERSION', '1') node.set('ENCODING', 'Base64') node.text = base64.b64encode(encrypted) return etree.tostring(doc)
def test_verify(self, backend, params): secret = params["secret"] counter = int(params["counter"]) hotp_value = params["hotp"] hotp = HOTP(secret, 6, SHA1(), backend) hotp.verify(hotp_value, counter)
def validate_revocation_certificate_chain(chain, error_messages): # a failed try to use ocsp validation for i in range(1, len(chain)): subject = chain[i - 1] issuer = chain[i] builder = ocsp.OCSPRequestBuilder() builder = builder.add_certificate(subject, issuer, SHA1()) req = builder.build() data = req.public_bytes(serialization.Encoding.DER) for e in subject.extensions: if isinstance(e.value, AuthorityInformationAccess): url = e.value._descriptions[0].access_location.value print(url) headers = {"Content-Type": "application/ocsp-request"} r = requests.post(url, data=data, headers=headers) ocsp_resp = ocsp.load_der_ocsp_response(r.content) print(ocsp_resp.certificate_status) if ocsp_resp.response_status == ocsp.OCSPResponseStatus.SUCCESSFUL: if ocsp_resp.certificate_status == ocsp.OCSPCertStatus.UNKNOWN: status = validate_revocation_certificate_chain_crl( [subject, issuer], error_messages) if not status: return False elif ocsp_resp.certificate_status == ocsp.OCSPCertStatus.REVOKED: error_messages.append( "One of the certificates is revoked") return False else: return False return True
def onion_name(key): pub_bytes = key.public_key().public_bytes( encoding=serialization.Encoding.DER, format=serialization.PublicFormat.PKCS1) hash = Hash(SHA1(), backend=default_backend()) hash.update(pub_bytes) return b32encode(hash.finalize()[:10]).lower().decode('ascii') + '.onion'