コード例 #1
0
    def _parse_attributes(cls, data, required=()):
        """Given a set of Attributes, parses them and returns them as a dict

        :param data: The authenticatedAttributes or unauthenticatedAttributes to process
        :param required: A list of required attributes
        """

        if isinstance(data, rfc2315.Attributes):
            type_key, value_key = 'type', 'values'
        elif isinstance(
                data, (rfc5652.SignedAttributes, rfc5652.UnsignedAttributes)):
            type_key, value_key = 'attrType', 'attrValues'

        result = {}
        for attr in data:
            typ = asn1.oids.get(attr[type_key])
            values = []
            for value in attr[value_key]:
                if not isinstance(typ, tuple):
                    value = guarded_ber_decode(value, asn1_spec=typ())
                values.append(value)
            result[typ] = values

        if not all((x in result for x in required)):
            raise SignerInfoParseError(
                "Not all required attributes found. Required: %s; Found: %s" %
                ([_print_type(x)
                  for x in required], [_print_type(x) for x in result]))

        return result
コード例 #2
0
ファイル: __init__.py プロジェクト: ralphje/signify
def guarded_ber_decode(data, asn1_spec=None):
    from pyasn1.codec.ber import decoder as ber_decoder
    from signify.exceptions import ParseError
    from signify import _print_type

    try:
        result, rest = ber_decoder.decode(data, asn1Spec=asn1_spec)
    except Exception as e:
        raise ParseError("Error while parsing %s BER: %s" % (_print_type(asn1_spec), e))
    if rest:
        raise ParseError("Extra information after parsing %s BER" % _print_type(asn1_spec))
    return result
コード例 #3
0
ファイル: signeddata.py プロジェクト: ralphje/signify
    def _parse(self):
        # digestAlgorithms
        if len(self.data['digestAlgorithms']) != 1:
            raise ParseError(
                "SignedData.digestAlgorithms must contain exactly 1 algorithm, not %d"
                % len(self.data['digestAlgorithms']))
        self.digest_algorithm = _get_digest_algorithm(
            self.data['digestAlgorithms'][0], "SignedData.digestAlgorithm")

        # contentType
        if isinstance(self.data, rfc2315.SignedData):
            self.content_type = asn1.oids.get(
                self.data['contentInfo']['contentType'])
            content = self.data['contentInfo']['content']
        elif isinstance(self.data, rfc5652.SignedData):
            self.content_type = asn1.oids.get(
                self.data['encapContentInfo']['eContentType'])
            content = self.data['encapContentInfo']['eContent']
        else:
            raise ParseError("Unknown SignedData data type {}".format(
                _print_type(self.data)))

        if self.content_type is not self._expected_content_type:
            raise ParseError("SignedData.contentInfo does not contain %s" %
                             _print_type(self._expected_content_type))

        # Content
        self.content = guarded_ber_decode(
            content, asn1_spec=self._expected_content_type())

        # Certificates
        self.certificates = CertificateStore([
            Certificate(cert) for cert in self.data['certificates']
            if Certificate.is_certificate(cert)
        ])

        # SignerInfo
        if self._signerinfo_class is not None:
            self.signer_infos = [
                self._signerinfo_class(si, parent=self)
                for si in self.data['signerInfos']
            ]
コード例 #4
0
def _get_digest_algorithm(algorithm,
                          location,
                          acceptable=ACCEPTED_DIGEST_ALGORITHMS):
    result = asn1.oids.get(algorithm['algorithm'])
    if result not in acceptable:
        raise ParseError(
            "%s must be one of %s, not %s" %
            (location, [x().name for x in acceptable], _print_type(result)))

    _verify_empty_algorithm_parameters(algorithm, location)
    return result
