Пример #1
0
 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
Пример #2
0
    def deriveDigest(self, chain):
        chain_params = self.getChainParams(chain)
        # Chain ID
        self.chainid = chain_params["chain_id"]

        # Do not serialize signatures
        sigs = self.data["signatures"]
        self.data["signatures"] = []

        # Get message to sign
        #   bytes(self) will give the wire formated data according to
        #   GrapheneObject and the data given in __init__()
        self.message = OctetString(unhexlify(self.chainid)).dump()
        for name, value in list(self.data.items()):
            if name == "operations":
                for operation in value:
                    if isinstance(value, string_types):
                        b = py23_bytes(operation, 'utf-8')
                    else:
                        b = py23_bytes(operation)
                    self.message += OctetString(b).dump()
            elif name != "signatures":
                if isinstance(value, string_types):
                    b = py23_bytes(value, 'utf-8')
                else:
                    b = py23_bytes(value)
                self.message += OctetString(b).dump()

        self.digest = hashlib.sha256(self.message).digest()

        # restore signatures
        self.data["signatures"] = sigs
def _create_ocsp_request(issuer, subject):
    """
    Create CertId and OCSPRequest
    """
    cert_id = CertId({
        'hash_algorithm':
        DigestAlgorithm({
            'algorithm': u'sha1',
            'parameters': None
        }),
        'issuer_name_hash':
        OctetString(subject.issuer.sha1),
        'issuer_key_hash':
        OctetString(issuer.public_key.sha1),
        'serial_number':
        subject.serial_number,
    })
    req = OCSPRequest({
        'tbs_request':
        TBSRequest({
            'version':
            Version(0),
            'request_list':
            Requests([Request({
                'req_cert': cert_id,
            })]),
        }),
    })
    return cert_id, req
 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': 'sha1',
             'parameters': None}),
         'issuer_name_hash': issuer_name_hash,
         'issuer_key_hash': issuer_key_hash,
         'serial_number': serial_number,
     })
     return cert_id
Пример #5
0
 def generate_private_key(self):
     parameters = self.session.create_domain_parameters(
         KeyType.EC,
         {Attribute.EC_PARAMS: encode_named_curve_parameters('secp256r1')},
         local=True)
     public_template = {
         Attribute.KEY_TYPE: KeyType.EC,
         Attribute.CLASS: ObjectClass.PUBLIC_KEY,
         Attribute.TOKEN: True,
         Attribute.VERIFY: True,
     }
     private_template = {
         Attribute.KEY_TYPE: KeyType.EC,
         Attribute.CLASS: ObjectClass.PRIVATE_KEY,
         Attribute.TOKEN: True,
         Attribute.PRIVATE: True,
         Attribute.SIGN: True,
         Attribute.EXTRACTABLE: False,
         Attribute.SENSITIVE: True
     }
     public_key, private_key = parameters.generate_keypair(
         store=True,
         public_template=public_template,
         private_template=private_template)
     ecpt = bytes(OctetString.load(public_key[Attribute.EC_POINT]))
     hash = hashlib.sha256(ecpt)
     ski = hash.digest()
     hexski = hash.hexdigest()
     public_key[Attribute.ID] = ski
     public_key[Attribute.LABEL] = hexski
     private_key[Attribute.ID] = ski
     private_key[Attribute.LABEL] = hexski
     return PKCS11KeyPair(public_key, private_key)
Пример #6
0
def decode_ec_public_key(der, encode_ec_point=True):
    """
    Decode a DER-encoded EC public key as stored by OpenSSL into a dictionary
    of attributes able to be passed to :meth:`pkcs11.Session.create_object`.

    .. note:: **encode_ec_point**

        For use as an attribute `EC_POINT` should be DER-encoded (True).

        For key derivation implementations can vary.  Since v2.30 the
        specification says implementations MUST accept a raw `EC_POINT` for
        ECDH (False), however not all implementations follow this yet.

    :param bytes der: DER-encoded key
    :param encode_ec_point: See text.
    :rtype: dict(Attribute,*)
    """
    asn1 = PublicKeyInfo.load(der)

    assert asn1.algorithm == 'ec', \
        "Wrong algorithm, not an EC key!"

    ecpoint = bytes(asn1['public_key'])

    if encode_ec_point:
        ecpoint = OctetString(ecpoint).dump()

    return {
        Attribute.KEY_TYPE: KeyType.EC,
        Attribute.CLASS: ObjectClass.PUBLIC_KEY,
        Attribute.EC_PARAMS: asn1['algorithm']['parameters'].dump(),
        Attribute.EC_POINT: ecpoint,
    }
