def test_unaligned_data_64(self): plaintexts = [b("7777777")] * 100 cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) ciphertexts = [cipher.encrypt(x) for x in plaintexts] cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) self.assertEqual( b("").join(ciphertexts), cipher.encrypt(b("").join(plaintexts))) cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) ciphertexts = [cipher.encrypt(x) for x in plaintexts] cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) self.assertEqual( b("").join(ciphertexts), cipher.encrypt(b("").join(plaintexts)))
def test_des3(self): # The following test vectors have been generated with gpg v1.4.0. # The command line used was: # gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \ # --disable-mdc --s2k-mode 0 --output ct pt # For an explanation, see test_AES.py . plaintext = 'ac1762037074324fb53ba3596f73656d69746556616c6c6579' ciphertext = '9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d' key = '7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2' iv = 'cd47e2afb8b7e4b0' encrypted_iv = '6a7eef0b58050e8b904a' plaintext = unhexlify(plaintext) ciphertext = unhexlify(ciphertext) key = unhexlify(key) iv = unhexlify(iv) encrypted_iv = unhexlify(encrypted_iv) cipher = DES3.new(key, DES3.MODE_OPENPGP, iv) ct = cipher.encrypt(plaintext) self.assertEqual(ct[:10], encrypted_iv) self.assertEqual(ct[10:], ciphertext) cipher = DES3.new(key, DES3.MODE_OPENPGP, encrypted_iv) pt = cipher.decrypt(ciphertext) self.assertEqual(pt, plaintext)
def test_loopback_64(self): cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) pt = get_tag_random("plaintext", 8 * 100) ct = cipher.encrypt(pt) cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) pt2 = cipher.decrypt(ct) self.assertEqual(pt, pt2)
def test_unaligned_data_64(self): cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) for wrong_length in range(1,8): self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) for wrong_length in range(1,8): self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length)
def test_loopback_64(self): cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) pt = get_tag_random("plaintext", 8 * 100) ct = cipher.encrypt(pt) cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) pt2 = cipher.decrypt(ct) self.assertEqual(pt, pt2)
def test_loopback_64(self): cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) pt = get_tag_random("plaintext", 8 * 100) ct = cipher.encrypt(pt) cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) pt2 = cipher.decrypt(ct) self.assertEqual(pt, pt2)
def test_loopback_64(self): cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) pt = get_tag_random("plaintext", 8 * 100) ct = cipher.encrypt(pt) eiv, ct = ct[:10], ct[10:] cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, eiv) pt2 = cipher.decrypt(ct) self.assertEqual(pt, pt2)
def test_unaligned_data_64(self): plaintexts = [b("7777777")] * 100 cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) ciphertexts = [cipher.encrypt(x) for x in plaintexts] cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) self.assertEqual( b("").join(ciphertexts), cipher.encrypt(b("").join(plaintexts))) cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) ciphertexts = [cipher.encrypt(x) for x in plaintexts] cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) self.assertEqual( b("").join(ciphertexts), cipher.encrypt(b("").join(plaintexts)))
def _do_tdes_test(self, file_name): test_vectors = load_tests(("Crypto", "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 isinstance(tv, str): 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 test_nonce_attribute(self): # Nonce attribute is the prefix passed to Counter (DES3) cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) self.assertEqual(cipher.nonce, self.nonce_32) # Nonce attribute is the prefix passed to Counter (AES) cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) self.assertEqual(cipher.nonce, self.nonce_64) # Nonce attribute is not defined if suffix is used in Counter counter = Counter.new(64, prefix=self.nonce_32, suffix=self.nonce_32) cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) self.assertFalse(hasattr(cipher, "nonce"))
def test_segment_size_64(self): for bits in range(8, 65, 8): cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=bits) for bits in 0, 7, 9, 63, 65: self.assertRaises(ValueError, DES3.new, self.key_192, AES.MODE_CFB, self.iv_64, segment_size=bits)
def encode(data, marker, passphrase=None, randfunc=None): """Encode a piece of binary data into PEM format. Args: data (byte string): The piece of binary data to encode. marker (string): The marker for the PEM block (e.g. "PUBLIC KEY"). Note that there is no official master list for all allowed markers. Still, you can refer to the OpenSSL_ source code. passphrase (byte string): If given, the PEM block will be encrypted. The key is derived from the passphrase. randfunc (callable): Random number generation function; it accepts an integer N and returns a byte string of random data, N bytes long. If not given, a new one is instantiated. Returns: The PEM block, as a string. .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h """ if randfunc is None: randfunc = get_random_bytes out = "-----BEGIN %s-----\n" % marker if passphrase: # We only support 3DES for encryption salt = randfunc(8) key = PBKDF1(passphrase, salt, 16, 1, MD5) key += PBKDF1(key + passphrase, salt, 8, 1, MD5) objenc = DES3.new(key, DES3.MODE_CBC, salt) out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\ tostr(hexlify(salt).upper()) # Encrypt with PKCS#7 padding data = objenc.encrypt(pad(data, objenc.block_size)) elif passphrase is not None: raise ValueError("Empty password") # Each BASE64 line can take up to 64 characters (=48 bytes of data) # b2a_base64 adds a new line character! chunks = [ tostr(b2a_base64(data[i:i + 48])) for i in range(0, len(data), 48) ] out += "".join(chunks) out += "-----END %s-----" % marker return out
def decode(pem_data, passphrase=None): """Decode a PEM block into binary. Args: pem_data (string): The PEM block. passphrase (byte string): If given and the PEM block is encrypted, the key will be derived from the passphrase. Returns: A tuple with the binary data, the marker string, and a boolean to indicate if decryption was performed. Raises: ValueError: if decoding fails, if the PEM file is encrypted and no passphrase has been provided or if the passphrase is incorrect. """ # Verify Pre-Encapsulation Boundary r = re.compile("\s*-----BEGIN (.*)-----\s+") m = r.match(pem_data) if not m: raise ValueError("Not a valid PEM pre boundary") marker = m.group(1) # Verify Post-Encapsulation Boundary r = re.compile("-----END (.*)-----\s*$") m = r.search(pem_data) if not m or m.group(1) != marker: raise ValueError("Not a valid PEM post boundary") # Removes spaces and slit on lines lines = pem_data.replace(" ", '').split() # Decrypts, if necessary if lines[1].startswith('Proc-Type:4,ENCRYPTED'): if not passphrase: raise ValueError("PEM is encrypted, but no passphrase available") DEK = lines[2].split(':') if len(DEK) != 2 or DEK[0] != 'DEK-Info': raise ValueError("PEM encryption format not supported.") algo, salt = DEK[1].split(',') salt = unhexlify(tobytes(salt)) if algo == "DES-CBC": # This is EVP_BytesToKey in OpenSSL key = PBKDF1(passphrase, salt, 8, 1, MD5) objdec = DES.new(key, DES.MODE_CBC, salt) elif algo == "DES-EDE3-CBC": # Note that EVP_BytesToKey is note exactly the same as PBKDF1 key = PBKDF1(passphrase, salt, 16, 1, MD5) key += PBKDF1(key + passphrase, salt, 8, 1, MD5) objdec = DES3.new(key, DES3.MODE_CBC, salt) elif algo == "AES-128-CBC": key = PBKDF1(passphrase, salt[:8], 16, 1, MD5) objdec = AES.new(key, AES.MODE_CBC, salt) else: raise ValueError("Unsupport PEM encryption algorithm (%s)." % algo) lines = lines[2:] else: objdec = None # Decode body data = a2b_base64(b(''.join(lines[1:-1]))) enc_flag = False if objdec: data = unpad(objdec.decrypt(data), objdec.block_size) enc_flag = True return (data, marker, enc_flag)
def test_block_size_64(self): cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) self.assertEqual(cipher.block_size, DES3.block_size)
def test_block_size_64(self): cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) self.assertEqual(cipher.block_size, DES3.block_size)
def test_block_size_64(self): cipher = DES3.new(self.key_192, AES.MODE_EAX, nonce=self.nonce_96) self.assertEqual(cipher.block_size, DES3.block_size)