def testStrict1(self): number = DerInteger() number.decode(b'\x02\x02\x00\x01') number.decode(b'\x02\x02\x00\x7F') self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x01', strict=True) self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x7F', strict=True)
def testDecode2(self): # Multi-byte integer der = DerInteger() # Value 0x180L der.decode(b('\x02\x02\x01\x80')) self.assertEqual(der.value,0x180) # One very long integer der.decode( 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(der.value,2**2048)
def testDecode3(self): # Negative integer der = DerInteger() # Value -1 der.decode(b('\x02\x01\xFF')) self.assertEqual(der.value, -1) # Value -32768 der.decode(b('\x02\x02\x80\x00')) self.assertEqual(der.value, -32768)
def testEncode1(self): # Single-byte integers # Value 0 der = DerInteger(0) self.assertEqual(der.encode(), b('\x02\x01\x00')) # Value 1 der = DerInteger(1) self.assertEqual(der.encode(), b('\x02\x01\x01')) # Value 127 der = DerInteger(127) self.assertEqual(der.encode(), b('\x02\x01\x7F'))
def testEncode3(self): # Negative integers # Value -1 der = DerInteger(-1) self.assertEqual(der.encode(), b('\x02\x01\xFF')) # Value -128 der = DerInteger(-128) self.assertEqual(der.encode(), b('\x02\x01\x80')) # Value der = DerInteger(-87873) self.assertEqual(der.encode(), b('\x02\x03\xFE\xA8\xBF'))
def _extract_sp_info(x509_certificate): """Extract subjectPublicKeyInfo from a DER X.509 certificate.""" from Crypto.Util.asn1 import DerSequence, DerInteger try: # This code will partially parse tbsCertificate # to get to subjectPublicKeyInfo. # # However, the first 2 elements of tbsCertificate are: # # version [0] Version DEFAULT v1, # serialNumber CertificateSerialNumber, # # where: # # Version ::= INTEGER { v1(0), v2(1), v3(2) } # CertificateSerialNumber ::= INTEGER # # In order to know the position of subjectPublicKeyInfo # in the tbsCertificate SEQUENCE, we try to see if the # first element is an untagged INTEGER (that is, the # certificate serial number). x509_tbs_cert = DerSequence() x509_tbs_cert.decode(x509_certificate[0]) index = -1 # Sentinel try: _ = x509_tbs_cert[0] + 1 # Still here? There was no version then index = 5 except TypeError: # Landed here? Version was there x509_version = DerInteger(explicit=0) x509_version.decode(x509_tbs_cert[0]) index = 6 if index in (5, 6): return x509_tbs_cert[index] except (TypeError, IndexError, ValueError, EOFError): pass raise ValueError("Cannot extract subjectPublicKeyInfo")
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 testDecode1(self): # Single-byte integer der = DerInteger() # Value 0 der.decode(b('\x02\x01\x00')) self.assertEquals(der.value, 0) # Value 1 der.decode(b('\x02\x01\x01')) self.assertEquals(der.value, 1) # Value 127 der.decode(b('\x02\x01\x7F')) self.assertEquals(der.value, 127)
def testDecode5(self): # We still accept BER integer format der = DerInteger() # Redundant leading zeroes der.decode(b('\x02\x02\x00\x01')) self.assertEquals(der.value, 1) # Redundant leading 0xFF der.decode(b('\x02\x02\xFF\xFF')) self.assertEquals(der.value, -1) # Empty payload der.decode(b('\x02\x00')) self.assertEquals(der.value, 0)
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 testDecode2(self): # Multi-byte integer der = DerInteger() # Value 0x180L der.decode(b('\x02\x02\x01\x80')) self.assertEquals(der.value, 0x180L) # One very long integer der.decode( 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.assertEquals(der.value, 2L**2048)
def testEncode2(self): # Multi-byte integers # Value 128 der = DerInteger(128) self.assertEqual(der.encode(), b('\x02\x02\x00\x80')) # Value 0x180 der = DerInteger(0x180) self.assertEqual(der.encode(), b('\x02\x02\x01\x80')) # One very long integer der = DerInteger(2**2048) self.assertEqual(der.encode(), 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 testDecode5(self): # We still accept BER integer format der = DerInteger() # Redundant leading zeroes der.decode(b('\x02\x02\x00\x01')) self.assertEqual(der.value, 1) # Redundant leading 0xFF der.decode(b('\x02\x02\xFF\xFF')) self.assertEqual(der.value, -1) # Empty payload der.decode(b('\x02\x00')) self.assertEqual(der.value, 0)
def testDecode1(self): # Single-byte integer der = DerInteger() # Value 0 der.decode(b('\x02\x01\x00')) self.assertEqual(der.value, 0) # Value 1 der.decode(b('\x02\x01\x01')) self.assertEqual(der.value, 1) # Value 127 der.decode(b('\x02\x01\x7F')) self.assertEqual(der.value, 127)
def testDecode3(self): # Negative integer der = DerInteger() # Value -1 der.decode(b('\x02\x01\xFF')) self.assertEquals(der.value, -1) # Value -32768 der.decode(b('\x02\x02\x80\x00')) self.assertEquals(der.value, -32768)
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=list(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 testInit1(self): der = newDerSetOf(DerInteger(1), DerInteger(2)) self.assertEqual(der.encode(), b('1\x06\x02\x01\x01\x02\x01\x02'))
def testInit1(self): der = DerInteger(1) self.assertEqual(der.encode(), b('\x02\x01\x01'))
def testEncode4(self): # Explicit encoding number = DerInteger(0x34, explicit=3) self.assertEquals(number.encode(), b('\xa3\x03\x02\x01\x34'))
def testInit1(self): der = newDerSequence(1, DerInteger(2), '0\x00') self.assertEqual(der.encode(), b('0\x08\x02\x01\x01\x02\x01\x020\x00'))
def exportKey(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 = list(map(func, 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 testInit2(self): der = DerBitString(DerInteger(1)) self.assertEquals(der.encode(), b('\x03\x04\x00\x02\x01\x01'))
def testErrDecode1(self): # Wide length field der = DerInteger() self.assertRaises(ValueError, der.decode, b('\x02\x81\x01\x01'))
def testDecode6(self): # Explicit encoding number = DerInteger(explicit=3) number.decode(b('\xa3\x03\x02\x01\x34')) self.assertEquals(number.value, 0x34)
def testEncode4(self): # Explicit encoding number = DerInteger(0x34, explicit=3) self.assertEqual(number.encode(), b('\xa3\x03\x02\x01\x34'))
def testDecode7(self): # Verify decode returns the DerInteger der = DerInteger() self.assertEquals(der, der.decode(b('\x02\x01\x7F')))
def exportKey(self, format='PEM', pkcs8=None, passphrase=None, protection=None, randfunc=None): """Export this DSA key. :Parameters: format : string The format to use for wrapping the key: - *'DER'*. Binary encoding. - *'PEM'*. Textual encoding, done according to `RFC1421`_/ `RFC1423`_ (default). - *'OpenSSH'*. Textual encoding, one line of text, see `RFC4253`_. Only suitable for public keys, not private keys. passphrase : string For private keys only. The pass phrase to use for deriving the encryption key. pkcs8 : boolean For private keys only. If ``True`` (default), the key is arranged according to `PKCS#8`_ and if `False`, according to the custom OpenSSL/OpenSSH encoding. protection : string The encryption scheme to use for protecting the private key. It is only meaningful when a pass phrase is present too. If ``pkcs8`` takes value ``True``, ``protection`` is the PKCS#8 algorithm to use for deriving the secret and encrypting the private DSA key. For a complete list of algorithms, see `Crypto.IO.PKCS8`. The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. If ``pkcs8`` is ``False``, the obsolete PEM encryption scheme is used. It is based on MD5 for key derivation, and Triple DES for encryption. Parameter ``protection`` is 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 `Crypto.Random.get_random_bytes`. :Return: A byte string with the encoded public or private half of the key. :Raise ValueError: When the format is unknown or when you try to encrypt a private key with *DER* format and OpenSSL/OpenSSH. :attention: 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 = map(func, 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 = newDerSequence(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 = newDerSequence(*ints).encode() key_type = "DSA PRIVATE" else: if pkcs8: raise ValueError("PKCS#8 is only meaningful for private keys") binary_key = newDerSequence( newDerSequence(DerObjectId(oid), params), newDerBitString(DerInteger(self.y)) ).encode() key_type = "DSA 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 testInit1(self): der = DerSequence([1, DerInteger(2), b('0\x00')]) self.assertEquals(der.encode(), b('0\x08\x02\x01\x01\x02\x01\x020\x00'))
def test_int_encoder_big_test(self): for i in range(1000): k = random.randint(0, 1000**1000) corr_ans = str(hexlify(DerInteger(k).encode()))[2:][:-1] imp_ans = main.encode_integer_tlv(k) self.assertEqual(corr_ans, imp_ans)
def testInit1(self): der = DerSetOf([DerInteger(1), DerInteger(2)]) self.assertEquals(der.encode(), b('1\x06\x02\x01\x01\x02\x01\x02'))
def testDecode7(self): # Verify decode returns the DerInteger der = DerInteger() self.assertEqual(der, der.decode(b('\x02\x01\x7F')))
def testInit1(self): der = DerInteger(1) self.assertEquals(der.encode(), b('\x02\x01\x01'))
def exportKey(self, format='PEM', pkcs8=None, passphrase=None, protection=None): if passphrase is not None: passphrase = tobytes(passphrase) if format == 'OpenSSH': tup1 = [long_to_bytes(x) for x in (self.p, self.q, self.g, self.y)] def func(x): if bord(x[0]) & 128: return bchr(0) + x else: return x tup2 = map(func, 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] else: params = newDerSequence(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=self._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 = newDerSequence(*ints).encode() key_type = 'DSA PRIVATE' else: if pkcs8: raise ValueError( 'PKCS#8 is only meaningful for private keys') binary_key = newDerSequence( newDerSequence(DerObjectId(oid), params), newDerBitString(DerInteger(self.y))).encode() key_type = 'DSA PUBLIC' if format == 'DER': return binary_key if format == 'PEM': pem_str = PEM.encode(binary_key, key_type + ' KEY', passphrase, self._randfunc) return tobytes(pem_str) raise ValueError( "Unknown key format '%s'. Cannot export the DSA key." % format) return
def encrypt(data, passphrase, protection, prot_params=None, randfunc=None): """Encrypt a piece of data using a passphrase and *PBES2*. :Parameters: data : byte string The piece of data to encrypt. passphrase : byte string The passphrase to use for encrypting the data. protection : string The identifier of the encryption algorithm to use. The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. prot_params : dictionary Parameters of the protection algorithm. +------------------+-----------------------------------------------+ | Key | Description | +==================+===============================================+ | iteration_count | The KDF algorithm is repeated several times to| | | slow down brute force attacks on passwords | | | (called *N* or CPU/memory cost in scrypt). | | | | | | The default value for PBKDF2 is 1 000. | | | The default value for scrypt is 16 384. | +------------------+-----------------------------------------------+ | salt_size | Salt is used to thwart dictionary and rainbow | | | attacks on passwords. The default value is 8 | | | bytes. | +------------------+-----------------------------------------------+ | block_size | *(scrypt only)* Memory-cost (r). The default | | | value is 8. | +------------------+-----------------------------------------------+ | parallelization | *(scrypt only)* CPU-cost (p). The default | | | value is 1. | +------------------+-----------------------------------------------+ randfunc : callable Random number generation function; it should accept a single integer N and return a string of random data, N bytes long. If not specified, a new RNG will be instantiated from ``Crypto.Random``. :Returns: The encrypted data, as a binary string. """ if prot_params is None: prot_params = {} if randfunc is None: randfunc = Random.new().read if protection == 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC': key_size = 24 module = DES3 cipher_mode = DES3.MODE_CBC enc_oid = "1.2.840.113549.3.7" elif protection in ('PBKDF2WithHMAC-SHA1AndAES128-CBC', 'scryptAndAES128-CBC'): key_size = 16 module = AES cipher_mode = AES.MODE_CBC enc_oid = "2.16.840.1.101.3.4.1.2" elif protection in ('PBKDF2WithHMAC-SHA1AndAES192-CBC', 'scryptAndAES192-CBC'): key_size = 24 module = AES cipher_mode = AES.MODE_CBC enc_oid = "2.16.840.1.101.3.4.1.22" elif protection in ('PBKDF2WithHMAC-SHA1AndAES256-CBC', 'scryptAndAES256-CBC'): key_size = 32 module = AES cipher_mode = AES.MODE_CBC enc_oid = "2.16.840.1.101.3.4.1.42" else: raise ValueError("Unknown mode") # Get random data iv = randfunc(module.block_size) salt = randfunc(prot_params.get("salt_size", 8)) # Derive key from password if protection.startswith('PBKDF2'): count = prot_params.get("iteration_count", 1000) key = PBKDF2(passphrase, salt, key_size, count) key_derivation_func = newDerSequence( DerObjectId("1.2.840.113549.1.5.12"), # PBKDF2 newDerSequence(DerOctetString(salt), DerInteger(count))) else: # It must be scrypt count = prot_params.get("iteration_count", 16384) scrypt_r = prot_params.get('block_size', 8) scrypt_p = prot_params.get('parallelization', 1) key = scrypt(passphrase, salt, key_size, count, scrypt_r, scrypt_p) key_derivation_func = newDerSequence( DerObjectId("1.3.6.1.4.1.11591.4.11"), # scrypt newDerSequence(DerOctetString(salt), DerInteger(count), DerInteger(scrypt_r), DerInteger(scrypt_p))) # Create cipher and use it cipher = module.new(key, cipher_mode, iv) encrypted_data = cipher.encrypt(pad(data, cipher.block_size)) encryption_scheme = newDerSequence(DerObjectId(enc_oid), DerOctetString(iv)) # Result encrypted_private_key_info = newDerSequence( # encryptionAlgorithm newDerSequence( DerObjectId("1.2.840.113549.1.5.13"), # PBES2 newDerSequence(key_derivation_func, encryption_scheme), ), DerOctetString(encrypted_data)) return encrypted_private_key_info.encode()
def testDecode6(self): # Explicit encoding number = DerInteger(explicit=3) number.decode(b('\xa3\x03\x02\x01\x34')) self.assertEqual(number.value, 0x34)
def _importKeyDER(key_data, passphrase, params): """Import a DSA key (public or private half), encoded in DER form.""" try: # # Dss-Parms ::= SEQUENCE { # p OCTET STRING, # q OCTET STRING, # g OCTET STRING # } # # Try a simple private key first if params: x = DerInteger().decode(key_data).value p, q, g = list(DerSequence().decode(params)) # Dss-Parms tup = (pow(g, x, p), g, p, q, x) return construct(tup) der = DerSequence().decode(key_data) # Try OpenSSL format for private keys if len(der) == 6 and der.hasOnlyInts() and der[0] == 0: tup = [der[comp] for comp in (4, 3, 1, 2, 5)] return construct(tup) # Try SubjectPublicKeyInfo if len(der) == 2: try: algo = DerSequence().decode(der[0]) algo_oid = DerObjectId().decode(algo[0]).value params = DerSequence().decode(algo[1]) # Dss-Parms if algo_oid == oid and len(params) == 3 and\ params.hasOnlyInts(): bitmap = DerBitString().decode(der[1]) pub_key = DerInteger().decode(bitmap.value) tup = [pub_key.value] tup += [params[comp] for comp in (2, 0, 1)] return construct(tup) except (ValueError, EOFError): pass # Try to see if this is an X.509 DER certificate # (Certificate ASN.1 type) if len(der) == 3: from Crypto.PublicKey import _extract_sp_info try: sp_info = _extract_sp_info(der) return _importKeyDER(sp_info, passphrase, None) except ValueError: pass # Try unencrypted PKCS#8 p8_pair = PKCS8.unwrap(key_data, passphrase) if p8_pair[0] == oid: return _importKeyDER(p8_pair[1], passphrase, p8_pair[2]) except (ValueError, EOFError): pass raise ValueError("DSA key format is not supported")
def test_int_encoder_liveq(self): k = 141200904527031427693111569572085332763291092089246046288015799505524112848666951727490655634310664507006287247690643568683363763333057271478359004846665350192723231859612961899401338906920115912147935812300211873100787356909246033420333758668256600284274201300130421437978238102757977633689474423065331072603 corr_ans = str(hexlify(DerInteger(k).encode()))[2:][:-1] print("\n\n" + main.encode_integer_tlv(k) + "\n\n") self.assertEqual(corr_ans, main.encode_integer_tlv(k))