Пример #7
0
def make_signed_attrs(digest: bytes, hash_type: int) -> CMSAttributes:
    content_type = CMSAttribute({
        "type": CMSAttributeType.unmap("content_type"),
        "values": [ContentType.unmap("data")],
    })

    time_now = UTCTime()
    time_now.set(datetime.now(timezone.utc))
    signing_time = CMSAttribute({
        "type": CMSAttributeType.unmap("signing_time"),
        "values": [time_now]
    })

    message_digest = CMSAttribute({
        "type":
        CMSAttributeType.unmap("message_digest"),
        "values": [OctetString(digest)],
    })

    ha_v1 = make_hash_agility_v1(digest)

    ha_v2 = make_hash_agility_v2(digest, hash_type)

    return CMSAttributes(
        [content_type, signing_time, message_digest, ha_v1, ha_v2])
Пример #8
0
    def finalize(self) -> Tuple[EnvelopedData, Union[TripleDES, AES], bytes]:
        """Encrypt the data and process the key using all available recipients.
        
        Returns:
              EnvelopedData, TripleDES, iv (bytes): The PKCSPKIEnvelope structure, The symmetric key, and the IV for
              the symmetric key.
        """
        sym_key, iv, ciphertext = self._encrypt_data(self._data)

        eci = EncryptedContentInfo({
            'content_type':
            ContentType('data'),
            'content_encryption_algorithm':
            EncryptionAlgorithm({
                'algorithm': self._encryption_algorithm_id,
                'parameters': OctetString(iv),
            }),
            'encrypted_content':
            ciphertext,
        })

        recipients = [
            self._build_recipient_info(sym_key.key, recipient)
            for recipient in self._recipients
        ]
        recipient_infos = RecipientInfos(recipients)

        ed = EnvelopedData({
            'version': 1,
            'recipient_infos': recipient_infos,
            'encrypted_content_info': eci,
        })

        return ed, sym_key, iv
Пример #9
0
 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": "sha1",
             "parameters": None
         }),
         "issuer_name_hash":
         issuer_name_hash,
         "issuer_key_hash":
         issuer_key_hash,
         "serial_number":
         serial_number,
     })
     return cert_id
Пример #10
0
 def __bytes__(self):
     if self.data is None:
         return py23_bytes()
     b = b""
     output = b""
     for name, value in list(self.data.items()):
         if name == "operations":
             for operation in value:
                 if isinstance(value, string_types):
                     b = py23_bytes(operation, 'utf-8')
                 else:
                     b = py23_bytes(operation)
                 output += OctetString(b).dump()
         elif name != "signatures":
             if isinstance(value, string_types):
                 b = py23_bytes(value, 'utf-8')
             else:
                 b = py23_bytes(value)
             output += OctetString(b).dump()
     return output
Пример #11
0
def make_hash_agility_v2(digest: bytes, hash_type: int) -> CMSAttribute:
    """
    CMSAttribute:
        type: HASH_AGILITY_V2_OID
        values: Set of HashAgility
            type: DigestAlgorithmId
            data: digest
    """
    dg_algo = _get_digest_algo(hash_type)
    ha = HashAgility({"type": dg_algo, "data": OctetString(digest)})
    return CMSAttribute({"type": HASH_AGILITY_V2_OID, "values": [ha]})
