def builder( *, config: SigningConfig, certificate: Certificate, element_id: str ) -> Element: return ds.Signature( ds.SignedInfo( ds.CanonicalizationMethod(Algorithm=XML_EXC_C14N), ds.SignatureMethod( Algorithm=utils.signature_method_algorithm(config.signature_method) ), ds.Reference( ds.Transforms( ds.Transform(Algorithm=XMLDSIG_ENVELOPED_SIGNATURE), ds.Transform(Algorithm=XML_EXC_C14N), ), ds.DigestMethod( Algorithm=utils.digest_method_algorithm(config.digest_method) ), ds.DigestValue(), URI="#" + element_id, ), ), ds.SignatureValue(), ds.KeyInfo( ds.X509Data(utils.ascii_b64(certificate.public_bytes(Encoding.DER))) ), )
def put_certificate( cls, session: "core.AuthSession", object_id: int, label: str, domains: int, capabilities: CAPABILITY, certificate: x509.Certificate, ) -> "Opaque": """Import an X509 certificate into the YubiHSM as an Opaque. :param session: The session to import via. :param object_id: The ID to set for the object. Set to 0 to let the YubiHSM designate an ID. :param label: A text label to give the object. :param domains: The set of domains to assign the object to. :param capabilities: The set of capabilities to give the object. :param certificate: A certificate to import. :return: A reference to the newly created object. """ encoded_cert = certificate.public_bytes(Encoding.DER) return cls.put( session, object_id, label, domains, capabilities, ALGORITHM.OPAQUE_X509_CERTIFICATE, encoded_cert, )
def _save( cls, key: PrivateKey, cert: x509.Certificate, directory: str, name: str, key_format: Encoding ) -> ((str, bytes), (str, bytes), (str, bytes)): private_file = f'{name}.{key_format.name.lower()}' private_path = join(directory, private_file) private_bytes = key.private_bytes(key_format, PrivateFormat.PKCS8, NoEncryption()) public_file = f'{name}.pub.{key_format.name.lower()}' public_path = join(directory, public_file) public_bytes = cert.public_key().public_bytes(key_format, PublicFormat.PKCS1) cert_file = f'{name}.cert.{key_format.name.lower()}' cert_path = join(directory, cert_file) cert_bytes = cert.public_bytes(key_format) serialized = ((private_path, private_bytes), (public_path, public_bytes), (cert_path, cert_bytes)) for file_path, file_bytes in serialized: with open(file_path, 'wb') as out: out.write(file_bytes) return serialized
def _write_tls_certificate( self, port: int, # used to avoid duplicate certs with the same IP certificate: Certificate, force: bool = True) -> Path: # Read x509 = OpenSSL.crypto.X509.from_cryptography(certificate) subject_components = x509.get_subject().get_components() common_name_as_bytes = subject_components[0][1] common_name_on_certificate = common_name_as_bytes.decode() host = common_name_on_certificate certificate_filepath = self.generate_certificate_filepath(host=host, port=port) certificate_already_exists = certificate_filepath.is_file() if force is False and certificate_already_exists: raise FileExistsError( 'A TLS certificate already exists at {}.'.format( certificate_filepath)) # Write certificate_filepath.parent.mkdir(parents=True, exist_ok=True) with open(certificate_filepath, 'wb') as certificate_file: public_pem_bytes = certificate.public_bytes( self.TLS_CERTIFICATE_ENCODING) certificate_file.write(public_pem_bytes) self.log.debug( f"Saved TLS certificate for {host} to {certificate_filepath}") return certificate_filepath
def create_degenerate_certificate(certificate: x509.Certificate) -> ContentInfo: """Produce a PKCS#7 Degenerate case with a single certificate. Args: certificate (x509.Certificate): The certificate to attach to the degenerate pkcs#7 payload. Returns: ContentInfo: The ContentInfo containing a SignedData structure. """ der_bytes = certificate.public_bytes( serialization.Encoding.DER ) asn1cert = parse_certificate(der_bytes) empty = ContentInfo({ 'content_type': ContentType('data') }) sd = SignedData({ 'version': CMSVersion(1), 'encap_content_info': empty, 'digest_algorithms': DigestAlgorithms([]), 'certificates': CertificateSet([CertificateChoices('certificate', asn1cert)]), 'signer_infos': SignerInfos([]), 'crls': RevocationInfoChoices([]), }) return ContentInfo({ 'content_type': ContentType('signed_data'), 'content': sd, })
def test_decode_base64_cert_ok( trusted_cert_b64: str, trusted_cert: Certificate, ) -> None: assert _decode_base64_cert(trusted_cert_b64).public_bytes( Encoding.DER ) == trusted_cert.public_bytes(Encoding.DER)
def x509_certificate_to_json(certificate: x509.Certificate) -> Dict[str, Any]: public_key = certificate.public_key() try: public_key_size = public_key.key_size # type: ignore except AttributeError: public_key_size = None public_key_json = _PublicKeyAsJson( algorithm=public_key.__class__.__name__, key_size=public_key_size, # EC-only fields ec_curve_name=public_key.curve.name if isinstance(public_key, EllipticCurvePublicKey) else None, ec_x=public_key.public_numbers().x if isinstance(public_key, EllipticCurvePublicKey) else None, ec_y=public_key.public_numbers().y if isinstance(public_key, EllipticCurvePublicKey) else None, # RSA-only fields rsa_e=public_key.public_numbers().e if isinstance(public_key, RSAPublicKey) else None, rsa_n=public_key.public_numbers().n if isinstance(public_key, RSAPublicKey) else None, ) signature_hash_algorithm: Optional[_HashAlgorithmAsJson] if certificate.signature_hash_algorithm: signature_hash_algorithm = _HashAlgorithmAsJson( name=certificate.signature_hash_algorithm.name, digest_size=certificate.signature_hash_algorithm.digest_size, ) else: signature_hash_algorithm = None # We may get garbage/invalid certificates so we need to handle ValueErrors. # See https://github.com/nabla-c0d3/sslyze/issues/403 for more information subject_field: Optional[x509.name.Name] try: subject_field = certificate.subject except ValueError: subject_field = None issuer_field: Optional[x509.name.Name] try: issuer_field = certificate.issuer except ValueError: issuer_field = None cert_as_json = _X509CertificateAsJson( as_pem=certificate.public_bytes(Encoding.PEM).decode("ascii"), hpkp_pin=b64encode(get_public_key_sha256(certificate)).decode("ascii"), fingerprint_sha1=b64encode(certificate.fingerprint(hashes.SHA1())).decode("ascii"), fingerprint_sha256=b64encode(certificate.fingerprint(hashes.SHA256())).decode("ascii"), serial_number=certificate.serial_number, not_valid_before=certificate.not_valid_before, not_valid_after=certificate.not_valid_after, subject_alternative_name=_SubjAltNameAsJson(dns=extract_dns_subject_alternative_names(certificate)), signature_hash_algorithm=signature_hash_algorithm, signature_algorithm_oid=certificate.signature_algorithm_oid, subject=subject_field, issuer=issuer_field, public_key=public_key_json, ) return asdict(cert_as_json)
def _write_tls_certificate(self, certificate: Certificate, host: str = None, force: bool = True) -> str: # Read x509 = OpenSSL.crypto.X509.from_cryptography(certificate) subject_components = x509.get_subject().get_components() common_name_as_bytes = subject_components[0][1] common_name_on_certificate = common_name_as_bytes.decode() if not host: host = common_name_on_certificate try: pseudonym = certificate.subject.get_attributes_for_oid( NameOID.PSEUDONYM)[0] except IndexError: raise self.InvalidNodeCertificate( f"Missing checksum address on certificate for host '{host}'. " f"Does this certificate belong to an Ursula?") else: checksum_address = pseudonym.value if not is_checksum_address(checksum_address): raise self.InvalidNodeCertificate( "Invalid certificate wallet address encountered: {}".format( checksum_address)) # Validate # TODO: It's better for us to have checked this a while ago so that this situation is impossible. #443 if host and (host != common_name_on_certificate): raise ValueError( f"You passed a hostname ('{host}') that does not match the certificate's common name." ) certificate_filepath = self.generate_certificate_filepath( checksum_address=checksum_address) certificate_already_exists = os.path.isfile(certificate_filepath) if force is False and certificate_already_exists: raise FileExistsError( 'A TLS certificate already exists at {}.'.format( certificate_filepath)) # Write os.makedirs(os.path.dirname(certificate_filepath), exist_ok=True) with open(certificate_filepath, 'wb') as certificate_file: public_pem_bytes = certificate.public_bytes( self.TLS_CERTIFICATE_ENCODING) certificate_file.write(public_pem_bytes) nickname, pairs = nickname_from_seed(checksum_address) self.log.debug( f"Saved TLS certificate for {nickname} {checksum_address}: {certificate_filepath}" ) return certificate_filepath
def to_pem(certificate: x509.Certificate) -> str: """Convert an instance of x509.Certificate to a PEM string Args: certificate (x509.Certificate): Cert to convert Returns: PEM string """ serialized = certificate.public_bytes(encoding=serialization.Encoding.PEM) return serialized
def _write_tls_certificate(certificate: Certificate, full_filepath: str, force: bool = False, ) -> str: cert_already_exists = os.path.isfile(full_filepath) if force is False and cert_already_exists: raise FileExistsError('A TLS certificate already exists at {}.'.format(full_filepath)) with open(full_filepath, 'wb') as certificate_file: public_pem_bytes = certificate.public_bytes(TLS_CERTIFICATE_ENCODING) certificate_file.write(public_pem_bytes) return full_filepath
def convert_cert_pem(cert: Certificate, include_info: bool = True) -> str: pem_return = None if cert: if include_info: pem_return = "################################################################\n" pem_return += f"Subject: {X509Utils.cert_get_subject(cert)}\n" pem_return += f"Issuer: {X509Utils.cert_get_issuer(cert)}\n" pem_return += f"Valid From: {X509Utils.cert_get_valid_from(cert)} GMT\n" pem_return += f"Valid To: {X509Utils.cert_get_valid_to(cert)} GMT\n" pem_return += cert.public_bytes( encoding=serialization.Encoding.PEM).decode("ascii") return pem_return
def certificate_to_context( certificate: x509.Certificate) -> Common.Certificate: """ certificate_to_context function Translates an X509 certificate into a Common.Certificate object :type certificate: ``x509.Certificate`` :param oid: Certificate Extension OID :return: Certificate represented as a Common.Certificate object :rtype: ``Common.Certificate`` """ spkisha256 = hashes.Hash(hashes.SHA256(), backends.default_backend()) spkisha256.update(certificate.public_key().public_bytes( encoding=serialization.Encoding.DER, format=serialization.PublicFormat.SubjectPublicKeyInfo)) extensions_contexts: List[Common.CertificateExtension] = [] for extension in certificate.extensions: extension_oid = cast(oid.ObjectIdentifier, extension.oid) extensions_contexts.append( extension_context(oid=extension_oid.dotted_string, extension_name=extension_oid._name, critical=extension.critical, extension_value=extension.value)) indicator = certificate.fingerprint(hashes.SHA256()).hex() cert = Common.Certificate( subject_dn=certificate.subject.rfc4514_string(), issuer_dn=certificate.issuer.rfc4514_string(), serial_number=str(certificate.serial_number), validity_not_before=certificate.not_valid_before.strftime( "%Y-%m-%dT%H:%M:%S.000Z"), validity_not_after=certificate.not_valid_after.strftime( "%Y-%m-%dT%H:%M:%S.000Z"), sha256=certificate.fingerprint(hashes.SHA256()).hex(), sha1=certificate.fingerprint(hashes.SHA1()).hex(), md5=certificate.fingerprint(hashes.MD5()).hex(), spki_sha256=spkisha256.finalize().hex(), extensions=extensions_contexts, signature_algorithm=certificate.signature_hash_algorithm. name, # type: ignore[union-attr] signature=certificate.signature.hex(), publickey=public_key_context(certificate.public_key()), # type: ignore dbot_score=Common.DBotScore(indicator=indicator, indicator_type=DBotScoreType.CERTIFICATE, integration_name="X509Certificate", score=Common.DBotScore.NONE), pem=certificate.public_bytes( serialization.Encoding.PEM).decode('ascii')) return cert
def store_certificate(self, certificate: Certificate) -> Path: """Store the supplied certificate as a PEM file. """ # A given certificate's path is always <SHA-256>.pem. cert_file_name = hexlify(certificate.fingerprint(SHA256())).decode('ascii') cert_path = self._path / f'{cert_file_name}.pem' # If the cert is NOT already there, add it if not cert_path.exists(): with open(cert_path, 'w') as cert_file: cert_file.write(certificate.public_bytes(Encoding.PEM).decode('ascii')) return cert_path
def _write_private_key_and_cert( self, key: ec.EllipticCurvePrivateKey, cert: x509.Certificate, disk_folder: str ) -> None: cert_file = os.path.join(disk_folder, self.private_cert_file_name) with open(cert_file, "w+") as file: file.write( key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.TraditionalOpenSSL, serialization.NoEncryption(), ).decode("UTF-8") ) file.write(cert.public_bytes(serialization.Encoding.PEM).decode("UTF-8"))
def x509_certificate_to_json(certificate: x509.Certificate) -> Dict[str, Any]: result: Dict[str, Union[None, str, Dict[str, Any]]] = { # Add general info "as_pem": certificate.public_bytes(Encoding.PEM).decode("ascii"), "hpkp_pin": b64encode( get_public_key_sha256(certificate)).decode("utf-8"), # RFC 7469 # Add some of the fields of the cert "serialNumber": str(certificate.serial_number), "notBefore": certificate.not_valid_before.isoformat(), "notAfter": certificate.not_valid_after.isoformat(), "subjectAlternativeName": { "DNS": extract_dns_subject_alternative_names(certificate) }, } if certificate.signature_hash_algorithm: # The signature_hash_algorithm can be None if signature did not use separate hash (ED25519, ED448) # https://cryptography.io/en/latest/x509/reference/#cryptography.x509.Certificate.signature_hash_algorithm result[ "signatureAlgorithm"] = certificate.signature_hash_algorithm.name else: result["signatureAlgorithm"] = None # We may get garbage/invalid certificates so we need to handle ValueErrors. # See https://github.com/nabla-c0d3/sslyze/issues/403 for more information for name_field in ["subject", "issuer"]: try: result[name_field] = getattr(certificate, name_field) except ValueError as e: x509name_as_json = _X509NameAsJson(rfc4514_string=None, attributes=None, parsing_error=e.args[0]) result[name_field] = asdict(x509name_as_json) # Add some info about the public key public_key = certificate.public_key() public_key_dict: Dict[str, Union[str, int]] = { "algorithm": public_key.__class__.__name__ } if isinstance(public_key, EllipticCurvePublicKey): public_key_dict["size"] = public_key.curve.key_size public_key_dict["curve"] = public_key.curve.name elif isinstance(public_key, RSAPublicKey): public_key_dict["size"] = public_key.key_size public_key_dict["exponent"] = public_key.public_numbers().e else: # DSA Key? https://github.com/nabla-c0d3/sslyze/issues/402 pass result["publicKey"] = public_key_dict return result
def to_der(certificate: x509.Certificate) -> bytes: """Convert an instance of x509.Certificate to DER bytes Args: certificate (x509.Certificate): Cert to convert Returns: DER bytes """ serialized = certificate.public_bytes( encoding=serialization.Encoding.DER, format=serialization.PublicFormat.PKCS8, encryption_algorithm=serialization.NoEncryption()) return serialized
def cert_as_string(self, cert: Certificate = None) -> str: if not cert: cert = self.signed_cert cert_info = ( f'# Issuer {cert.issuer}\n' f'# Subject {cert.subject}\n' f'# Valid from {cert.not_valid_before} to {cert.not_valid_after}\n' ) data = cert_info data += cert.public_bytes(serialization.Encoding.PEM).decode('utf-8') data += '\n' return data
def _save_tls_certificate( certificate: Certificate, full_filepath: str, force: bool = True, # TODO: Make configurable, or set to False by default. ) -> str: if force is False and os.path.isfile(full_filepath): raise FileExistsError( 'A TLS certificate already exists at {}.'.format(full_filepath)) with open(full_filepath, 'wb') as certificate_file: public_pem_bytes = certificate.public_bytes(Encoding.PEM) certificate_file.write(public_pem_bytes) return full_filepath
def from_crypto_type(cls, certificate: x509.Certificate, certtype: CertificateType): # type: (certtype, x509.Certificate, CertificateType) -> Certificate m = cls() m.pem_data = certificate.public_bytes(serialization.Encoding.PEM) m.not_after = certificate.not_valid_after m.not_before = certificate.not_valid_before m.fingerprint = certificate.fingerprint(hashes.SHA256()) m.discriminator = certtype.value subject: x509.Name = certificate.subject cns = subject.get_attributes_for_oid(NameOID.COMMON_NAME) if cns is not None: m.x509_cn = cns[0].value return m
async def write_certs(key: rsa.RSAPrivateKey, cert: x509.Certificate, name: str): assert len(name) > 0 with open(f"{name:s}.key", "wb") as f: f.write( key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), # ? )) with open(f"{name:s}.crt", "wb") as f: f.write(cert.public_bytes(encoding=serialization.Encoding.PEM, ))
def from_crypto(cls, certificate: x509.Certificate): # TODO: sometimes serial numbers are too large even for SQLite BIGINT m = cls() m.pem_data = certificate.public_bytes( encoding=serialization.Encoding.PEM) m.not_after = certificate.not_valid_after m.not_before = certificate.not_valid_before m.fingerprint = certificate.fingerprint(hashes.SHA256()) subject: x509.Name = certificate.subject cns = subject.get_attributes_for_oid(NameOID.COMMON_NAME) if cns is not None: m.x509_cn = cns[0].value return m
def sign( *, element: Element, private_key: RSAPrivateKey, certificate: Certificate, config: SigningConfig = SigningConfig.default(), index: int = 0, ) -> bytes: try: element_id = element.attrib["ID"] except KeyError: raise NoIDAttribute(element) # Generate the digest value of the element/content to be signed content_digest_value = utils.ascii_b64( utils.hash_digest(config.digest_method, utils.serialize_xml(element))) # Build the SignedInfo tag, referencing the element we got passed, # including the digest value we just created. signed_info = ds.SignedInfo( ds.CanonicalizationMethod(Algorithm=XML_EXC_C14N), ds.SignatureMethod(Algorithm=utils.signature_method_algorithm( config.signature_method)), ds.Reference( ds.Transforms( ds.Transform(Algorithm=XMLDSIG_ENVELOPED_SIGNATURE), ds.Transform(Algorithm=XML_EXC_C14N), ), ds.DigestMethod( Algorithm=utils.digest_method_algorithm(config.digest_method)), ds.DigestValue(content_digest_value), # Embed the digest value URI="#" + element_id, # Reference the element to sign ), ) # Sign the digest of the SignedInfo element signature = utils.sign(utils.serialize_xml(signed_info), private_key, config.signature_method) signature_value = utils.ascii_b64(signature) # Encode the certificate to embed into the signature. cert_data = utils.ascii_b64(certificate.public_bytes(Encoding.DER)) signature_element = ds.Signature( signed_info, ds.SignatureValue(signature_value), ds.KeyInfo(ds.X509Data(ds.X509Certificate(cert_data))), ) element.insert(index, signature_element) root = utils.get_root(element) result = utils.serialize_xml(root) element.remove(signature_element) return result
def _write_tls_certificate(self, certificate: Certificate, host: str = None, force: bool = True) -> str: # Read x509 = OpenSSL.crypto.X509.from_cryptography(certificate) subject_components = x509.get_subject().get_components() common_name_as_bytes = subject_components[0][1] common_name_on_certificate = common_name_as_bytes.decode() if not host: host = common_name_on_certificate pseudonym = certificate.subject.get_attributes_for_oid( NameOID.PSEUDONYM)[0] checksum_address = pseudonym.value if not is_checksum_address(checksum_address): # TODO: more? raise RuntimeError( "Invalid certificate checksum address encountered: {}".format( checksum_address)) # Validate # TODO: It's better for us to have checked this a while ago so that this situation is impossible. #443 if host and (host != common_name_on_certificate): raise ValueError( 'You passed a hostname ("{}") that does not match the certificat\'s common name.' .format(host)) certificate_filepath = self.generate_certificate_filepath( checksum_address=checksum_address) certificate_already_exists = os.path.isfile(certificate_filepath) if force is False and certificate_already_exists: raise FileExistsError( 'A TLS certificate already exists at {}.'.format( certificate_filepath)) # Write with open(certificate_filepath, 'wb') as certificate_file: public_pem_bytes = certificate.public_bytes( self.TLS_CERTIFICATE_ENCODING) certificate_file.write(public_pem_bytes) self.certificate_filepath = certificate_filepath self.log.info("Saved TLS certificate for {}: {}".format( self, certificate_filepath)) return certificate_filepath
def serialize_certificate(certificate: Certificate, encoding: serialization.Encoding) -> bytes: """Serializes an X.509 certificate using the specified encoding. Args: certificate: Certificate object to be serialized to bytes. encoding: The serialization format to use to save the certificate. Raises: X509CertificateError: In case it cannot get the bytes from the certificate object. """ try: cert_bytes = certificate.public_bytes(encoding) except Exception as err: raise X509CertificateError( 'Could not get bytes from object: {}'.format(str(err))) return cert_bytes
def from_crypto(cls, certificate: x509.Certificate): m = cls() m.pem_data = certificate.public_bytes( encoding=serialization.Encoding.PEM) m.not_after = certificate.not_valid_after m.not_before = certificate.not_valid_before m.fingerprint = certificate.fingerprint(hashes.SHA1()) subject: x509.Name = certificate.subject m.x509_cn = subject.get_attributes_for_oid( NameOID.COMMON_NAME)[0].value # m.x509_c = subject.get_attributes_for_oid(NameOID.COUNTRY_NAME) # m.x509_o = subject.get_attributes_for_oid(NameOID.ORGANIZATION_NAME) # m.x509_ou = subject.get_attributes_for_oid(NameOID.ORGANIZATIONAL_UNIT_NAME) # m.x509_st = subject.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME) return m
def from_orm(cls, certificate: x509.Certificate) -> "_CertificateAsJson": signature_hash_algorithm: Optional[_HashAlgorithmAsJson] if certificate.signature_hash_algorithm: signature_hash_algorithm = _HashAlgorithmAsJson.from_orm( certificate.signature_hash_algorithm) else: signature_hash_algorithm = None # We may get garbage/invalid certificates so we need to handle ValueErrors. # See https://github.com/nabla-c0d3/sslyze/issues/403 for more information subject_field: Optional[_X509NameAsJson] try: subject_field = _X509NameAsJson.from_orm(certificate.subject) except ValueError: subject_field = None issuer_field: Optional[_X509NameAsJson] try: issuer_field = _X509NameAsJson.from_orm(certificate.issuer) except ValueError: issuer_field = None return cls( as_pem=certificate.public_bytes(Encoding.PEM).decode("ascii"), hpkp_pin=b64encode( get_public_key_sha256(certificate)).decode("ascii"), fingerprint_sha1=b64encode(certificate.fingerprint( hashes.SHA1())).decode("ascii"), fingerprint_sha256=b64encode( certificate.fingerprint(hashes.SHA256())).decode("ascii"), serial_number=certificate.serial_number, not_valid_before=certificate.not_valid_before, not_valid_after=certificate.not_valid_after, subject_alternative_name=_SubjAltNameAsJson( dns=extract_dns_subject_alternative_names(certificate)), signature_hash_algorithm=signature_hash_algorithm, signature_algorithm_oid=certificate.signature_algorithm_oid, subject=subject_field, issuer=issuer_field, public_key=_PublicKeyAsJson.from_orm(certificate.public_key()), )
def storePublicKey(self, certName: str, cert: x509.Certificate) -> None: path = self.conf.getCertPath(certName=certName, ext="signed_certificate") certConf = self.conf.getCert(certName=certName) format = certConf.get("public_key").get("format", None) try: if type(format) == str and format.lower() == "openssh": content = serialization.ssh.serialize_ssh_public_key( cert.public_key()) with open(path, "wb") as f: f.write(content) # DER or PEM encodings else: encoding, _ = self._getParamsForPublicBytes(certConf=certConf) content = cert.public_bytes(encoding) with open(path, "wb") as f: f.write(content) except OSError: logging.error(f"can't save public key in {path}") sys.exit()
def _build_recipient_info(self, symmetric_key: bytes, recipient: x509.Certificate) -> RecipientInfo: """Build an ASN.1 data structure containing the encrypted symmetric key for the encrypted_content. NOTE: The recipient is always identified by issuerAndSerialNumber NOTE: Args: symmetric_key (bytes): Typically the randomly generated 3DES key for the encrypted_content. recipient (x509.Certificate): The certificate which will be used to encrypt the symmetric key. Returns: RecipientInfo: Instance of ASN.1 data structure with required attributes and encrypted key. """ encrypted_symkey = recipient.public_key().encrypt( symmetric_key, asympad.PKCS1v15()) asn1cert = parse_certificate( recipient.public_bytes(serialization.Encoding.DER)) ias = IssuerAndSerialNumber({ 'issuer': asn1cert.issuer, 'serial_number': asn1cert.serial_number }) ri = RecipientInfo( 'ktri', KeyTransRecipientInfo({ 'version': 0, 'rid': RecipientIdentifier('issuer_and_serial_number', ias), 'key_encryption_algorithm': KeyEncryptionAlgorithm( {'algorithm': KeyEncryptionAlgorithmId('rsa')}), 'encrypted_key': encrypted_symkey, })) return ri
def submit_mdmcert_request(email: str, csr: x509.CertificateSigningRequest, encrypt_with: x509.Certificate, api_key: str = MDMCERT_API_KEY) -> Dict: """Submit a CSR signing request to mdmcert.download. Args: email (str): Your registered mdmcert.download e-mail address. api_key (str): Your registered mdmcert.download API key. csr (cryptography.x509.CertificateSigningRequest): The MDM CSR to sign. encrypt_with (cryptography.x509.Certificate): The certificate which will be used to encrypt the response. Returns: dict: Response from the mdmcert.download service. """ base64_csr = b64encode(csr.public_bytes(serialization.Encoding.PEM)) base64_recipient = b64encode( encrypt_with.public_bytes(serialization.Encoding.PEM)) mdmcert_dict = { 'csr': base64_csr.decode('utf8'), 'email': email, 'key': api_key, 'encrypt': base64_recipient.decode('utf8'), } req = urllib.request.Request(MDMCERT_REQ_URL, json.dumps(mdmcert_dict).encode('utf8'), { 'Content-Type': 'application/json', 'User-Agent': 'coMmanDMent/0.1' }) f = urllib.request.urlopen(req) resp = f.read() f.close() return json.loads(resp)
def fixture_untrusted_cert_b64(untrusted_cert: Certificate) -> str: return urlsafe_b64encode(untrusted_cert.public_bytes( Encoding.DER)).decode()