def testDecode4(self): # One very long integer der = DerSequence() der.decode( b('0\x82\x01\x05') + b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) self.assertEqual(len(der), 1) self.assertEqual(der[0], 2**2048)
def testDecode6(self): # Two integers der = DerSequence() der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) self.assertEqual(len(der), 2) self.assertEqual(der[0], 0x180) self.assertEqual(der[1], 0xFF)
def testEncode4(self): # One very long integer der = DerSequence() der.append(2**2048) self.assertEqual( der.encode(), b('0\x82\x01\x05') + b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
def testDecode7(self): # One integer and 2 other types der = DerSequence() der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) self.assertEqual(len(der), 3) self.assertEqual(der[0], 0x180) self.assertEqual(der[1], b('\x24\x02\xb6\x63')) self.assertEqual(der[2], b('\x12\x00'))
def _create_subject_public_key_info(algo_oid, secret_key, params=None): if params is None: params = DerNull() spki = DerSequence([ DerSequence([DerObjectId(algo_oid), params]), DerBitString(secret_key) ]) return spki.encode()
def testEncode8(self): # One integer and another type (yet to encode) der = DerSequence() der.append(0x180) der.append(DerSequence([5])) self.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) self.assertFalse(der.hasOnlyInts())
def decrypt(data, passphrase): """Decrypt a piece of data using a passphrase and *PBES1*. The algorithm to use is automatically detected. :Parameters: data : byte string The piece of data to decrypt. passphrase : byte string The passphrase to use for decrypting the data. :Returns: The decrypted data, as a binary string. """ enc_private_key_info = DerSequence().decode(data) encrypted_algorithm = DerSequence().decode(enc_private_key_info[0]) encrypted_data = DerOctetString().decode( enc_private_key_info[1]).payload pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value cipher_params = {} if pbe_oid == "1.2.840.113549.1.5.3": # PBE_MD5_DES_CBC hashmod = MD5 ciphermod = DES elif pbe_oid == "1.2.840.113549.1.5.6": # PBE_MD5_RC2_CBC hashmod = MD5 ciphermod = ARC2 cipher_params['effective_keylen'] = 64 elif pbe_oid == "1.2.840.113549.1.5.10": # PBE_SHA1_DES_CBC hashmod = SHA1 ciphermod = DES elif pbe_oid == "1.2.840.113549.1.5.11": # PBE_SHA1_RC2_CBC hashmod = SHA1 ciphermod = ARC2 cipher_params['effective_keylen'] = 64 else: raise PbesError("Unknown OID for PBES1") pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2) salt = DerOctetString().decode(pbe_params[0]).payload iterations = pbe_params[1] key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod) key, iv = key_iv[:8], key_iv[8:] cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params) pt = cipher.decrypt(encrypted_data) return unpad(pt, cipher.block_size)
def test_expected_nr_elements(self): der_bin = DerSequence([1, 2, 3]).encode() DerSequence().decode(der_bin, nr_elements=3) DerSequence().decode(der_bin, nr_elements=(2, 3)) self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=1) self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=(4, 5))
def verify(self, msg_hash, signature): """Check if a certain (EC)DSA signature is authentic. :parameter msg_hash: The hash that was carried out over the message. This is an object belonging to the :mod:`crypto.Hash` module. Under mode *'fips-186-3'*, the hash must be a FIPS approved secure hash (SHA-1 or a member of the SHA-2 family), of cryptographic strength appropriate for the DSA key. For instance, a 3072/256 DSA key can only be used in combination with SHA-512. :type msg_hash: hash object :parameter signature: The signature that needs to be validated :type signature: byte string :raise ValueError: if the signature is not authentic """ if not self._valid_hash(msg_hash): raise ValueError("Hash is not sufficiently strong") if self._encoding == 'binary': if len(signature) != (2 * self._order_bytes): raise ValueError("The signature is not authentic (length)") r_prime, s_prime = [ Integer.from_bytes(x) for x in (signature[:self._order_bytes], signature[self._order_bytes:]) ] else: try: der_seq = DerSequence().decode(signature, strict=True) except (ValueError, IndexError): raise ValueError("The signature is not authentic (DER)") if len(der_seq) != 2 or not der_seq.hasOnlyInts(): raise ValueError( "The signature is not authentic (DER content)") r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1]) if not (0 < r_prime < self._order) or not (0 < s_prime < self._order): raise ValueError("The signature is not authentic (d)") z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) result = self._key._verify(z, (r_prime, s_prime)) if not result: raise ValueError("The signature is not authentic") # Make PyCrypto code to fail return False
def testEncode7(self): # One integer and another type (already encoded) der = DerSequence() der.append(0x180) der.append(b('0\x03\x02\x01\x05')) self.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) self.assertFalse(der.hasOnlyInts())
def _export_private_der(self, include_ec_params=True): assert self.has_private() # ECPrivateKey ::= SEQUENCE { # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), # privateKey OCTET STRING, # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, # publicKey [1] BIT STRING OPTIONAL # } # Public key - uncompressed form order_bytes = _curve.order.size_in_bytes() public_key = (bchr(4) + self.pointQ.x.to_bytes(order_bytes) + self.pointQ.y.to_bytes(order_bytes)) seq = [1, DerOctetString(self.d.to_bytes(order_bytes)), DerObjectId(_curve.oid, explicit=0), DerBitString(public_key, explicit=1)] if not include_ec_params: del seq[2] return DerSequence(seq).encode()
def _import_pkcs1_public(encoded, *kwargs): # RSAPublicKey ::= SEQUENCE { # modulus INTEGER, -- n # publicExponent INTEGER -- e # } der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True) return construct(der)
def _import_openssl_private(encoded, passphrase, params): if params: raise ValueError("DSA private key already comes with parameters") der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True) if der[0] != 0: raise ValueError("No version found") tup = [der[comp] for comp in (4, 3, 1, 2, 5)] return construct(tup)
def testDecode8(self): # Only 2 other types der = DerSequence() der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00')) self.assertEqual(len(der), 2) self.assertEqual(der[0], b('\x24\x02\xb6\x63')) self.assertEqual(der[1], b('\x12\x00')) self.assertEqual(der.hasInts(), 0) self.assertEqual(der.hasInts(False), 0) self.assertFalse(der.hasOnlyInts()) self.assertFalse(der.hasOnlyInts(False))
def _import_pkcs8(encoded, passphrase, params): if params: raise ValueError("PKCS#8 already includes parameters") k = PKCS8.unwrap(encoded, passphrase) if k[0] != oid: raise ValueError("No PKCS#8 encoded DSA key") x = DerInteger().decode(k[1]).value p, q, g = list(DerSequence().decode(k[2])) tup = (pow(g, x, p), g, p, q, x) return construct(tup)
def _extract_subject_public_key_info(x509_certificate): """Extract subjectPublicKeyInfo from a DER X.509 certificate.""" certificate = DerSequence().decode(x509_certificate, nr_elements=3) tbs_certificate = DerSequence().decode(certificate[0], nr_elements=range(6, 11)) index = 5 try: tbs_certificate[0] + 1 # Version not present version = 1 except TypeError: version = DerInteger(explicit=0).decode(tbs_certificate[0]).value if version not in (2, 3): raise ValueError("Incorrect X.509 certificate version") index = 6 return tbs_certificate[index]
def testDecode1(self): # Empty sequence der = DerSequence() der.decode(b('0\x00')) self.assertEqual(len(der), 0) # One single-byte integer (zero) der.decode(b('0\x03\x02\x01\x00')) self.assertEqual(len(der), 1) self.assertEqual(der[0], 0) # Invariant der.decode(b('0\x03\x02\x01\x00')) self.assertEqual(len(der), 1) self.assertEqual(der[0], 0)
def testErrDecode3(self): # Wrong length format der = DerSequence() # Missing length in sub-item self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\x01\x00')) # Valid BER, but invalid DER length self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01')) self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01'))
def _import_subjectPublicKeyInfo(encoded, passphrase, params): algoid, encoded_key, emb_params = _expand_subject_public_key_info(encoded) if algoid != oid: raise ValueError("No DSA subjectPublicKeyInfo") if params and emb_params: raise ValueError("Too many DSA parameters") y = DerInteger().decode(encoded_key).value p, q, g = list(DerSequence().decode(params or emb_params)) tup = (y, g, p, q) return construct(tup)
def test_expected_only_integers(self): der_bin1 = DerSequence([1, 2, 3]).encode() der_bin2 = DerSequence([1, 2, DerSequence([3, 4])]).encode() DerSequence().decode(der_bin1, only_ints_expected=True) DerSequence().decode(der_bin1, only_ints_expected=False) DerSequence().decode(der_bin2, only_ints_expected=False) self.assertRaises(ValueError, DerSequence().decode, der_bin2, only_ints_expected=True)
def _import_private_der(encoded, passphrase, curve_oid=None): # See RFC5915 https://tools.ietf.org/html/rfc5915 # # ECPrivateKey ::= SEQUENCE { # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), # privateKey OCTET STRING, # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, # publicKey [1] BIT STRING OPTIONAL # } private_key = DerSequence().decode(encoded, nr_elements=(3, 4)) if private_key[0] != 1: raise ValueError("Incorrect ECC private key version") try: parameters = DerObjectId(explicit=0).decode(private_key[2]).value if curve_oid is not None and parameters != curve_oid: raise ValueError("Curve mismatch") curve_oid = parameters except ValueError: pass if curve_oid is None: raise ValueError("No curve found") for curve_name, curve in _curves.items(): if curve.oid == curve_oid: break else: raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) scalar_bytes = DerOctetString().decode(private_key[1]).payload modulus_bytes = curve.p.size_in_bytes() if len(scalar_bytes) != modulus_bytes: raise ValueError("Private key is too small") d = Integer.from_bytes(scalar_bytes) # Decode public key (if any) if len(private_key) == 4: public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value public_key = _import_public_der(curve_oid, public_key_enc) point_x = public_key.pointQ.x point_y = public_key.pointQ.y else: point_x = point_y = None return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y)
def _expand_subject_public_key_info(encoded): """Parse a SubjectPublicKeyInfo structure. It returns a triple with: * OID (string) * encoded public key (bytes) * Algorithm parameters (bytes or None) """ # # SubjectPublicKeyInfo ::= SEQUENCE { # algorithm AlgorithmIdentifier, # subjectPublicKey BIT STRING # } # # AlgorithmIdentifier ::= SEQUENCE { # algorithm OBJECT IDENTIFIER, # parameters ANY DEFINED BY algorithm OPTIONAL # } # spki = DerSequence().decode(encoded, nr_elements=2) algo = DerSequence().decode(spki[0], nr_elements=(1, 2)) algo_oid = DerObjectId().decode(algo[0]) spk = DerBitString().decode(spki[1]).value if len(algo) == 1: algo_params = None else: try: DerNull().decode(algo[1]) algo_params = None except: algo_params = algo[1] return algo_oid.value, spk, algo_params
def sign(self, msg_hash): """Produce the DSA/ECDSA signature of a message. :parameter msg_hash: The hash that was carried out over the message. The object belongs to the :mod:`crypto.Hash` package. Under mode *'fips-186-3'*, the hash must be a FIPS approved secure hash (SHA-1 or a member of the SHA-2 family), of cryptographic strength appropriate for the DSA key. For instance, a 3072/256 DSA key can only be used in combination with SHA-512. :type msg_hash: hash object :return: The signature as a *byte string* :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key :raise TypeError: if the (EC)DSA key has no private half """ if not self._valid_hash(msg_hash): raise ValueError("Hash is not sufficiently strong") # Generate the nonce k (critical!) nonce = self._compute_nonce(msg_hash) # Perform signature using the raw API z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) sig_pair = self._key._sign(z, nonce) # Encode the signature into a single byte string if self._encoding == 'binary': output = b"".join( [long_to_bytes(x, self._order_bytes) for x in sig_pair]) else: # Dss-sig ::= SEQUENCE { # r INTEGER, # s INTEGER # } # Ecdsa-Sig-Value ::= SEQUENCE { # r INTEGER, # s INTEGER # } output = DerSequence(sig_pair).encode() return output
def _import_pkcs1_private(encoded, *kwargs): # RSAPrivateKey ::= SEQUENCE { # version Version, # modulus INTEGER, -- n # publicExponent INTEGER, -- e # privateExponent INTEGER, -- d # prime1 INTEGER, -- p # prime2 INTEGER, -- q # exponent1 INTEGER, -- d mod (p-1) # exponent2 INTEGER, -- d mod (q-1) # coefficient INTEGER -- (inverse of q) mod p # } # # Version ::= INTEGER der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) if der[0] != 0: raise ValueError("No PKCS#1 encoding of an RSA private key") return construct(der[1:6] + [Integer(der[4]).inverse(der[5])])
def testEncode2(self): # Indexing der = DerSequence() der.append(0) der[0] = 1 self.assertEqual(len(der), 1) self.assertEqual(der[0], 1) self.assertEqual(der[-1], 1) self.assertEqual(der.encode(), b('0\x03\x02\x01\x01')) # der[:] = [1] self.assertEqual(len(der), 1) self.assertEqual(der[0], 1) self.assertEqual(der.encode(), b('0\x03\x02\x01\x01'))
def _import_private_der(encoded, passphrase, curve_name=None): # ECPrivateKey ::= SEQUENCE { # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), # privateKey OCTET STRING, # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, # publicKey [1] BIT STRING OPTIONAL # } private_key = DerSequence().decode(encoded, nr_elements=(3, 4)) if private_key[0] != 1: raise ValueError("Incorrect ECC private key version") try: curve_name = DerObjectId(explicit=0).decode(private_key[2]).value except ValueError: pass if curve_name != _curve.oid: raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_name) scalar_bytes = DerOctetString().decode(private_key[1]).payload order_bytes = _curve.order.size_in_bytes() if len(scalar_bytes) != order_bytes: raise ValueError("Private key is too small") d = Integer.from_bytes(scalar_bytes) # Decode public key (if any, it must be P-256) if len(private_key) == 4: public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value public_key = _import_public_der(curve_name, public_key_enc) point_x = public_key.pointQ.x point_y = public_key.pointQ.y else: point_x = point_y = None return construct(curve="P-256", d=d, point_x=point_x, point_y=point_y)
def testErrDecode2(self): der = DerSequence() # Too much data self.assertRaises(ValueError, der.decode, b('\x30\x00\x00'))
def export_key(self, format='PEM', pkcs8=None, passphrase=None, protection=None, randfunc=None): """Export this DSA key. Args: format (string): The encoding for the output: - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_. - *'DER'*. Binary ASN.1 encoding. - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_. Only suitable for public keys, not for private keys. passphrase (string): *Private keys only*. The pass phrase to protect the output. pkcs8 (boolean): *Private keys only*. If ``True`` (default), the key is encoded with `PKCS#8`_. If ``False``, it is encoded in the custom OpenSSL/OpenSSH container. protection (string): *Only in combination with a pass phrase*. The encryption scheme to use to protect the output. If :data:`pkcs8` takes value ``True``, this is the PKCS#8 algorithm to use for deriving the secret and encrypting the private DSA key. For a complete list of algorithms, see :mod:`crypto.IO.PKCS8`. The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is used. It is based on MD5 for key derivation, and Triple DES for encryption. Parameter :data:`protection` is then ignored. The combination ``format='DER'`` and ``pkcs8=False`` is not allowed if a passphrase is present. randfunc (callable): A function that returns random bytes. By default it is :func:`crypto.Random.get_random_bytes`. Returns: byte string : the encoded key Raises: ValueError : when the format is unknown or when you try to encrypt a private key with *DER* format and OpenSSL/OpenSSH. .. warning:: If you don't provide a pass phrase, the private key will be exported in the clear! .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt """ if passphrase is not None: passphrase = tobytes(passphrase) if randfunc is None: randfunc = Random.get_random_bytes if format == 'OpenSSH': tup1 = [self._key[x].to_bytes() for x in ('p', 'q', 'g', 'y')] def func(x): if (bord(x[0]) & 0x80): return bchr(0) + x else: return x tup2 = [func(x) for x in tup1] keyparts = [b'ssh-dss'] + tup2 keystring = b''.join( [struct.pack(">I", len(kp)) + kp for kp in keyparts]) return b'ssh-dss ' + binascii.b2a_base64(keystring)[:-1] # DER format is always used, even in case of PEM, which simply # encodes it into BASE64. params = DerSequence([self.p, self.q, self.g]) if self.has_private(): if pkcs8 is None: pkcs8 = True if pkcs8: if not protection: protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' private_key = DerInteger(self.x).encode() binary_key = PKCS8.wrap(private_key, oid, passphrase, protection, key_params=params, randfunc=randfunc) if passphrase: key_type = 'ENCRYPTED PRIVATE' else: key_type = 'PRIVATE' passphrase = None else: if format != 'PEM' and passphrase: raise ValueError("DSA private key cannot be encrypted") ints = [0, self.p, self.q, self.g, self.y, self.x] binary_key = DerSequence(ints).encode() key_type = "DSA PRIVATE" else: if pkcs8: raise ValueError("PKCS#8 is only meaningful for private keys") binary_key = _create_subject_public_key_info( oid, DerInteger(self.y), params) key_type = "PUBLIC" if format == 'DER': return binary_key if format == 'PEM': pem_str = PEM.encode(binary_key, key_type + " KEY", passphrase, randfunc) return tobytes(pem_str) raise ValueError( "Unknown key format '%s'. Cannot export the DSA key." % format)
def testDecode9(self): # Verify that decode returns itself der = DerSequence() self.assertEqual(der, der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00')))
def testErrDecode1(self): # Not a sequence der = DerSequence() self.assertRaises(ValueError, der.decode, b('')) self.assertRaises(ValueError, der.decode, b('\x00')) self.assertRaises(ValueError, der.decode, b('\x30'))