def _parse_attributes(cls, data): """Given a set of Attributes, parses them and returns them as a dict :param data: The attributes to process """ result = {} for attr in data: typ = asn1.oids.get(attr['type']) values = [] for value in attr['values']: if not isinstance(typ, tuple): # This should transparently handle when the data is encapsulated in an OctetString but we are # not expecting an OctetString try: from pyasn1.type import univ if not isinstance(type, univ.OctetString): _, v = ber_decoder.decode(value, recursiveFlag=0) else: v = value value = guarded_ber_decode(v, asn1_spec=typ()) except Exception: value = guarded_ber_decode(value, asn1_spec=typ()) values.append(value) result[typ] = values return result
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
def _parse(self): super()._parse() # - Retrieve object from SpcSpOpusInfo from the authenticated attributes (for normal signer) self.program_name = self.more_info = None if asn1.spc.SpcSpOpusInfo in self.authenticated_attributes: if len(self.authenticated_attributes[asn1.spc.SpcSpOpusInfo]) != 1: raise AuthenticodeParseError( "Only one SpcSpOpusInfo expected in SignerInfo.authenticatedAttributes" ) self.program_name = self.authenticated_attributes[ asn1.spc.SpcSpOpusInfo][0]['programName'].to_python() self.more_info = self.authenticated_attributes[ asn1.spc.SpcSpOpusInfo][0]['moreInfo'].to_python() # - Authenticode can be signed using a RFC-3161 timestamp, so we discover this possibility here if pkcs7.Countersignature in self.unauthenticated_attributes \ and asn1.spc.SpcRfc3161Timestamp in self.unauthenticated_attributes: raise AuthenticodeParseError( "Countersignature and RFC-3161 timestamp present in " "SignerInfo.unauthenticatedAttributes") if asn1.spc.SpcRfc3161Timestamp in self.unauthenticated_attributes: if len(self.unauthenticated_attributes[ asn1.spc.SpcRfc3161Timestamp]) != 1: raise AuthenticodeParseError( "Only one RFC-3161 timestamp expected in " "SignerInfo.unauthenticatedAttributes") ts_data = self.unauthenticated_attributes[ asn1.spc.SpcRfc3161Timestamp][0] content_type = asn1.oids.get(ts_data['contentType']) if content_type is not rfc2315.SignedData: raise AuthenticodeParseError( "RFC-3161 Timestamp does not contain SignedData structure") # Note that we expect rfc5652 compatible data here # This is a work-around for incorrectly tagged v2AttrCerts in the BER-encoded blob, # see the docstring for patch_rfc5652_signeddata for more details try: signed_data = guarded_ber_decode( ts_data['content'], asn1_spec=rfc5652.SignedData()) except ParseError: with patch_rfc5652_signeddata() as asn1_spec: signed_data = guarded_ber_decode(ts_data['content'], asn1_spec=asn1_spec) self.countersigner = RFC3161SignedData(signed_data)
def from_envelope(cls, data, *args, **kwargs): """Loads a :class:`SignedData` object from raw data that contains ContentInfo. :param bytes data: The bytes to parse """ # This one is not guarded, which is intentional content, rest = ber_decoder.decode(data, asn1Spec=rfc2315.ContentInfo()) if asn1.oids.get(content['contentType']) is not rfc2315.SignedData: raise ParseError("ContentInfo does not contain SignedData") data = guarded_ber_decode(content['content'], asn1_spec=rfc2315.SignedData()) signed_data = cls(data, *args, **kwargs) signed_data._rest_data = rest return signed_data
def from_stl_file(cls, path=AUTHROOTSTL_PATH): with open(str(path), "rb") as f: content, rest = ber_decoder.decode(f.read(), asn1Spec=rfc2315.ContentInfo()) # # from pyasn1 import debug # debug.setLogger(debug.Debug('all')) if asn1.oids.get(content['contentType']) is not rfc2315.SignedData: raise CertificateTrustListParseError( "ContentInfo does not contain SignedData") data = guarded_ber_decode(content['content'], asn1_spec=rfc2315.SignedData()) signed_data = cls(data) signed_data._rest_data = rest return signed_data
def _parse(self): # Parse the fields of the SignedData structure if self.data['version'] != 1: raise AuthenticodeParseError( "SignedData.version must be 1, not %d" % self.data['version']) # digestAlgorithms if len(self.data['digestAlgorithms']) != 1: raise AuthenticodeParseError( "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") # SpcIndirectDataContent self.content_type = asn1.oids.get( self.data['contentInfo']['contentType']) if self.content_type is not asn1.spc.SpcIndirectDataContent: raise AuthenticodeParseError( "SignedData.contentInfo does not contain SpcIndirectDataContent" ) spc_info = guarded_ber_decode( self.data['contentInfo']['content'], asn1_spec=asn1.spc.SpcIndirectDataContent()) self.spc_info = SpcInfo(spc_info) # Certificates self.certificates = CertificateStore( [Certificate(cert) for cert in self.data['certificates']]) # signerInfos if len(self.data['signerInfos']) != 1: raise AuthenticodeParseError( "SignedData.signerInfos must contain exactly 1 signer, not %d" % len(self.data['signerInfos'])) self.signer_info = AuthenticodeSignerInfo(self.data['signerInfos'][0]) # CRLs if 'crls' in self.data and self.data['crls'].isValue: raise AuthenticodeParseError( "SignedData.crls is present, but that is unexpected.")
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'] ]
def _verify_empty_algorithm_parameters(algorithm, location): if 'parameters' in algorithm and algorithm['parameters'].isValue: parameters = guarded_ber_decode(algorithm['parameters']) if not isinstance(parameters, univ.Null): raise ParseError("%s has parameters set, which is unexpected" % (location, ))
def test_normal_read(self): self.assertTrue(guarded_ber_decode(univ.Any("\x01\x01\xff"))) # true self.assertFalse(guarded_ber_decode(univ.Any("\x01\x01\x00"))) # false self.assertIsInstance(guarded_ber_decode(univ.Any("\x05\x00")), univ.Null) # null