def generate_root_certificate(private_key: rsa.RSAPrivateKey) -> x509.Certificate: backend = cryptography.hazmat.backends.default_backend() subject = x509.Name( [x509.NameAttribute( x509.oid.NameOID.COMMON_NAME, 'root' )] ) builder = x509.CertificateBuilder() return builder.subject_name(subject).issuer_name(subject) \ .not_valid_before(datetime.datetime.utcnow()) \ .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=1)) \ .serial_number(1) \ .public_key(private_key.public_key()) \ .add_extension(extension=x509.BasicConstraints(ca=True, path_length=1), critical=True) \ .add_extension(extension=x509.KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=False, decipher_only=False, ), critical=True) \ .sign(private_key=private_key, algorithm=hashes.SHA256(), backend=backend)
def compute_signature(pkey: RSAPrivateKey, text: str) -> str: signature = pkey.sign( text.encode('utf-8'), padding.PKCS1v15(), SHA256(), ) return b64encode(signature).decode('ascii')
def _DefaultBlobSign( self, blob_bytes: bytes, private_key: rsa.RSAPrivateKey, ) -> bytes: padding_algorithm = padding.PKCS1v15() return private_key.sign(blob_bytes, padding_algorithm, hashes.SHA256())
def getFileSignature(cls, filename: str, private_key: RSAPrivateKey) -> Optional[str]: """Creates the signature for the (hash of the) provided file, given a private key. :param filename: The file to be signed. :param private_key: The private key used for signing. :return: The signature if successful, 'None' otherwise. """ file_hash = cls.getFileHash(filename) if file_hash is None: return None try: file_hash_bytes = base64.b64decode(file_hash) signature_bytes = private_key.sign( file_hash_bytes, padding.PSS(mgf=padding.MGF1(cls.__hash_algorithm), salt_length=padding.PSS.MAX_LENGTH), Prehashed(cls.__hash_algorithm)) return base64.b64encode(signature_bytes).decode("utf-8") except: # Yes, we do really want this on _every_ exception that might occur. Logger.logException( "e", "Couldn't sign '{0}', no signature generated.".format( filename)) return None
def rsa_key_to_str(private_key: rsa.RSAPrivateKey) -> str: """ return RSA private key as string - PEM format, no encryption """ return private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() ).decode()
def serialize_privkey(private_key: rsa.RSAPrivateKey) -> bytes: """ Serialize an RSA private into the DER format. """ return private_key.private_bytes(serialization.Encoding.DER, serialization.PrivateFormat.PKCS8, serialization.NoEncryption())
def getHashSignature(cls, shash: str, private_key: RSAPrivateKey, err_info: Optional[str] = None) -> Optional[str]: """ Creates the signature for the provided hash, given a private key. :param shash: The provided string. :param private_key: The private key used for signing. :param err_info: Some optional extra info to be printed on error (for ex.: a filename the data came from). :return: The signature if successful, 'None' otherwise. """ try: hash_bytes = base64.b64decode(shash) signature_bytes = private_key.sign( hash_bytes, padding.PSS(mgf=padding.MGF1(cls.__hash_algorithm), salt_length=padding.PSS.MAX_LENGTH), Prehashed(cls.__hash_algorithm)) return base64.b64encode(signature_bytes).decode("utf-8") except: # Yes, we do really want this on _every_ exception that might occur. if err_info is None: err_info = "HASH:" + shash Logger.logException( "e", "Couldn't sign '{0}', no signature generated.".format( err_info)) return None
def save_private_key(key: rsa.RSAPrivateKey, file_name: Path, passphrase: bytes = None, encoding: str = 'PEM', format: str = 'PKCS8'): """ Save private key to file. Default is PEM key in PKCS8 format. Parameters ---------- key Private key object. file_name Output file name. passphrase Passphrase to encrypt file. encoding Encoding format. format Output format. Values: PKCS8 or TraditionalOpenSSL """ with open(str(file_name), "wb") as outf: outf.write( key.private_bytes( encoding=Encoding[encoding], format=PrivateFormat[format], encryption_algorithm=serialization.BestAvailableEncryption( password=passphrase), ))
def generate_self_signed(private_key: rsa.RSAPrivateKey, subject: x509.Name) -> x509.Certificate: """Generate a Self-Signed certificate for use with a CMS PKCS#10 request. Args: private_key (rsa.RSAPrivateKey): The private key to sign the certificate with. subject (x509.Name): The subject used in the CSR, which must match this certificates subject. Returns: x509.Certificate: Self signed certificate for CMS envelope """ one_day = datetime.timedelta(1, 0, 0) builder = x509.CertificateBuilder() builder = builder.subject_name(subject) builder = builder.issuer_name(subject) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=365)) builder = builder.serial_number(x509.random_serial_number()) builder = builder.public_key(private_key.public_key()) # builder = builder.add_extension( # x509.KeyUsage(digital_signature=True, key_encipherment=True), critical=True # ) certificate = builder.sign(private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend()) return certificate
def obtain_key_id(token: str, rsa_key: RSAPrivateKey, staging: bool = False) -> Response: target = '/g_business/v1/authentication_keys' key_encoding = Encoding.PEM key_format = PublicFormat.SubjectPublicKeyInfo public_key = rsa_key.public_key().public_bytes(key_encoding, key_format) body = {'public_key': public_key.decode(), 'token': token} with SatispayClient('PLACEHOLDER', rsa_key, staging) as client: return client.post(target, json=body)
def check_certificate_against_private_key( cert: Certificate, private_key: RSAPrivateKey, ) -> None: # Check if the public key of certificate matches the public key corresponding to the given # private one assert (_rsa_public_key_from_cert_or_csr(cert).public_numbers() == private_key.public_key().public_numbers())
def decode(cls, private_key: RSAPrivateKey, token_bytes: str) -> str: public_bytes = private_key.public_key().public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo) token = jwt_decode(token_bytes, public_bytes, algorithms=['RS256'], verify=False) return token['sub']
def decrypt_message(ciphertext: bytes, private_key: rsa.RSAPrivateKey = PRIVATE_KEY) -> bytes: """Decrypt some message encrypted with out public key.""" return private_key.decrypt( ciphertext, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None))
def pk_decrypt(ciphertext: bytes, private_key: rsa.RSAPrivateKey) -> bytes: """ Decrypt an RSAES-OAEP-encrypted message. """ plaintext = private_key.decrypt( ciphertext, padding.OAEP(padding.MGF1(hashes.SHA1()), hashes.SHA1(), None)) return plaintext
def gen_self_signed(key: rsa.RSAPrivateKey, cert_opts: Dict, crypto_opts: Dict) -> None: # noqa # subject / issuer subject = issuer = _subject(cert_opts) # init builder builder = x509.CertificateBuilder() # set subject and issuer builder = builder.subject_name(subject) builder = builder.issuer_name(issuer) # set public key builder = builder.public_key(key.public_key()) # set serial number serial = x509.random_serial_number() builder = builder.serial_number(serial) # set expiration now = datetime.datetime.utcnow() days = cert_opts['days'] builder = builder.not_valid_before(now) builder = builder.not_valid_after(now + datetime.timedelta(days=days)) # add base extensions for is_critical, ext in _extensions(key, cert_opts): builder = builder.add_extension(ext, critical=is_critical) # add AuthorityKeyIdentifier extension (experimental feature) pkey = key.public_key() key_identifier = x509.extensions._key_identifier_from_public_key(pkey) authority_cert_issuer = [x509.DirectoryName(issuer)] builder = builder.add_extension(x509.AuthorityKeyIdentifier( key_identifier, authority_cert_issuer, serial), critical=False) # sign the certificate md_alg = MD_ALGS[crypto_opts['md_alg']] crt = builder.sign(key, md_alg) # write to file crt_out = crypto_opts['crt_out'] with open(str(crt_out), "wb") as fp: fp.write(crt.public_bytes(serialization.Encoding.PEM)) fp.close()
def pk_sign(message: bytes, private_key: rsa.RSAPrivateKey) -> bytes: """ Sign a message using RSASSA-PSS. """ signer = private_key.signer(padding.PSS(padding.MGF1(hashes.SHA256()), padding.PSS.MAX_LENGTH), hashes.SHA256()) signer.update(message) return signer.finalize()
def pk_sign(message: bytes, private_key: rsa.RSAPrivateKey) -> bytes: """ Sign a message using RSASSA-PSS. """ signer = private_key.signer( padding.PSS(padding.MGF1(hashes.SHA256()), padding.PSS.MAX_LENGTH), hashes.SHA256()) signer.update(message) return signer.finalize()
def make_jwks(_private_key: RSAPrivateKey): """Returns JWKS.""" jwk = json.loads( RSAAlgorithm.to_jwk(_private_key.public_key()), ) jwk['kid'] = TEST_KID return { 'keys': [jwk] }
def get_envelope(self, key: RSAPrivateKey): json_message = self.to_json() signature = base64.b64encode( key.sign(json_message.encode("utf-8"), padding.PKCS1v15(), hashes.SHA256()) ) return PaymentRequestEnvelope( message=json_message, signature=signature.decode("utf-8") )
def pk_decrypt(ciphertext: bytes, private_key: rsa.RSAPrivateKey) -> bytes: """ Decrypt an RSAES-OAEP-encrypted message. """ plaintext = private_key.decrypt(ciphertext, padding.OAEP( padding.MGF1(hashes.SHA1()), hashes.SHA1(), None)) return plaintext
def get_decrypted_envelope_data(self, certificate: x509.Certificate, key: rsa.RSAPrivateKey) -> bytes: """Decrypt the encrypted envelope data: Decrypt encrypted_key using public key of CA encrypted_key is available at content.recipient_infos[x].encrypted_key algo is content.recipient_infos[x].key_encryption_algorithm at the moment this is RSA """ encap = self.encap_content_info ct = encap['content_type'].native print(ct) recipient_info = encap['content']['recipient_infos'][0] encryption_algo = recipient_info.chosen[ 'key_encryption_algorithm'].native encrypted_key = recipient_info.chosen['encrypted_key'].native assert encryption_algo['algorithm'] == 'rsa' plain_key = key.decrypt( encrypted_key, padding=asympad.PKCS1v15(), ) # Now we have the plain key, we can decrypt the encrypted data encrypted_contentinfo = encap['content']['encrypted_content_info'] print('encrypted content type: {}'.format( encrypted_contentinfo['content_type'].native)) algorithm = encrypted_contentinfo[ 'content_encryption_algorithm'] #: EncryptionAlgorithm encrypted_content_bytes = encrypted_contentinfo[ 'encrypted_content'].native symkey = None if algorithm.encryption_cipher == 'aes': symkey = AES(plain_key) print('cipher AES') elif algorithm.encryption_cipher == 'tripledes': symkey = TripleDES(plain_key) print('cipher 3DES') else: print('Dont understand encryption cipher: ', algorithm.encryption_cipher) print('key length: ', algorithm.key_length) print('enc mode: ', algorithm.encryption_mode) cipher = Cipher(symkey, modes.CBC(algorithm.encryption_iv), backend=default_backend()) decryptor = cipher.decryptor() return decryptor.update(encrypted_content_bytes) + decryptor.finalize()
def encode(self, private_key: RSAPrivateKey) -> bytes: private_bytes = private_key.private_bytes( encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption()) public_key = private_key.public_key() numbers = public_key.public_numbers() n = numbers.n.to_bytes(int(public_key.key_size / 8), 'big').lstrip(b'\x00') kid = sha1(n).hexdigest() payload = self.payload() return jwt_encode(payload, private_bytes, algorithm='RS256', headers={'kid': kid})
def sign(self, key: rsa.RSAPrivateKey, msg: bytes) -> bytes: """Sign the ``msg`` using ``key``.""" try: return key.sign(msg, self.padding, self.hash) except AttributeError as error: logger.debug(error, exc_info=True) raise errors.Error("Public key cannot be used for signing") except ValueError as error: # digest too large logger.debug(error, exc_info=True) raise errors.Error(str(error))
def sign(private_key: RSAPrivateKey, data: bytes) -> bytes: """Sign one block of data which can be verified later by other using the public key. Args: private_key: The private key with which the data is signed. data: The message data to sign. Returns: Signature """ return private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
def write_key(rsa_key: RSAPrivateKey, path: PathLike, password: Optional[str] = None) -> None: try: encryption_algorithm = BestAvailableEncryption(password.encode()) except AttributeError: encryption_algorithm = NoEncryption() pem = rsa_key.private_bytes(Encoding.PEM, PrivateFormat.PKCS8, encryption_algorithm) with open(path, 'wb') as file: file.write(pem)
def dump_private_key(key: rsa.RSAPrivateKey) -> bytes: """Dump a private key to PEM format (text) :param key: The Private Key objec to dump :return: The bytes of the private key, as PEM """ return key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), )
def rsa_decrypt(enc_short_message: bytes, private_key: rsa.RSAPrivateKey) -> bytes: """ decrypt Optimal Asymmetric Encryption Padding (OAEP)""" hash_algorithm = hashes.SHA512 if private_key.key_size >= 2048 else hashes.SHA256 return private_key.decrypt( ciphertext=enc_short_message, padding=padding.OAEP( mgf=padding.MGF1(algorithm=hash_algorithm()), algorithm=hash_algorithm(), label=None ) )
def get_private_key_pem(private_key: RSAPrivateKey) -> bytes: """ Returns private key PEM file bytes. :param private_key: RSPrivateKey :return: bytes """ return private_key.private_bytes( # type: ignore encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), )
def _save_key(namespace: str, identifier: str, key_pair: rsa.RSAPrivateKey): key_dir = pathlib.Path(KEY_STORE_PATH) / namespace / identifier os.makedirs(key_dir) with open(key_dir / 'id_rsa', 'wb') as f: key_binary = key_pair.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() ) f.write(key_binary) with open(key_dir / 'id_rsa.pub', 'wb') as f: key_binary = key_pair.public_key().public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) f.write(key_binary)
def key_to_bytes( key: RSAPrivateKey, passphrase: Optional[str] = None, ): kwargs = {"encryption_algorithm": serialization.NoEncryption()} if passphrase is not None: kwargs["encryption_algorithm"] = serialization.BestAvailableEncryption( passphrase.encode()) return key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, **kwargs, )
def private_key(self, private_key: rsa.RSAPrivateKey): if self._password is not None: enc = serialization.BestAvailableEncryption(self._password) else: enc = serialization.NoEncryption() key_bytes = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=enc) with open(os.path.join(self._key_path), 'wb') as fd: fd.write(key_bytes)
def attack_pubkey_deception_jwk(self, pk: RSAPrivateKey, kid: str, jwt: TestJWT = None): if jwt is None: jwt = self.init_token() pubkey: RSAPublicKey = pk.public_key() jwk = utils.rsa_pubkey_to_jwk(pem_file=None, key_id=kid, pubkey=pubkey) jwt.header['jwk'] = jwk jwt.header['jwk']['use'] = "sig" del (jwt.header['jwk']['alg']) self.payloads['attack_pubkey_deception_jwk'] = utils.force_unicode( jwt.build_token(pk))
def _key_to_str(key_object: rsa.RSAPrivateKey) -> str: """ Converts a private key object to a string """ pem = key_object.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()) key_str = pem.decode() # type: str key_str = key_str[len(_PRIVATE_BEGIN_TAG):] # remove being tag key_str = key_str[:-(len(_PRIVATE_END_TAG) + 1)] # remove end tag key_str = key_str.replace("\n", "") # remove new lines return key_str
def serialize_privkey(private_key: rsa.RSAPrivateKey) -> bytes: """ Serialize an RSA private into the DER format. """ return private_key.private_bytes(serialization.Encoding.DER, serialization.PrivateFormat.PKCS8, serialization.NoEncryption())