Пример #12
0
    def encode(byte_string, is_der = None, alg = 'Curve25519' ):
        try:
            raw = OctetString(byte_string)
        except Exception as e:
            raise FailedToParseByteString
        
        privateKey = PrivateKey(raw.dump())
        
        privateKeyAlgorithmIdentifier = PrivateKeyAlgorithmIdentifier( {'algorithm': alg });
        
        oneAsymmetricKey = OneAsymmetricKey({
            'version': Integer(0), 
            'privateKeyAlgorithm': privateKeyAlgorithmIdentifier,
            'privateKey': privateKey})
            
        der = oneAsymmetricKey.dump()

        if is_der:
             return der 

        return pem.armor('PRIVATE KEY',der).decode('ASCII')
Пример #13
0
def make_cms(
    cert: Certificate,
    hash_type: int,
    signed_attrs: CMSAttributes,
    sig: bytes,
    unsigned_attrs: Optional[CMSAttributes],
) -> ContentInfo:
    sid = SignerIdentifier(
        "issuer_and_serial_number",
        IssuerAndSerialNumber({
            "issuer":
            cert["tbs_certificate"]["issuer"],
            "serial_number":
            cert["tbs_certificate"]["serial_number"],
        }),
    )

    dg_algo = DigestAlgorithm({"algorithm": _get_digest_algo(hash_type)})

    sig_algo = SignedDigestAlgorithm(
        {"algorithm": SignedDigestAlgorithmId("rsassa_pkcs1v15")})

    sig_info = SignerInfo({
        "version": CMSVersion(1),
        "sid": sid,
        "digest_algorithm": dg_algo,
        "signed_attrs": signed_attrs,
        "signature_algorithm": sig_algo,
        "signature": OctetString(sig),
        "unsigned_attrs": unsigned_attrs,
    })

    certs = make_certificate_chain(cert)

    signed_data = SignedData({
        "version":
        CMSVersion(1),
        "digest_algorithms": [dg_algo],
        "encap_content_info":
        ContentInfo({"content_type": ContentType("data")}),
        "certificates":
        certs,
        "signer_infos": [sig_info],
    })

    return ContentInfo({
        "content_type": ContentType.unmap("signed_data"),
        "content": signed_data
    })
Пример #14
0
def make_hash_agility_v1(digest: bytes) -> CMSAttribute:
    """
    CMSAttribue:
        type: HASH_AGILITY_V1_OID
        values: Set of 1 XML Plist
            dict: {
                "cdhashes": [digset truncated to 20 bytes]
            }
    """
    plist_dict = {"cdhashes": [digest[:20]]}
    plist_bytes = plistlib.dumps(plist_dict, fmt=plistlib.FMT_XML)
    return CMSAttribute({
        "type": HASH_AGILITY_V1_OID,
        "values": [OctetString(plist_bytes)]
    })
Пример #15
0
def encode_ec_public_key(key):
    """
    Encode a DER-encoded EC public key as stored by OpenSSL.

    :param PublicKey key: EC public key
    :rtype: bytes
    """

    ecparams = ECDomainParameters.load(key[Attribute.EC_PARAMS])
    ecpoint = bytes(OctetString.load(key[Attribute.EC_POINT]))

    return PublicKeyInfo({
        'algorithm': {
            'algorithm': 'ec',
            'parameters': ecparams,
        },
        'public_key': ecpoint,
    }).dump()
Пример #16
0
def get_timestamp_token(digest: bytes, hash_type: int):
    # Create a TimestampRequest
    dg_algo = DigestAlgorithm({"algorithm": _get_digest_algo(hash_type)})
    imprint = MessageImprint({
        "hash_algorithm": dg_algo,
        "hashed_message": OctetString(digest)
    })

    tsreq = TimeStampReq({
        "version": Version(1),
        "message_imprint": imprint,
        "cert_req": True,
    })

    # Send tsreq to the server
    headers = {"Content-Type": "application/timestamp-query"}
    resp = requests.post(TIMESTAMP_SERVER, data=tsreq.dump(), headers=headers)
    resp.raise_for_status()
    tsresp = TimeStampResp.load(resp.content)

    return tsresp["time_stamp_token"]
