def _decode_value(cls, buf, strict=True):
        """Decode from a string or string buffer."""
        if buf in _OID_DECODING_DICT:
            return _OID_DECODING_DICT[buf]
        if not buf:
            raise error.ASN1Error("Invalid encoding")
        int_bytes = bytearray(buf)

        # Last byte can't have the high bit set.
        if int_bytes[-1] & 0x80:
            raise error.ASN1Error("Invalid encoding")

        components = []

        first, int_bytes = cls._read_component(int_bytes)
        if first < 40:
            components += [0, first]
        elif first < 80:
            components += [1, first - 40]
        else:
            components += [2, first - 80]

        while int_bytes:
            component, int_bytes = cls._read_component(int_bytes)
            components.append(component)

        return tuple(components)
    def _read_component(cls, int_bytes):
        """Parse a single component from a non-empty bytearray.

        Args:
            int_bytes: a non-empty bytearray.

        Returns:
            a (component, rest) tuple with the decoded integer and the
                remaining bytes of the bytearray.
        """
        ret = 0
        i = 0
        while int_bytes[i] & 0x80:
            num = int_bytes[i] & 0x7f
            if not ret and not num:
                # The component must be encoded with as few digits as possible,
                # i.e., leading zeroes are not allowed. Since ASN.1 libraries
                # interpret leading 0x80-octets differently, this may be
                # indicative of an attempt to trick a browser into accepting a
                # certificate it shouldn't. See page 7 of
                # www.cosic.esat.kuleuven.be/publications/article-1432.pdf
                raise error.ASN1Error("Leading 0x80 octets in the base-128 "
                                      "encoding of  OID component")
            ret |= num
            ret <<= 7
            i += 1

        ret |= int_bytes[i]
        return ret, int_bytes[i + 1:]
 def __init__(self, value=None, serialized_value=None, strict=True):
     super(IPAddress, self).__init__(value=value,
                                     serialized_value=serialized_value,
                                     strict=strict)
     if strict and len(self._value) != 4 and len(self._value) != 16:
         raise error.ASN1Error("%s is not a valid IP address",
                               self.value.encode("hex"))
 def __init__(self, value=None, serialized_value=None, strict=True):
     super(BaseTime, self).__init__(value=value,
                                    serialized_value=serialized_value,
                                    strict=strict)
     self._gmtime = self._decode_gmtime(strict=strict)
     # This is a lenient "strict": if we were able to decode the time,
     # even if it didn't fully conform to the standard, then we'll allow it.
     # If the time string is garbage then we raise.
     if strict and self._gmtime is None:
         raise error.ASN1Error("Corrupt time: %s" % self._value)
    def gmtime(self):
        """GMT time.

        Returns:
            a time.struct_time struct.

        Raises:
            error.ASN1Error: the ASN.1 string does not represent a valid time.
        """
        if self._gmtime is None:
            raise error.ASN1Error("Corrupt time: %s" % self._value)
        return self._gmtime
    def attributes(self, attr_type):
        """Get a flat list of attribute values of the given type.

        Returns:
            a list of attributes.

        Raises:
            error.ASN1Error: corrupt attribute value.
        """
        attrs = self.flatten()
        decoded_values = [attr["value"].decoded_value for attr in attrs
                          if attr["type"] == attr_type]
        if any([val is None for val in decoded_values]):
            raise error.ASN1Error("Corrupt name attribute")
        # A subject name attribute is always a DirectoryString (a Choice),
        # so we need to take its value.
        return [d.component_value() for d in decoded_values]
    def __init__(self, der_string, strict_der=True):
        """Initialize from a DER string.

        Args:
            der_string: a binary string containing the DER-encoded
                certificate.
            strict_der: if False, tolerate some non-fatal DER errors.

        Raises:
            error.ASN1Error: invalid encoding.
        """
        # ASN.1 errors fall through.
        self._asn1_cert = x509.Certificate.decode(der_string,
                                                  strict=strict_der)
        # The general philosophy here is that a certificate decoded in
        # strict mode should never raise CertificateErrors later on in the
        # code. Strict mode already catches corrupt extensions, to the extent
        # that their IDs are recognized; in addition, we have to ensure that
        # no extension appears more than once.
        # TODO(ekasper): move this check to the Extensions class.
        if strict_der and self._has_multiple_extension_values():
            raise error.ASN1Error("Multiple extensions")