def encode_cert_id_key(self, hkey): issuer_name_hash, issuer_key_hash, serial_number = hkey issuer_name_hash = OctetString.load(issuer_name_hash) issuer_key_hash = OctetString.load(issuer_key_hash) serial_number = Integer.load(serial_number) cert_id = CertId({ 'hash_algorithm': DigestAlgorithm({ 'algorithm': u'sha1', 'parameters': None }), 'issuer_name_hash': issuer_name_hash, 'issuer_key_hash': issuer_key_hash, 'serial_number': serial_number, }) return cert_id
def create_ocsp_request(self, issuer, subject): """Creates CertId and OCSPRequest.""" cert_id = CertId({ 'hash_algorithm': DigestAlgorithm({ 'algorithm': 'sha1', 'parameters': None}), 'issuer_name_hash': OctetString(subject.issuer.sha1), 'issuer_key_hash': OctetString(issuer.public_key.sha1), 'serial_number': subject.serial_number, }) ocsp_request = OCSPRequest({ 'tbs_request': TBSRequest({ 'version': Version(0), 'request_list': Requests([ Request({ 'req_cert': cert_id, })]), }), }) return cert_id, ocsp_request
def __init__(self, certificate: x509.Certificate, private_key: rsa.RSAPrivateKeyWithSerialization, digest_algorithm: str, signed_attributes: List[CMSAttribute] = None): self.certificate = certificate self.private_key = private_key self.digest_algorithm_id = { 'sha1': DigestAlgorithmId('sha1'), 'sha256': DigestAlgorithmId('sha256'), 'sha512': DigestAlgorithmId('sha512'), }[digest_algorithm] self.digest_algorithm = DigestAlgorithm({'algorithm': self.digest_algorithm_id}) if signed_attributes is not None: self.signed_attributes = signed_attributes else: self.signed_attributes = []
vals.append(vals[0]) else: vals = signed_attrs[ix]['values'] vals[0] = replace_with # ... and replace the signature if requested if resign: si['signature'] = \ signer.sign_raw(si['signed_attrs'].untag().dump(), md_algorithm) cms_writer.send(cms_obj) return output @pytest.mark.parametrize('replacement_value', [ cms.CMSAlgorithmProtection({ 'digest_algorithm': DigestAlgorithm({'algorithm': 'sha1'}), 'signature_algorithm': SignedDigestAlgorithm( {'algorithm': 'rsassa_pkcs1v15'} ) }), cms.CMSAlgorithmProtection({ 'digest_algorithm': DigestAlgorithm({'algorithm': 'sha256'}), 'signature_algorithm': SignedDigestAlgorithm( {'algorithm': 'sha512_rsa'} ) }), cms.CMSAlgorithmProtection({ 'digest_algorithm': DigestAlgorithm({'algorithm': 'sha256'}), }), None ])
def finalize(self) -> ContentInfo: """Build all data structures from the given parameters and return the top level contentInfo. Returns: ContentInfo: The PKIMessage """ pkcs_pki_envelope = self._pki_envelope pkienvelope_content_info = ContentInfo({ 'content_type': ContentType('enveloped_data'), 'content': pkcs_pki_envelope, }) # NOTE: This might not be needed for the degenerate CertRep encap_info = ContentInfo({ 'content_type': ContentType('data'), 'content': pkienvelope_content_info.dump() }) # encap_info_degen = ContentInfo({ # 'content_type': ContentType('data'), # 'content': pkcs_pki_envelope.dump() # }) # Calculate digest on encrypted content + signed_attrs #digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) digest = hashes.Hash(hashes.SHA512(), backend=default_backend()) #digest = hashes.Hash(hashes.SHA1(), backend=default_backend()) # digest.update(pkcs_pki_envelope.dump()) digest.update(pkienvelope_content_info.dump()) d = digest.finalize() # Now start building SignedData # signer_infos = self._build_signerinfos(pkcs_pki_envelope.dump(), d, self._cms_attributes) signer_infos = self._build_signerinfos(pkienvelope_content_info.dump(), d, self._cms_attributes) certificates = self._certificates #da_id = DigestAlgorithmId('sha256') # SHA-1 works for macOS # da_id = DigestAlgorithmId('sha1') da_id = DigestAlgorithmId('sha512') da = DigestAlgorithm({'algorithm': da_id}) das = DigestAlgorithms([da]) sd = SignedData({ 'version': 1, 'certificates': certificates, 'signer_infos': signer_infos, 'digest_algorithms': das, 'encap_content_info': encap_info, # should point to type data + content contentinfo }) ci = ContentInfo({ 'content_type': ContentType('signed_data'), 'content': sd, }) return ci
def sign(self): h = hashes.Hash(hashes.SHA256(), backend=default_backend()) h.update(self._content_mime.as_bytes()) message_digest = h.finalize() cs = CertificateSet() cs.append(load(self._certificate.public_bytes(Encoding.DER))) for ca_cert in self._ca: cs.append(load(ca_cert.public_bytes(Encoding.DER))) ec = ContentInfo({ 'content_type': ContentType('data'), }) sident = SignerIdentifier({ 'issuer_and_serial_number': IssuerAndSerialNumber({ 'issuer': load(self._issuer_name.public_bytes(default_backend())), 'serial_number': self._cert_serial, }) }) certv2 = ESSCertIDv2({ 'hash_algorithm': DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), 'cert_hash': OctetString(self._certificate.fingerprint(hashes.SHA256())), 'issuer_serial': IssuerSerial({ 'issuer': load(self._issuer_name.public_bytes(default_backend())), 'serial_number': self._cert_serial, }), }) now = datetime.now().replace(microsecond=0, tzinfo=pytz.utc) # .isoformat() sattrs = CMSAttributes({ CMSAttribute({ 'type': CMSAttributeType('content_type'), 'values': ["data"] }), CMSAttribute({ 'type': CMSAttributeType('message_digest'), 'values': [message_digest] }), CMSAttribute({ 'type': CMSAttributeType('signing_time'), 'values': (Time({'utc_time': UTCTime(now)}), ) }), CMSAttribute({ 'type': CMSAttributeType('signing_certificate_v2'), 'values': [SigningCertificateV2({'certs': (certv2, )})] }) }) signature = self._private_key.sign(sattrs.dump(), padding.PKCS1v15(), hashes.SHA256()) # si = SignerInfo({ 'version': 'v1', 'sid': sident, 'digest_algorithm': DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), 'signed_attrs': sattrs, 'signature_algorithm': SignedDigestAlgorithm( {'algorithm': SignedDigestAlgorithmId('rsassa_pkcs1v15')}), 'signature': signature, }) da = DigestAlgorithms( (DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), )) signed_data = SignedData({ 'version': 'v1', 'encap_content_info': ec, 'certificates': cs, 'digest_algorithms': da, 'signer_infos': SignerInfos((si, )) }) ci = ContentInfo({ 'content_type': ContentType('signed_data'), 'content': signed_data }) self._signature_mime = MIMEApplication(ci.dump(), _subtype="pkcs7-signature", name="smime.p7s", policy=email.policy.SMTPUTF8) self._signature_mime.add_header('Content-Disposition', 'attachment; filename=smime.p7s') super(CADESMIMESignature, self).attach(self._content_mime) super(CADESMIMESignature, self).attach(self._signature_mime)
def sign(self): h = hashes.Hash(hashes.SHA256(), backend=default_backend()) h.update(self._content_mime.as_bytes()) message_digest = h.finalize() cs = CertificateSet() cs.append(load(self._certificate.public_bytes(Encoding.DER))) for ca_cert in self._ca: cs.append(load(ca_cert.public_bytes(Encoding.DER))) ec = EncapsulatedContentInfo({ 'content_type': ContentType('data'), 'content': ParsableOctetString(self._content_mime.as_bytes()) }) sident = SignerIdentifier({ 'issuer_and_serial_number': IssuerAndSerialNumber({ 'issuer': load(self._issuer_name.public_bytes(default_backend())), 'serial_number': self._cert_serial, }) }) certv2 = ESSCertIDv2({ 'hash_algorithm': DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), 'cert_hash': OctetString(self._certificate.fingerprint(hashes.SHA256())), 'issuer_serial': IssuerSerial({ 'issuer': load( self._issuer_name.public_bytes(default_backend()) ), #[GeneralName({'directory_name': self._issuer_name.public_bytes(default_backend())})], 'serial_number': self._cert_serial, }), }) now = datetime.now().replace(microsecond=0, tzinfo=pytz.utc) sattrs = CMSAttributes({ CMSAttribute({ 'type': CMSAttributeType('content_type'), 'values': ["data"] }), CMSAttribute({ 'type': CMSAttributeType('message_digest'), 'values': [message_digest] }), CMSAttribute({ 'type': CMSAttributeType('signing_time'), 'values': (Time({'utc_time': UTCTime(now)}), ) }), # isti k v CMSAttribute({ 'type': CMSAttributeType('signing_certificate_v2'), 'values': [SigningCertificateV2({'certs': (certv2, )})] }) }) signature = self._private_key.sign(sattrs.dump(), padding.PKCS1v15(), hashes.SHA256()) si = SignerInfo({ 'version': 'v1', 'sid': sident, 'digest_algorithm': DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), 'signed_attrs': sattrs, 'signature_algorithm': SignedDigestAlgorithm( {'algorithm': SignedDigestAlgorithmId('rsassa_pkcs1v15')}), 'signature': signature, }) da = DigestAlgorithms( (DigestAlgorithm({'algorithm': DigestAlgorithmId('sha256')}), )) signed_data = SignedData({ 'version': 'v3', 'encap_content_info': ec, 'certificates': cs, 'digest_algorithms': da, 'signer_infos': SignerInfos((si, )) }) ci = ContentInfo({ 'content_type': ContentType('signed_data'), 'content': signed_data }) self.set_payload(ci.dump()) encode_base64(self)
else: vals = signed_attrs[ix]['values'] vals[0] = replace_with # ... and replace the signature if requested if resign: si['signature'] = \ signer.sign_raw(si['signed_attrs'].untag().dump(), md_algorithm) cms_writer.send(cms_obj) return output @pytest.mark.parametrize('replacement_value', [ cms.CMSAlgorithmProtection({ 'digest_algorithm': DigestAlgorithm({'algorithm': 'sha1'}), 'signature_algorithm': SignedDigestAlgorithm({'algorithm': 'rsassa_pkcs1v15'}) }), cms.CMSAlgorithmProtection({ 'digest_algorithm': DigestAlgorithm({'algorithm': 'sha256'}), 'signature_algorithm': SignedDigestAlgorithm({'algorithm': 'sha512_rsa'}) }), cms.CMSAlgorithmProtection({ 'digest_algorithm': DigestAlgorithm({'algorithm': 'sha256'}), }), None ]) def test_cms_algorithm_protection(replacement_value):