Пример #17
0
    def build(self, signing_private_key_path, debug=False):
        """
        Validates the certificate information, constructs the ASN.1 structure
        and then signs it
        :param signing_private_key:
            path to a .pem file with a private key
        :return:
            An m2m.Certificate object of the newly signed
            certificate
        """
        if self._self_signed is not True and self._issuer is None:
            raise ValueError(_pretty_message(
                '''
                Certificate must be self-signed, or an issuer must be specified
                '''
            ))

        if self._self_signed:
            self._issuer = self._subject

        if self.serial_number is None:
            time_part = int_to_bytes(int(time.time()))
            random_part = random.getrandbits(24).to_bytes(3, byteorder='big')  # Must contain at least 20 randomly generated BITS
            self.serial_number = int_from_bytes(time_part + random_part)

        # Only re non-optionals are always in this dict
        properties = {
            'version':Integer(value=self._version),
            'serialNumber':OctetString(value=self.serial_number.to_bytes(20, byteorder='big')),
            'subject':self.subject,
        }

        # Optional fields are only added if they're not None
        if self.ca_algorithm is not None:
            properties['cAAlgorithm'] = self.ca_algorithm
        if self.ca_algorithm_parameters is not None:
            properties['cAAlgParams'] = OctetString(value=self.ca_algorithm_parameters)
        if self.issuer is not None:
            properties['issuer'] = self.issuer
        if self.valid_from is not None:
            properties['validFrom'] = self.valid_from
        if self.valid_duration is not None:
            properties['validDuration'] =  self.valid_duration
        if self.pk_algorithm is not None:
            properties['pKAlgorithm'] = self.pk_algorithm
        if self.pk_algorithm_parameters is not None:
            properties['pKAlgParams'] = OctetString(value=self.pk_algorithm_parameters)
        if self.public_key is not None:
            properties['pubKey'] = OctetString(value=self.public_key)
        if self.authkey_id is not None:
            properties['authKeyId'] = self.authkey_id
        if self.subject_key_id is not None:
            properties['subjKeyId'] = OctetString(value=self.subject_key_id)
        if self.key_usage is not None:
            properties['keyUsage'] = OctetString(value=self.key_usage)
        if self.basic_constraints is not None:
            properties['basicConstraints'] =  Integer(value=self.basic_constraints)
        if self.certificate_policy is not None:
            properties['certificatePolicy'] = self.certificate_policy
        if self.subject_alternative_name is not None:
            properties['subjectAltName'] = self.subject_alternative_name
        if self.issuer_alternative_name is not None:
            properties['issuerAltName'] = self.issuer_alternative_name
        if self.extended_key_usage is not None:
            properties['extendedKeyUsage'] = self.extended_key_usage
        if self.auth_info_access_ocsp is not None:
            properties['authInfoAccessOCSP'] = self.auth_info_access_ocsp
        if self.crl_distribution_point_uri is not None:
            properties['cRLDistribPointURI'] = self.crl_distribution_point_uri
        if self.x509_extensions is not None:
            properties['x509extensions'] = self.x509_extensions

        # import ipdb; ipdb.set_trace()
        # break /usr/local/lib/python3.5/dist-packages/asn1crypto/core.py:2786
        tbs_cert = TBSCertificate(properties)

        bytes_to_sign = tbs_cert.dump()
        signature = generate_signature(bytes_to_sign, signing_private_key_path)

        # assert verify_signature(bytes_to_sign, signature, "public.pem")

        if debug:
            print("Build  - Signed_bytes ({len}): {content}".format(len=len(bytes_to_sign), content=hexlify(bytes_to_sign)))
            print("Build  - Signature ({len}): {content}".format(len=len(signature), content=hexlify(signature)))


        return Certificate({
            'tbsCertificate': tbs_cert,
            'cACalcValue': signature
        })
Пример #18
0
 def asn1(self) -> _asn1.ImgGroupValue:
     return _asn1.ImgGroupValue({"ECPoint": OctetString(bytes(self))})
