def _do_mct_aes_test(self, file_name): test_vectors = load_test_vectors(("Cipher", "AES"), file_name, "AES CBC Montecarlo", {"count": lambda x: int(x)}) if test_vectors is None: return direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc cipher = AES.new(tv.key, self.aes_mode, tv.iv) if direction == '[ENCRYPT]': cts = [tv.iv] for count in range(1000): cts.append(cipher.encrypt(tv.plaintext)) tv.plaintext = cts[-2] self.assertEqual(cts[-1], tv.ciphertext) elif direction == '[DECRYPT]': pts = [tv.iv] for count in range(1000): pts.append(cipher.decrypt(tv.ciphertext)) tv.ciphertext = pts[-2] self.assertEqual(pts[-1], tv.plaintext) else: assert False
def _do_tdes_test(self, file_name): test_vectors = load_test_vectors(("Cipher", "TDES"), file_name, "TDES CBC KAT", {"count": lambda x: int(x)}) if test_vectors is None: return direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc if hasattr(tv, "keys"): cipher = DES.new(tv.keys, self.des_mode, tv.iv) else: if tv.key1 != tv.key3: key = tv.key1 + tv.key2 + tv.key3 # Option 3 else: key = tv.key1 + tv.key2 # Option 2 cipher = DES3.new(key, self.des3_mode, tv.iv) if direction == "[ENCRYPT]": self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) elif direction == "[DECRYPT]": self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) else: assert False
def _do_mct_aes_test(self, file_name): test_vectors = load_tests(("Cryptodome", "SelfTest", "Cipher", "test_vectors", "AES"), file_name, "AES Montecarlo", { "count" : lambda x: int(x) } ) assert(test_vectors) direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc cipher = AES.new(tv.key, self.aes_mode, tv.iv) if direction == '[ENCRYPT]': cts = [ tv.iv ] for count in range(1000): cts.append(cipher.encrypt(tv.plaintext)) tv.plaintext = cts[-2] self.assertEqual(cts[-1], tv.ciphertext) elif direction == '[DECRYPT]': pts = [ tv.iv] for count in range(1000): pts.append(cipher.decrypt(tv.ciphertext)) tv.ciphertext = pts[-2] self.assertEqual(pts[-1], tv.plaintext) else: assert False
def _do_kat_aes_test(self, file_name): test_vectors = load_test_vectors(("Cipher", "AES"), file_name, "AES CBC KAT", {"count": lambda x: int(x)}) if test_vectors is None: return direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc cipher = AES.new(tv.key, self.aes_mode, tv.iv) if direction == "[ENCRYPT]": self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) elif direction == "[DECRYPT]": self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) else: assert False
def _do_tdes_test(self, file_name): test_vectors = load_tests(("Cryptodome", "SelfTest", "Cipher", "test_vectors", "TDES"), file_name, "TDES CBC KAT", { "count" : lambda x: int(x) } ) assert(test_vectors) direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc if hasattr(tv, "keys"): cipher = DES.new(tv.keys, self.des_mode, tv.iv) else: if tv.key1 != tv.key3: key = tv.key1 + tv.key2 + tv.key3 # Option 3 else: key = tv.key1 + tv.key2 # Option 2 cipher = DES3.new(key, self.des3_mode, tv.iv) if direction == "[ENCRYPT]": self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) elif direction == "[DECRYPT]": self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) else: assert False
def _do_kat_aes_test(self, file_name, segment_size): test_vectors = load_tests( ("Cryptodome", "SelfTest", "Cipher", "test_vectors", "AES"), file_name, "AES CFB%d KAT" % segment_size, {"count": lambda x: int(x)}) assert (test_vectors) direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv, segment_size=segment_size) if direction == "[ENCRYPT]": self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) elif direction == "[DECRYPT]": self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) else: assert False
def _do_mct_aes_test(self, file_name, segment_size): test_vectors = load_test_vectors(("Cipher", "AES"), file_name, "AES CFB%d Montecarlo" % segment_size, { "count" : lambda x: int(x) } ) if test_vectors is None: return assert(segment_size in (8, 128)) direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv, segment_size=segment_size) def get_input(input_text, output_seq, j): # CFB128 if segment_size == 128: if j >= 2: return output_seq[-2] return [input_text, tv.iv][j] # CFB8 if j == 0: return input_text elif j <= 16: return tv.iv[j - 1:j] return output_seq[j - 17] if direction == '[ENCRYPT]': cts = [] for j in range(1000): plaintext = get_input(tv.plaintext, cts, j) cts.append(cipher.encrypt(plaintext)) self.assertEqual(cts[-1], tv.ciphertext) elif direction == '[DECRYPT]': pts = [] for j in range(1000): ciphertext = get_input(tv.ciphertext, pts, j) pts.append(cipher.decrypt(ciphertext)) self.assertEqual(pts[-1], tv.plaintext) else: assert False
def _do_mct_aes_test(self, file_name, segment_size): test_vectors = load_tests(("Cryptodome", "SelfTest", "Cipher", "test_vectors", "AES"), file_name, "AES CFB%d Montecarlo" % segment_size, { "count" : lambda x: int(x) } ) assert(test_vectors) assert(segment_size in (8, 128)) direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv, segment_size=segment_size) def get_input(input_text, output_seq, j): # CFB128 if segment_size == 128: if j >= 2: return output_seq[-2] return [input_text, tv.iv][j] # CFB8 if j == 0: return input_text elif j <= 16: return tv.iv[j - 1:j] return output_seq[j - 17] if direction == '[ENCRYPT]': cts = [] for j in range(1000): plaintext = get_input(tv.plaintext, cts, j) cts.append(cipher.encrypt(plaintext)) self.assertEqual(cts[-1], tv.ciphertext) elif direction == '[DECRYPT]': pts = [] for j in range(1000): ciphertext = get_input(tv.ciphertext, pts, j) pts.append(cipher.decrypt(ciphertext)) self.assertEqual(pts[-1], tv.plaintext) else: assert False
def _do_kat_aes_test(self, file_name): test_vectors = load_tests(("Cryptodome", "SelfTest", "Cipher", "test_vectors", "AES"), file_name, "AES KAT", { "count" : lambda x: int(x) } ) assert(test_vectors) direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc cipher = AES.new(tv.key, self.aes_mode, tv.iv) if direction == "[ENCRYPT]": self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) elif direction == "[DECRYPT]": self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) else: assert False
def _do_tdes_test(self, file_name, segment_size): test_vectors = load_tests( ("Cryptodome", "SelfTest", "Cipher", "test_vectors", "TDES"), file_name, "AES CFB%d KAT" % segment_size, {"count": lambda x: int(x)}) assert (test_vectors) direction = None for tv in test_vectors: # The test vector file contains some directive lines if is_string(tv): direction = tv continue self.description = tv.desc if hasattr(tv, "keys"): cipher = DES.new(tv.keys, DES.MODE_CFB, tv.iv, segment_size=segment_size) else: if tv.key1 != tv.key3: key = tv.key1 + tv.key2 + tv.key3 # Option 3 else: key = tv.key1 + tv.key2 # Option 2 cipher = DES3.new(key, DES3.MODE_CFB, tv.iv, segment_size=segment_size) if direction == "[ENCRYPT]": self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) elif direction == "[DECRYPT]": self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) else: assert False
def export_key(self, **kwargs): """Export this ECC key. Args: format (string): The format to use for encoding the key: - *'DER'*. The key will be encoded in ASN.1 DER format (binary). For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure defined in `RFC5480`_ will be used. For a private key, the ASN.1 ``ECPrivateKey`` structure defined in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope, see the ``use_pkcs8`` flag below). - *'PEM'*. The key will be encoded in a PEM_ envelope (ASCII). - *'OpenSSH'*. The key will be encoded in the OpenSSH_ format (ASCII, public keys only). passphrase (byte string or string): The passphrase to use for protecting the private key. use_pkcs8 (boolean): If ``True`` (default and recommended), the `PKCS#8`_ representation will be used. If ``False``, the much weaker `PEM encryption`_ mechanism will be used. protection (string): When a private key is exported with password-protection and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be present and be a valid algorithm supported by :mod:`Cryptodome.IO.PKCS8`. It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``. compress (boolean): If ``True``, a more compact representation of the public key (X-coordinate only) is used. If ``False`` (default), the full public key (in both its coordinates) will be exported. .. warning:: If you don't provide a passphrase, the private key will be exported in the clear! .. note:: When exporting a private key with password-protection and `PKCS#8`_ (both ``DER`` and ``PEM`` formats), any extra parameters is passed to :mod:`Cryptodome.IO.PKCS8`. .. _PEM: http://www.ietf.org/rfc/rfc1421.txt .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt .. _RFC5480: https://tools.ietf.org/html/rfc5480 .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt Returns: A multi-line string (for PEM and OpenSSH) or bytes (for DER) with the encoded key. """ args = kwargs.copy() ext_format = args.pop("format") if ext_format not in ("PEM", "DER", "OpenSSH"): raise ValueError("Unknown format '%s'" % ext_format) compress = args.pop("compress", False) if self.has_private(): passphrase = args.pop("passphrase", None) if is_string(passphrase): passphrase = tobytes(passphrase) if not passphrase: raise ValueError("Empty passphrase") use_pkcs8 = args.pop("use_pkcs8", True) if ext_format == "PEM": if use_pkcs8: if passphrase: return self._export_private_encrypted_pkcs8_in_clear_pem( passphrase, **args) else: return self._export_private_clear_pkcs8_in_clear_pem() else: return self._export_private_pem(passphrase, **args) elif ext_format == "DER": # DER if passphrase and not use_pkcs8: raise ValueError( "Private keys can only be encrpyted with DER using PKCS#8" ) if use_pkcs8: return self._export_pkcs8(passphrase=passphrase, **args) else: return self._export_private_der() else: raise ValueError( "Private keys cannot be exported in OpenSSH format") else: # Public key if args: raise ValueError("Unexpected parameters: '%s'" % args) if ext_format == "PEM": return self._export_public_pem(compress) elif ext_format == "DER": return self._export_subjectPublicKeyInfo(compress) else: return self._export_openssh(compress)
def export_key(self, **kwargs): """Export this ECC key. Args: format (string): The format to use for encoding the key: - *'DER'*. The key will be encoded in ASN.1 DER format (binary). For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure defined in `RFC5480`_ will be used. For a private key, the ASN.1 ``ECPrivateKey`` structure defined in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope, see the ``use_pkcs8`` flag below). - *'PEM'*. The key will be encoded in a PEM_ envelope (ASCII). - *'OpenSSH'*. The key will be encoded in the OpenSSH_ format (ASCII, public keys only). passphrase (byte string or string): The passphrase to use for protecting the private key. use_pkcs8 (boolean): If ``True`` (default and recommended), the `PKCS#8`_ representation will be used. If ``False``, the much weaker `PEM encryption`_ mechanism will be used. protection (string): When a private key is exported with password-protection and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be present and be a valid algorithm supported by :mod:`Cryptodome.IO.PKCS8`. It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``. compress (boolean): If ``True``, a more compact representation of the public key (X-coordinate only) is used. If ``False`` (default), the full public key (in both its coordinates) will be exported. .. warning:: If you don't provide a passphrase, the private key will be exported in the clear! .. note:: When exporting a private key with password-protection and `PKCS#8`_ (both ``DER`` and ``PEM`` formats), any extra parameters is passed to :mod:`Cryptodome.IO.PKCS8`. .. _PEM: http://www.ietf.org/rfc/rfc1421.txt .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt .. _RFC5480: https://tools.ietf.org/html/rfc5480 .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt Returns: A multi-line string (for PEM and OpenSSH) or bytes (for DER) with the encoded key. """ args = kwargs.copy() ext_format = args.pop("format") if ext_format not in ("PEM", "DER", "OpenSSH"): raise ValueError("Unknown format '%s'" % ext_format) compress = args.pop("compress", False) if self.has_private(): passphrase = args.pop("passphrase", None) if is_string(passphrase): passphrase = tobytes(passphrase) if not passphrase: raise ValueError("Empty passphrase") use_pkcs8 = args.pop("use_pkcs8", True) if ext_format == "PEM": if use_pkcs8: if passphrase: return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args) else: return self._export_private_clear_pkcs8_in_clear_pem() else: return self._export_private_pem(passphrase, **args) elif ext_format == "DER": # DER if passphrase and not use_pkcs8: raise ValueError("Private keys can only be encrpyted with DER using PKCS#8") if use_pkcs8: return self._export_pkcs8(passphrase=passphrase, **args) else: return self._export_private_der() else: raise ValueError("Private keys cannot be exported in OpenSSH format") else: # Public key if args: raise ValueError("Unexpected parameters: '%s'" % args) if ext_format == "PEM": return self._export_public_pem(compress) elif ext_format == "DER": return self._export_subjectPublicKeyInfo(compress) else: return self._export_openssh(compress)