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
def _get_encryption_algorithm(algorithm, location): result = asn1.oids.OID_TO_PUBKEY.get(algorithm['algorithm']) if result is None: raise ParseError("%s: %s is not acceptable as encryption algorithm" % (location, algorithm['algorithm'])) _verify_empty_algorithm_parameters(algorithm, location) return result
def _get_digest_algorithm(algorithm, location): result = asn1.oids.get(algorithm['algorithm']) if result not in ACCEPTED_DIGEST_ALGORITHMS: raise ParseError( "%s must be one of %s, not %s" % (location, [x().name for x in ACCEPTED_DIGEST_ALGORITHMS], result().name)) _verify_empty_algorithm_parameters(algorithm, location) return result
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 _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
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 _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, ))