Пример #19
0
def parse_general_name(name: ParsableGeneralName) -> x509.GeneralName:
    """Parse a general name from user input.

    This function will do its best to detect the intended type of any value passed to it:

    >>> parse_general_name('example.com')
    <DNSName(value='example.com')>
    >>> parse_general_name('*.example.com')
    <DNSName(value='*.example.com')>
    >>> parse_general_name('.example.com')  # Syntax used e.g. for NameConstraints: All levels of subdomains
    <DNSName(value='.example.com')>
    >>> parse_general_name('*****@*****.**')
    <RFC822Name(value='*****@*****.**')>
    >>> parse_general_name('https://example.com')
    <UniformResourceIdentifier(value='https://example.com')>
    >>> parse_general_name('1.2.3.4')
    <IPAddress(value=1.2.3.4)>
    >>> parse_general_name('fd00::1')
    <IPAddress(value=fd00::1)>
    >>> parse_general_name('/CN=example.com')
    <DirectoryName(value=<Name(CN=example.com)>)>

    The default fallback is to assume a :py:class:`~cg:cryptography.x509.DNSName`. If this doesn't
    work, an exception will be raised:

    >>> parse_general_name('foo..bar`*123')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: Could not parse name: foo..bar`*123

    If you want to override detection, you can prefix the name to match :py:const:`GENERAL_NAME_RE`:

    >>> parse_general_name('email:[email protected]')
    <RFC822Name(value='*****@*****.**')>
    >>> parse_general_name('URI:https://example.com')
    <UniformResourceIdentifier(value='https://example.com')>
    >>> parse_general_name('dirname:/CN=example.com')
    <DirectoryName(value=<Name(CN=example.com)>)>

    Some more exotic values can only be generated by using this prefix:

    >>> parse_general_name('rid:2.5.4.3')
    <RegisteredID(value=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>)>
    >>> parse_general_name('otherName:2.5.4.3;UTF8:example.com')
    <OtherName(type_id=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=b'example.com')>

    If you give a prefixed value, this function is less forgiving of any typos and does not catch any
    exceptions:

    >>> parse_general_name('email:foo@bar com')
    Traceback (most recent call last):
        ...
    ValueError: Invalid domain: bar com

    """
    # pylint: disable=too-many-return-statements,too-many-branches,too-many-statements

    if isinstance(name, x509.GeneralName):
        return name
    if not isinstance(name, str):
        raise ValueError(
            "Cannot parse general name %s: Must be of type str (was: %s)." % (name, type(name).__name__)
        )

    typ = None
    match = GENERAL_NAME_RE.match(name)
    if match is not None:
        typ, name = match.groups()
        typ = typ.lower()

    if typ is None:
        if re.match("[a-z0-9]{2,}://", name):  # Looks like a URI
            try:
                return x509.UniformResourceIdentifier(encode_url(name))
            except idna.IDNAError:
                pass

        if "@" in name:  # Looks like an Email address
            try:
                return x509.RFC822Name(validate_email(name))
            except ValueError:
                pass

        if name.strip().startswith("/"):  # maybe it's a dirname?
            return x509.DirectoryName(x509_name(name))

        # Try to parse this as IPAddress/Network
        try:
            return x509.IPAddress(ip_address(name))
        except ValueError:
            pass
        try:
            return x509.IPAddress(ip_network(name))
        except ValueError:
            pass

        # Almost anything passes as DNS name, so this is our default fallback
        try:
            return x509.DNSName(encode_dns(name))
        except idna.IDNAError as e:
            raise ValueError("Could not parse name: %s" % name) from e

    if typ == "uri":
        try:
            return x509.UniformResourceIdentifier(encode_url(name))
        except idna.IDNAError as e:
            raise ValueError("Could not parse DNS name in URL: %s" % name) from e
    elif typ == "email":
        return x509.RFC822Name(validate_email(name))  # validate_email already raises ValueError
    elif typ == "ip":
        try:
            return x509.IPAddress(ip_address(name))
        except ValueError:
            pass

        try:
            return x509.IPAddress(ip_network(name))
        except ValueError:
            pass

        raise ValueError("Could not parse IP address.")
    elif typ == "rid":
        return x509.RegisteredID(x509.ObjectIdentifier(name))
    elif typ == "othername":
        match = re.match("(.*);(.*):(.*)", name)
        if match is not None:
            oid, asn_typ, val = match.groups()
            if asn_typ == "UTF8":
                parsed_value = val.encode("utf-8")
            elif asn_typ == "OctetString":
                parsed_value = OctetString(bytes(bytearray.fromhex(val))).dump()
            else:
                raise ValueError("Unsupported ASN type in otherName: %s" % asn_typ)

            return x509.OtherName(x509.ObjectIdentifier(oid), parsed_value)

        raise ValueError("Incorrect otherName format: %s" % name)
    elif typ == "dirname":
        return x509.DirectoryName(x509_name(name))
    else:
        try:
            return x509.DNSName(encode_dns(name))
        except idna.IDNAError as e:
            raise ValueError("Could not parse DNS name: %s" % name) from e