コード例 #5
0
    def _parse(self):
        if self.data['version'] != 1:
            raise SignerInfoParseError("SignerInfo.version must be 1, not %d" %
                                       self.data['version'])

        # We can handle several different rfc types here
        if isinstance(self.data, rfc2315.SignerInfo):
            self.issuer = CertificateName(
                self.data['issuerAndSerialNumber']['issuer'][0])
            self.serial_number = self.data['issuerAndSerialNumber'][
                'serialNumber']

            self.authenticated_attributes = self._parse_attributes(
                self.data['authenticatedAttributes'],
                required=self._required_authenticated_attributes)
            self._encoded_authenticated_attributes = self._encode_attributes(
                self.data['authenticatedAttributes'])

            self.unauthenticated_attributes = self._parse_attributes(
                self.data['unauthenticatedAttributes'])

            self.digest_encryption_algorithm = _get_encryption_algorithm(
                self.data['digestEncryptionAlgorithm'],
                location="SignerInfo.digestEncryptionAlgorithm")
            self.encrypted_digest = bytes(self.data['encryptedDigest'])

        elif isinstance(self.data, rfc5652.SignerInfo):
            # TODO: handle case where sid contains key identifier
            self.issuer = CertificateName(
                self.data['sid']['issuerAndSerialNumber']['issuer'][0])
            self.serial_number = self.data['sid']['issuerAndSerialNumber'][
                'serialNumber']

            self.authenticated_attributes = self._parse_attributes(
                self.data['signedAttrs'],
                required=self._required_authenticated_attributes)
            self._encoded_authenticated_attributes = self._encode_attributes(
                self.data['signedAttrs'])

            self.unauthenticated_attributes = self._parse_attributes(
                self.data['unsignedAttrs'])

            self.digest_encryption_algorithm = _get_encryption_algorithm(
                self.data['signatureAlgorithm'],
                location="SignerInfo.signatureAlgorithm")
            self.encrypted_digest = bytes(self.data['signature'])

        else:
            raise SignerInfoParseError("Unknown SignerInfo type %s" %
                                       type(self.data))

        self.digest_algorithm = _get_digest_algorithm(
            self.data['digestAlgorithm'],
            location="SignerInfo.digestAlgorithm")

        # Parse the content of the authenticated attributes
        # - The messageDigest
        self.message_digest = None
        if rfc2315.Digest in self.authenticated_attributes:
            if len(self.authenticated_attributes[rfc2315.Digest]) != 1:
                raise SignerInfoParseError(
                    "Only one Digest expected in SignerInfo.authenticatedAttributes"
                )

            self.message_digest = bytes(
                self.authenticated_attributes[rfc2315.Digest][0])

        # - The contentType
        self.content_type = None
        if rfc2315.ContentType in self.authenticated_attributes:
            if len(self.authenticated_attributes[rfc2315.ContentType]) != 1:
                raise SignerInfoParseError(
                    "Only one ContentType expected in SignerInfo.authenticatedAttributes"
                )

            self.content_type = asn1.oids.get(
                self.authenticated_attributes[rfc2315.ContentType][0])

            if self._expected_content_type is not None and self.content_type is not self._expected_content_type:
                raise SignerInfoParseError(
                    "Unexpected content type for SignerInfo, expected %s, got %s"
                    % (_print_type(self._expected_content_type),
                       _print_type(self.content_type)))

        # - The signingTime (used by countersigner)
        self.signing_time = None
        if rfc5652.SigningTime in self.authenticated_attributes:
            if len(self.authenticated_attributes[rfc5652.SigningTime]) != 1:
                raise SignerInfoParseError(
                    "Only one SigningTime expected in SignerInfo.authenticatedAttributes"
                )

            self.signing_time = time_to_python(
                self.authenticated_attributes[rfc5652.SigningTime][0])

        # - The countersigner
        self.countersigner = None
        if pkcs7.Countersignature in self.unauthenticated_attributes:
            if len(self.unauthenticated_attributes[
                    pkcs7.Countersignature]) != 1:
                raise SignerInfoParseError(
                    "Only one CountersignInfo expected in SignerInfo.unauthenticatedAttributes"
                )

            self.countersigner = self._countersigner_class(
                self.unauthenticated_attributes[pkcs7.Countersignature][0])