Пример #20
0
    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)
Пример #21
0
    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)
Пример #22
0
def parse_general_name(name):
    """Parse a general name from user input.

    This function will do its best to detect the intended type of any value passed to it:

    >>> parse_general_name('example.com')
    <DNSName(value='example.com')>
    >>> parse_general_name('*.example.com')
    <DNSName(value='*.example.com')>
    >>> parse_general_name('.example.com')  # Syntax used e.g. for NameConstraints: All levels of subdomains
    <DNSName(value='.example.com')>
    >>> parse_general_name('*****@*****.**')
    <RFC822Name(value='*****@*****.**')>
    >>> parse_general_name('https://example.com')
    <UniformResourceIdentifier(value='https://example.com')>
    >>> parse_general_name('1.2.3.4')
    <IPAddress(value=1.2.3.4)>
    >>> parse_general_name('fd00::1')
    <IPAddress(value=fd00::1)>
    >>> parse_general_name('/CN=example.com')
    <DirectoryName(value=<Name(CN=example.com)>)>

    The default fallback is to assume a :py:class:`~cg:cryptography.x509.DNSName`. If this doesn't
    work, an exception will be raised:

    >>> parse_general_name('foo..bar`*123')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    idna.core.IDNAError: ...

    If you want to override detection, you can prefix the name to match :py:const:`GENERAL_NAME_RE`:

    >>> parse_general_name('email:[email protected]')
    <RFC822Name(value='*****@*****.**')>
    >>> parse_general_name('URI:https://example.com')
    <UniformResourceIdentifier(value='https://example.com')>
    >>> parse_general_name('dirname:/CN=example.com')
    <DirectoryName(value=<Name(CN=example.com)>)>

    Some more exotic values can only be generated by using this prefix:

    >>> parse_general_name('rid:2.5.4.3')
    <RegisteredID(value=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>)>
    >>> parse_general_name('otherName:2.5.4.3;UTF8:example.com')
    <OtherName(type_id=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=b'example.com')>

    If you give a prefixed value, this function is less forgiving of any typos and does not catch any
    exceptions:

    >>> parse_general_name('email:foo@bar com')
    Traceback (most recent call last):
        ...
    ValueError: Invalid domain: bar com

    """
    name = force_text(name)
    typ = None
    match = GENERAL_NAME_RE.match(name)
    if match is not None:
        typ, name = match.groups()
        typ = typ.lower()

    if typ is None:
        if re.match('[a-z0-9]{2,}://', name):  # Looks like a URI
            try:
                return x509.UniformResourceIdentifier(name)
            except Exception:  # pragma: no cover - this really accepts anything
                pass

        if '@' in name:  # Looks like an Email address
            try:
                return x509.RFC822Name(validate_email(name))
            except Exception:
                pass

        if name.strip().startswith('/'):  # maybe it's a dirname?
            return x509.DirectoryName(x509_name(name))

        # Try to parse this as IPAddress/Network
        try:
            return x509.IPAddress(ip_address(name))
        except ValueError:
            pass
        try:
            return x509.IPAddress(ip_network(name))
        except ValueError:
            pass

        # Try to encode as domain name. DNSName() does not validate the domain name, but this check will fail.
        if name.startswith('*.'):
            idna.encode(name[2:])
        elif name.startswith('.'):
            idna.encode(name[1:])
        else:
            idna.encode(name)

        # Almost anything passes as DNS name, so this is our default fallback
        return x509.DNSName(name)

    if typ == 'uri':
        return x509.UniformResourceIdentifier(name)
    elif typ == 'email':
        return x509.RFC822Name(validate_email(name))
    elif typ == 'ip':
        try:
            return x509.IPAddress(ip_address(name))
        except ValueError:
            pass

        try:
            return x509.IPAddress(ip_network(name))
        except ValueError:
            pass

        raise ValueError('Could not parse IP address.')
    elif typ == 'rid':
        return x509.RegisteredID(x509.ObjectIdentifier(name))
    elif typ == 'othername':
        regex = "(.*);(.*):(.*)"
        if re.match(regex, name) is not None:
            oid, asn_typ, val = re.match(regex, name).groups()
            oid = x509.ObjectIdentifier(oid)
            if asn_typ == 'UTF8':
                val = val.encode('utf-8')
            elif asn_typ == 'OctetString':
                val = bytes(bytearray.fromhex(val))
                val = OctetString(val).dump()
            else:
                raise ValueError('Unsupported ASN type in otherName: %s' %
                                 asn_typ)
            val = force_bytes(val)
            return x509.OtherName(oid, val)
        else:
            raise ValueError('Incorrect otherName format: %s' % name)
    elif typ == 'dirname':
        return x509.DirectoryName(x509_name(name))
    else:
        # Try to encode the domain name. DNSName() does not validate the domain name, but this
        # check will fail.
        if name.startswith('*.'):
            idna.encode(name[2:])
        elif name.startswith('.'):
            idna.encode(name[1:])
        else:
            idna.encode(name)

        return x509.DNSName(name)
Пример #23
0
from asn1crypto.core import Sequence, OctetString


data = bytes.fromhex('605e06062b0601050502a0543052a024302206092a864882f71201020206092a864886f712010202060a2b06010401823702020aa32a3028a0261b246e6f745f646566696e65645f696e5f5246433431373840706c656173655f69676e6f7265')
#data = bytes.fromhex('6E8201FE308201FAA003020105A10302010EA20703050000000000A38201416182013D30820139A003020105A10F1B0D465245454950412E4C4F43414CA21D301BA003020101A11430121B066B61646D696E1B086368616E67657077A38201003081FDA003020112A103020101A281F00481EDECC2A53967B412D791DFF3EA3D50F765DC7ED7C7E66912C836163F5BD0A07FC679E46D36C9B38A2273C877D233AD55FAB9F3D95637F8F1DC22117723E77537C92D909064DE10B26E86C9EFDCCF37CC16D20E75849D0CBD04A56E7F69D46C6D7DB9DDDC6ACBBE37D6CF49C6CC78C57228C0E903FDC08772B030DD22DC84B5D55C66E07279E9840A3EA68F1C27BA26305D1CD05D1E3A994A4246DB8E834948EFD3788409760994AF1A72F5CF1485C49C7646A3B72C460FD62F5C373C224ECE0859F4DDEF5B77BF75A9AB220524E00A35A357722F703A218C5FD1A717ED0392F19864BF0B52921B501906A8AF48C3A4819F30819CA003020112A28194048191EAD1DF7495E86BFEC932DBA81C9A764826080BB8C359AC3627C4B2CE530217042449E9CAA3DB66031FBE4B1CF942EC9EC773A2FB2485DD4D6E1271F9FF41D26C54CE9370D6E4573156CDC051944A563056BFA1D47CECEFF3CB4AC455FE33CD03E91BA9B4DC2243CE59EF0E1865AEBDBA76E30EB2AD8DEB71409B11F86CFA6C6E488270303C0451BD86A91C139018421A07')
#data = b'$\x80\x04\r\x8d\xff\xf0\x98\x076\xaf\x93nB:\xcf\xcc\x04\x15\x92w\xf7\xf0\xe4y\xff\xc7\xdc3\xb2\xd0={\x1a\x18mDr\xaaI\x00\x00'
a = OctetString.load(data)
print(data)
print(a)
#parsed = Sequence.load(data)
#serialized = parsed.dump()