def test_round_trip(self): pt = b("A") * 1024 c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) ct = c1.encrypt(pt) self.assertEqual(c2.decrypt(ct), pt) self.assertEqual(c1.encrypt(b("")), b("")) self.assertEqual(c2.decrypt(b("")), b(""))
def _update(self, assoc_data_pt=b("")): """Update the MAC with associated data or plaintext (without FSM checks)""" if self._mac_status == MacStatus.NOT_STARTED: self._cache.append(assoc_data_pt) return assert(byte_string(self._cache)) assert(len(self._cache) < self.block_size) if len(self._cache) > 0: filler = min(self.block_size - len(self._cache), len(assoc_data_pt)) self._cache += assoc_data_pt[:filler] assoc_data_pt = assoc_data_pt[filler:] if len(self._cache) < self.block_size: return # The cache is exactly one block self._t = self._mac.encrypt(self._cache) self._cache = b("") update_len = len(assoc_data_pt) // self.block_size * self.block_size self._cache = assoc_data_pt[update_len:] if update_len > 0: self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:]
def test_iv_with_matching_length(self): self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, b("")) self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, self.iv_128[:15]) self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, self.iv_128 + b("0"))
def import_key(encoded, passphrase=None): """Import an ECC key (public or private). :Parameters: encoded : bytes or a (multi-line) string The ECC key to import. An ECC public key can be: - An X.509 certificate, binary (DER) or ASCII (PEM) - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM) - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) An ECC private key can be: - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_) - In ASCII format (PEM or OpenSSH) Private keys can be in the clear or password-protected. For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. :Keywords: passphrase : byte string The passphrase to use for decrypting a private key. Encryption may be applied protected at the PEM level or at the PKCS#8 level. This parameter is ignored if the key in input is not encrypted. :Return: An ECC key object (`EccKey`) :Raise ValueError: When the given key cannot be parsed (possibly because the pass phrase is wrong). .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt """ encoded = tobytes(encoded) if passphrase is not None: passphrase = tobytes(passphrase) # PEM if encoded.startswith(b('-----')): der_encoded, marker, enc_flag = PEM.decode(tostr(encoded), passphrase) if enc_flag: passphrase = None return _import_der(der_encoded, passphrase) # OpenSSH if encoded.startswith(b('ecdsa-sha2-')): return _import_openssh(encoded) # DER if bord(encoded[0]) == 0x30: return _import_der(encoded, passphrase) raise ValueError("ECC key format is not supported")
def test_nonce_parameter(self): # Nonce parameter becomes nonce attribute cipher1 = AES.new(self.key_128, AES.MODE_CTR, nonce=self.nonce_64) self.assertEqual(cipher1.nonce, self.nonce_64) counter = Counter.new(64, prefix=self.nonce_64, initial_value=0) cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) self.assertEqual(cipher1.nonce, cipher2.nonce) pt = get_tag_random("plaintext", 65536) self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) # Nonce is implicitly created (for AES) when no parameters are passed nonce1 = AES.new(self.key_128, AES.MODE_CTR).nonce nonce2 = AES.new(self.key_128, AES.MODE_CTR).nonce self.assertNotEqual(nonce1, nonce2) self.assertEqual(len(nonce1), 8) # Nonce can be zero-length cipher = AES.new(self.key_128, AES.MODE_CTR, nonce=b("")) self.assertEqual(b(""), cipher.nonce) # Nonce and Counter are mutually exclusive self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, counter=self.ctr_128, nonce=self.nonce_64)
def test3(self): for keylen, taglen, result in self.tv3: key = bchr(0) * (keylen // 8 - 1) + bchr(taglen) C = b("") for i in range(128): S = bchr(0) * i N = long_to_bytes(3 * i + 1, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) cipher.update(S) C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() N = long_to_bytes(3 * i + 2, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() N = long_to_bytes(3 * i + 3, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) cipher.update(S) C += cipher.encrypt() + cipher.digest() N = long_to_bytes(385, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) cipher.update(C) result2 = cipher.encrypt() + cipher.digest() self.assertEquals(unhexlify(b(result)), result2)
def test_unaligned_data_64(self): plaintexts = [ b("7777777") ] * 100 cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) self.assertEqual(b("").join(ciphertexts), cipher.encrypt(b("").join(plaintexts)))
def test_unaligned_data_128(self): plaintexts = [ b("7777777") ] * 100 cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) self.assertEqual(b("").join(ciphertexts), cipher.encrypt(b("").join(plaintexts)))
def _start_mac(self): assert(self._mac_status == MacStatus.NOT_STARTED) assert(None not in (self._assoc_len, self._msg_len)) assert(isinstance(self._cache, list)) # Formatting control information and nonce (A.2.1) q = 15 - len(self.nonce) # length of Q, the encoded message length flags = (64 * (self._assoc_len > 0) + 8 * ((self._mac_len - 2) // 2) + (q - 1)) b_0 = bchr(flags) + self.nonce + long_to_bytes(self._msg_len, q) # Formatting associated data (A.2.2) # Encoded 'a' is concatenated with the associated data 'A' assoc_len_encoded = b('') if self._assoc_len > 0: if self._assoc_len < (2 ** 16 - 2 ** 8): enc_size = 2 elif self._assoc_len < (2L ** 32): assoc_len_encoded = b('\xFF\xFE') enc_size = 4 else: assoc_len_encoded = b('\xFF\xFF') enc_size = 8 assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size)
def __init__(self, module, params): from Cryptodome import Random unittest.TestCase.__init__(self) self.module = module self.iv = Random.get_random_bytes(module.block_size) self.key = b(params['key']) self.plaintext = 100 * b(params['plaintext']) self.module_name = params.get('module_name', None)
def test_either_encrypt_or_decrypt(self): cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) cipher.encrypt(b("")) self.assertRaises(TypeError, cipher.decrypt, b("")) cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) cipher.decrypt(b("")) self.assertRaises(TypeError, cipher.encrypt, b(""))
def test_either_encrypt_or_decrypt(self): cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) cipher.encrypt(b("xyz")) self.assertRaises(TypeError, cipher.decrypt, b("xyz")) cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) cipher.decrypt(b("xyz")) self.assertRaises(TypeError, cipher.encrypt, b("xyz"))
def test_unaligned_data_128(self): cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) for wrong_length in xrange(1,16): self.assertRaises(ValueError, cipher.encrypt, b("5") * wrong_length) cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) for wrong_length in xrange(1,16): self.assertRaises(ValueError, cipher.decrypt, b("5") * wrong_length)
def test_unaligned_data_64(self): cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) for wrong_length in xrange(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 xrange(1,8): self.assertRaises(ValueError, cipher.decrypt, b("5") * wrong_length)
def test_either_encrypt_or_decrypt(self): cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) eiv = cipher.encrypt(b("")) self.assertRaises(TypeError, cipher.decrypt, b("")) cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) cipher.decrypt(b("")) self.assertRaises(TypeError, cipher.encrypt, b(""))
def test_either_encrypt_or_decrypt(self): cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) cipher.encrypt(b("")) self.assertRaises(TypeError, cipher.decrypt, b("")) cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) cipher.decrypt(b("")) self.assertRaises(TypeError, cipher.encrypt, b(""))
def test_new_positive(self): xof1 = self.shake.new() xof2 = self.shake.new(data=b("90")) xof3 = self.shake.new().update(b("90")) self.assertNotEqual(xof1.read(10), xof2.read(10)) xof3.read(10) self.assertEqual(xof2.read(10), xof3.read(10))
def runTest(self): for key_size, result in self.test_vectors: next_data = b("") for _ in xrange(100): h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b("A" * key_size)) h.update(next_data) next_data = h.digest() + next_data self.assertEqual(h.digest(), result)
def __init__(self, key, msg=b(""), digestmod=None): """Create a new HMAC object. :Parameters: key : byte string secret key for the MAC object. It must be long enough to match the expected security level of the MAC. However, there is no benefit in using keys longer than the `digest_size` of the underlying hash algorithm. msg : byte string The very first chunk of the message to authenticate. It is equivalent to an early call to `update()`. Optional. :Parameter digestmod: The hash algorithm the HMAC is based on. Default is `Cryptodome.Hash.MD5`. :Type digestmod: A hash module or object instantiated from `Cryptodome.Hash` """ if digestmod is None: digestmod = MD5 if msg is None: msg = b("") #: Size of the MAC tag self.digest_size = digestmod.digest_size self._digestmod = digestmod try: if len(key) <= digestmod.block_size: # Step 1 or 2 key_0 = key + bchr(0) * (digestmod.block_size - len(key)) else: # Step 3 hash_k = digestmod.new(key).digest() key_0 = hash_k + bchr(0) * (digestmod.block_size - len(hash_k)) except AttributeError: # Not all hash types have "block_size" raise ValueError("Hash type incompatible to HMAC") # Step 4 key_0_ipad = strxor(key_0, bchr(0x36) * len(key_0)) # Start step 5 and 6 self._inner = digestmod.new(key_0_ipad) self._inner.update(msg) # Step 7 key_0_opad = strxor(key_0, bchr(0x5c) * len(key_0)) # Start step 8 and 9 self._outer = digestmod.new(key_0_opad)
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 test_invalid_multiple_encrypt(self): # Without AAD cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) cipher.encrypt(b("xxx")) self.assertRaises(TypeError, cipher.encrypt, b("xxx")) # With AAD cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) cipher.update(b("yyy")) cipher.encrypt(b("xxx")) self.assertRaises(TypeError, cipher.encrypt, b("xxx"))
def test_template(self, factory=factory, key_size=key_size): cipher = factory.new(get_tag_random("cipher", key_size), factory.MODE_EAX, nonce=b("nonce")) ct, mac = cipher.encrypt_and_digest(b("plaintext")) cipher = factory.new(get_tag_random("cipher", key_size), factory.MODE_EAX, nonce=b("nonce")) pt2 = cipher.decrypt_and_verify(ct, mac) self.assertEqual(b("plaintext"), pt2)
def runTest(self): key = binascii.a2b_hex(b(self.key)) data = binascii.a2b_hex(b(self.input)) # Strip whitespace from the expected string (which should be in lowercase-hex) expected = b("".join(self.result.split())) h = self.module.new(key, **self.params) h.update(data) out1_bin = h.digest() out1 = binascii.b2a_hex(h.digest()) out2 = h.hexdigest() # Verify that correct MAC does not raise any exception h.hexverify(out1) h.verify(out1_bin) # Verify that incorrect MAC does raise ValueError exception wrong_mac = strxor_c(out1_bin, 255) self.assertRaises(ValueError, h.verify, wrong_mac) self.assertRaises(ValueError, h.hexverify, "4556") h = self.module.new(key, data, **self.params) out3 = h.hexdigest() out4 = binascii.b2a_hex(h.digest()) # Test .copy() h2 = h.copy() h.update(b("blah blah blah")) # Corrupt the original hash object out5 = binascii.b2a_hex(h2.digest()) # The copied hash object should return the correct result # PY3K: Check that hexdigest() returns str and digest() returns bytes if sys.version_info[0] > 2: self.assertTrue(isinstance(h.digest(), type(b("")))) self.assertTrue(isinstance(h.hexdigest(), type(""))) # PY3K: Check that .hexverify() accepts bytes or str if sys.version_info[0] > 2: h.hexverify(h.hexdigest()) h.hexverify(h.hexdigest().encode('ascii')) # PY3K: hexdigest() should return str, and digest() should return bytes self.assertEqual(expected, out1) if sys.version_info[0] == 2: self.assertEqual(expected, out2) self.assertEqual(expected, out3) else: self.assertEqual(expected.decode(), out2) self.assertEqual(expected.decode(), out3) self.assertEqual(expected, out4) self.assertEqual(expected, out5)
def _import_openssh(encoded): keystring = binascii.a2b_base64(encoded.split(b(' '))[1]) keyparts = [] while len(keystring) > 4: l = struct.unpack(">I", keystring[:4])[0] keyparts.append(keystring[4:4 + l]) keystring = keystring[4 + l:] if keyparts[1] != b("nistp256"): raise ValueError("Unsupported ECC curve") return _import_public_der(_curve.oid, keyparts[2])
def _export_openssh(self): assert not self.has_private() desc = "ecdsa-sha2-nistp256" # 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)) comps = (tobytes(desc), b("nistp256"), public_key) blob = b("").join([ struct.pack(">I", len(x)) + x for x in comps]) return desc + " " + tostr(binascii.b2a_base64(blob))
def __init__(self, key, *args, **kwargs): """Initialize an ARC4 cipher object See also `new()` at the module level.""" if len(args) > 0: ndrop = args[0] args = args[1:] else: ndrop = kwargs.pop('drop', 0) if len(key) not in key_size: raise ValueError("Incorrect ARC4 key length (%d bytes)" % len(key)) expect_byte_string(key) self._state = VoidPointer() result = _raw_arc4_lib.ARC4_stream_init(key, c_size_t(len(key)), self._state.address_of()) if result != 0: raise ValueError("Error %d while creating the ARC4 cipher" % result) self._state = SmartPointer(self._state.get(), _raw_arc4_lib.ARC4_stream_destroy) if ndrop > 0: # This is OK even if the cipher is used for decryption, # since encrypt and decrypt are actually the same thing # with ARC4. self.encrypt(b('\x00') * ndrop) self.block_size = 1 self.key_size = len(key)
def MGF1(mgfSeed, maskLen, hash_gen): """Mask Generation Function, described in `B.2.1 of RFC8017 <https://tools.ietf.org/html/rfc8017>`_. :param mfgSeed: seed from which the mask is generated :type mfgSeed: byte string :param maskLen: intended length in bytes of the mask :type maskLen: integer :param hash_gen: A module or a hash object from :mod:`Cryptodome.Hash` :type hash_object: :return: the mask, as a *byte string* """ T = b("") for counter in xrange(ceil_div(maskLen, hash_gen.digest_size)): c = long_to_bytes(counter, 4) hobj = hash_gen.new() hobj.update(mgfSeed + c) T = T + hobj.digest() assert(len(T) >= maskLen) return T[:maskLen]
def test_IV_iv_attributes(self): cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) eiv = cipher.encrypt(b("")) self.assertEqual(cipher.iv, self.iv_128) cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) self.assertEqual(cipher.iv, self.iv_128)
def encode(self): """Return the DER BIT STRING, fully encoded as a binary string.""" # Add padding count byte self.payload = b('\x00') + self.value return DerObject.encode(self)
def test_digest(self): h = self.shake.new() digest = h.read(90) # read returns a byte string of the right length self.failUnless(isinstance(digest, type(b("digest")))) self.assertEqual(len(digest), 90)
def test_valid_multiple_encrypt_or_decrypt(self): for method_name in "encrypt", "decrypt": for auth_data in (None, b("333"), self.data_128, self.data_128 + b("3")): if auth_data is None: assoc_len = None else: assoc_len = len(auth_data) cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) if auth_data is not None: cipher.update(auth_data) method = getattr(cipher, method_name) method(self.data_128) method(self.data_128) method(self.data_128) method(self.data_128) method()
def test_longer_assoc_data_than_declared(self): # More than zero cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, assoc_len=0) self.assertRaises(ValueError, cipher.update, b("1")) # Too large cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, assoc_len=15) self.assertRaises(ValueError, cipher.update, self.data_128)
def test_byte_or_string_passphrase(self): encoded1 = ref_private.export_key(format="PEM", use_pkcs8=False, passphrase="secret", randfunc=get_fixed_prng()) encoded2 = ref_private.export_key(format="PEM", use_pkcs8=False, passphrase=b("secret"), randfunc=get_fixed_prng()) self.assertEqual(encoded1, encoded2)
def _create_ctr_cipher(self, mac_tag): """Create a new CTR cipher from the MAC in SIV mode""" tag_int = bytes_to_long(mac_tag) return self._factory.new(self._subkey_cipher, self._factory.MODE_CTR, initial_value=tag_int ^ (tag_int & 0x8000000080000000L), nonce=b(""), **self._cipher_params)
def runTest(self): key = RSA.generate(1280) signer = pss.new(key) hash_names = ("MD2", "MD4", "MD5", "RIPEMD160", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512") for name in hash_names: hashed = load_hash_by_name(name).new(b("Test")) signer.sign(hashed) from Cryptodome.Hash import BLAKE2b, BLAKE2s for hash_size in (20, 32, 48, 64): hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b("Test")) signer.sign(hashed_b) for hash_size in (16, 20, 28, 32): hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b("Test")) signer.sign(hashed_s)
def test_negative_unapproved_hashes(self): """Verify that unapproved hashes are rejected""" from Cryptodome.Hash import RIPEMD160 self.description = "Unapproved hash (RIPEMD160) test" hash_obj = RIPEMD160.new() signer = DSS.new(self.key_priv, 'fips-186-3') self.assertRaises(ValueError, signer.sign, hash_obj) self.assertRaises(ValueError, signer.verify, hash_obj, b("\x00") * 40)
def runTest(self): for tv in self.test_vectors: digest_bytes = len(tv) next_data = b("") for _ in xrange(100): h = self.BLAKE2.new(digest_bytes=digest_bytes) h.update(next_data) next_data = h.digest() + next_data self.assertEqual(h.digest(), tv)
def import_key(encoded, passphrase=None): """Import an ECC key (public or private). Args: encoded (bytes or multi-line string): The ECC key to import. An ECC **public** key can be: - An X.509 certificate, binary (DER) or ASCII (PEM) - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM) - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) An ECC **private** key can be: - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_) - In ASCII format (PEM or OpenSSH) Private keys can be in the clear or password-protected. For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. passphrase (byte string): The passphrase to use for decrypting a private key. Encryption may be applied protected at the PEM level or at the PKCS#8 level. This parameter is ignored if the key in input is not encrypted. Returns: :class:`EccKey` : a new ECC key object Raises: ValueError: when the given key cannot be parsed (possibly because the pass phrase is wrong). .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt """ encoded = tobytes(encoded) if passphrase is not None: passphrase = tobytes(passphrase) # PEM if encoded.startswith(b('-----')): der_encoded, marker, enc_flag = PEM.decode(tostr(encoded), passphrase) if enc_flag: passphrase = None try: result = _import_der(der_encoded, passphrase) except UnsupportedEccFeature, uef: raise uef except ValueError: raise ValueError("Invalid DER encoding inside the PEM file")
def test_message_chunks(self): # Validate that both associated data and plaintext/ciphertext # can be broken up in chunks of arbitrary length auth_data = get_tag_random("authenticated data", 127) plaintext = get_tag_random("plaintext", 127) cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) cipher.update(auth_data) ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) def break_up(data, chunk_length): return [data[i:i+chunk_length] for i in range(0, len(data), chunk_length)] # Encryption for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) for chunk in break_up(auth_data, chunk_length): cipher.update(chunk) pt2 = b("") for chunk in break_up(ciphertext, chunk_length): pt2 += cipher.decrypt(chunk) pt2 += cipher.decrypt() self.assertEqual(plaintext, pt2) cipher.verify(ref_mac) # Decryption for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) for chunk in break_up(auth_data, chunk_length): cipher.update(chunk) ct2 = b("") for chunk in break_up(plaintext, chunk_length): ct2 += cipher.encrypt(chunk) ct2 += cipher.encrypt() self.assertEqual(ciphertext, ct2) self.assertEqual(cipher.digest(), ref_mac)
def test_nonce_length(self): # nonce can be of any length (but not empty) self.assertRaises(ValueError, AES.new, self.key_256, AES.MODE_SIV, nonce=b("")) for x in range(1, 128): cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=bchr(1) * x) cipher.encrypt(bchr(1))
def test_valid_multiple_encrypt_or_decrypt(self): # Only possible if msg_len is declared in advance for method_name in "encrypt", "decrypt": for auth_data in (None, b("333"), self.data_128, self.data_128 + b("3")): if auth_data is None: assoc_len = None else: assoc_len = len(auth_data) cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, msg_len=64, assoc_len=assoc_len) if auth_data is not None: cipher.update(auth_data) method = getattr(cipher, method_name) method(self.data_128) method(self.data_128) method(self.data_128) method(self.data_128)
def __init__(self, value=b(''), implicit=None, explicit=None): """Initialize the DER object as a BIT STRING. :Parameters: value : byte string or DER object The initial, packed bit string. If not specified, the bit string is empty. implicit : integer The IMPLICIT tag to use for the encoded object. It overrides the universal tag for OCTET STRING (3). explicit : integer The EXPLICIT tag to use for the encoded object. """ DerObject.__init__(self, 0x03, b(''), implicit, False, explicit) # The bitstring value (packed) if isinstance(value, DerObject): self.value = value.encode() else: self.value = value
def test_nonce_length(self): # nonce cannot be empty self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, nonce=b("")) # nonce can be up to 15 bytes long for length in range(1, 16): AES.new(self.key_128, AES.MODE_OCB, nonce=self.data[:length]) self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, nonce=self.data)
def runTest(self): key = RSA.generate(1024) hashed = SHA1.new(b("Test")) good_signature = PKCS1_PSS.new(key).sign(hashed) verifier = PKCS1_PSS.new(key.publickey()) self.assertEqual(verifier.verify(hashed, good_signature), True) # Flip a few bits in the signature bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) self.assertEqual(verifier.verify(hashed, bad_signature), False)
def runTest(self): key = RSA.importKey(PKCS1_15_NoParams.rsakey) hashed = SHA1.new(b("Test")) good_signature = PKCS1_v1_5.new(key).sign(hashed) verifier = PKCS1_v1_5.new(key.publickey()) self.assertEqual(verifier.verify(hashed, good_signature), True) # Flip a few bits in the signature bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) self.assertEqual(verifier.verify(hashed, bad_signature), False)
def update(self, msg): """Continue authentication of a message by consuming the next chunk of data. Repeated calls are equivalent to a single call with the concatenation of all the arguments. In other words: >>> m.update(a); m.update(b) is equivalent to: >>> m.update(a+b) :Parameters: msg : byte string The next chunk of the message being authenticated """ self._data_size += len(msg) if len(self._cache) > 0: filler = min(self.digest_size - len(self._cache), len(msg)) self._cache += msg[:filler] if len(self._cache) < self.digest_size: return self msg = msg[filler:] self._update(self._cache) self._cache = b("") update_len, remain = divmod(len(msg), self.digest_size) update_len *= self.digest_size if remain > 0: self._update(msg[:update_len]) self._cache = msg[update_len:] else: self._update(msg) self._cache = b("") return self
def __init__(self, value=b(''), implicit=None): """Initialize the DER object as an OCTET STRING. :Parameters: value : byte string The initial payload of the object. If not specified, the payload is empty. implicit : integer The IMPLICIT tag to use for the encoded object. It overrides the universal tag for OCTET STRING (4). """ DerObject.__init__(self, 0x04, value, implicit, False)
def testVerify1(self): for test in self._testData: key = RSA.importKey(test[0]) expected_pt = b(test[1]) ct = t2b(test[2]) cipher = PKCS.new(key) # The real test pt = cipher.decrypt(ct, None) self.assertEqual(pt, expected_pt) pt = cipher.decrypt(ct, b'\xFF' * len(expected_pt)) self.assertEqual(pt, expected_pt)
def _transcrypt(self, in_data, trans_func, trans_desc): # Last piece to encrypt/decrypt if in_data is None: out_data = self._transcrypt_aligned(self._cache_P, len(self._cache_P), trans_func, trans_desc) self._cache_P = b("") return out_data # Try to fill up the cache, if it already contains something expect_byte_string(in_data) prefix = b("") if len(self._cache_P) > 0: filler = min(16 - len(self._cache_P), len(in_data)) self._cache_P += in_data[:filler] in_data = in_data[filler:] if len(self._cache_P) < 16: # We could not manage to fill the cache, so there is certainly # no output yet. return b("") # Clear the cache, and proceeding with any other aligned data prefix = self._transcrypt_aligned(self._cache_P, len(self._cache_P), trans_func, trans_desc) self._cache_P = b("") # Process data in multiples of the block size trans_len = len(in_data) // 16 * 16 result = self._transcrypt_aligned(in_data, trans_len, trans_func, trans_desc) if prefix: result = prefix + result # Left-over self._cache_P = in_data[trans_len:] return result
def runTest(self): plaintext = a2b_hex(self.plaintext) ciphertext = a2b_hex(self.ciphertext) # The cipher should work like a stream cipher # Test counter mode encryption, 3 bytes at a time ct3 = [] cipher = self._new() for i in range(0, len(plaintext), 3): ct3.append(cipher.encrypt(plaintext[i:i+3])) ct3 = b2a_hex(b("").join(ct3)) self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time) # Test counter mode decryption, 3 bytes at a time pt3 = [] cipher = self._new() for i in range(0, len(ciphertext), 3): pt3.append(cipher.encrypt(ciphertext[i:i+3])) # PY3K: This is meant to be text, do not change to bytes (data) pt3 = b2a_hex(b("").join(pt3)) self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time)
def new(**kwargs): """Create a new hash object. Args: data (byte string/array): Optional. The very first chunk of the message to hash. It is equivalent to an early call to :meth:`BLAKE2b_Hash.update`. digest_bytes (integer): Optional. The size of the digest, in bytes (1 to 64). Default is 64. digest_bits (integer): Optional and alternative to ``digest_bytes``. The size of the digest, in bits (8 to 512, in steps of 8). Default is 512. key (byte string): Optional. The key to use to compute the MAC (1 to 64 bytes). If not specified, no key will be used. update_after_digest (boolean): Optional. By default, a hash object cannot be updated anymore after the digest is computed. When this flag is ``True``, such check is no longer enforced. Returns: A :class:`BLAKE2b_Hash` hash object """ data = kwargs.pop("data", None) update_after_digest = kwargs.pop("update_after_digest", False) digest_bytes = kwargs.pop("digest_bytes", None) digest_bits = kwargs.pop("digest_bits", None) if None not in (digest_bytes, digest_bits): raise TypeError("Only one digest parameter must be provided") if (None, None) == (digest_bytes, digest_bits): digest_bytes = 64 if digest_bytes is not None: if not (1 <= digest_bytes <= 64): raise ValueError("'digest_bytes' not in range 1..64") else: if not (8 <= digest_bits <= 512) or (digest_bits % 8): raise ValueError("'digest_bytes' not in range 8..512, " "with steps of 8") digest_bytes = digest_bits // 8 key = kwargs.pop("key", b("")) if len(key) > 64: raise ValueError("BLAKE2s key cannot exceed 64 bytes") if kwargs: raise TypeError("Unknown parameters: " + str(kwargs)) return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest)
def test3(self): for keylen, taglen, result in self.tv3: key = bchr(0) * (keylen // 8 - 1) + bchr(taglen) C = b("") for i in range(128): S = bchr(0) * i N = long_to_bytes(3 * i + 1, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) cipher.update(S) C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() N = long_to_bytes(3 * i + 2, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() N = long_to_bytes(3 * i + 3, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) cipher.update(S) C += cipher.encrypt() + cipher.digest() N = long_to_bytes(385, 12) cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) cipher.update(C) result2 = cipher.encrypt() + cipher.digest() self.assertEqual(unhexlify(b(result)), result2)
def testVerify2(self): # Verify that decryption fails if ciphertext is not as long as # RSA modulus cipher = PKCS.new(self.key1024) self.assertRaises(ValueError, cipher.decrypt, '\x00' * 127, "---") self.assertRaises(ValueError, cipher.decrypt, '\x00' * 129, "---") # Verify that decryption fails if there are less then 8 non-zero padding # bytes pt = b('\x00\x02' + '\xFF' * 7 + '\x00' + '\x45' * 118) pt_int = bytes_to_long(pt) ct_int = self.key1024._encrypt(pt_int) ct = long_to_bytes(ct_int, 128) self.assertEqual("---", cipher.decrypt(ct, "---"))
def __init__(self, value=0, implicit=None, explicit=None): """Initialize the DER object as an INTEGER. :Parameters: value : integer The value of the integer. implicit : integer The IMPLICIT tag to use for the encoded object. It overrides the universal tag for INTEGER (2). """ DerObject.__init__(self, 0x02, b(''), implicit, False, explicit) self.value = value # The integer value
def __init__(self, value='', implicit=None, explicit=None): """Initialize the DER object as an OBJECT ID. :Parameters: value : string The initial Object Identifier (e.g. "1.2.0.0.6.2"). implicit : integer The IMPLICIT tag to use for the encoded object. It overrides the universal tag for OBJECT ID (6). explicit : integer The EXPLICIT tag to use for the encoded object. """ DerObject.__init__(self, 0x06, b(''), implicit, False, explicit) self.value = value
def _decodeFromStream(self, s): """Decode a complete DER BIT STRING DER from a file.""" # Fill-up self.payload DerObject._decodeFromStream(self, s) if self.payload and bord(self.payload[0]) != 0: raise ValueError("Not a valid BIT STRING") # Fill-up self.value self.value = b('') # Remove padding count byte if self.payload: self.value = self.payload[1:]
def test_new_positive(self): h = self.BLAKE2.new(digest_bits=self.max_bits) for new_func in self.BLAKE2.new, h.new: for dbits in xrange(8, self.max_bits + 1, 8): hobj = new_func(digest_bits=dbits) self.assertEqual(hobj.digest_size, dbits // 8) for dbytes in xrange(1, self.max_bytes + 1): hobj = new_func(digest_bytes=dbytes) self.assertEqual(hobj.digest_size, dbytes) digest1 = new_func(data=b("\x90"), digest_bytes=self.max_bytes).digest() digest2 = new_func(digest_bytes=self.max_bytes).update( b("\x90")).digest() self.assertEqual(digest1, digest2) new_func(data=b("A"), key=b("5"), digest_bytes=self.max_bytes) hobj = h.new() self.assertEqual(hobj.digest_size, self.max_bytes)
def encode(self): """Return the DER INTEGER, fully encoded as a binary string.""" number = self.value self.payload = b('') while True: self.payload = bchr(int(number & 255)) + self.payload if 128 <= number <= 255: self.payload = bchr(0x00) + self.payload if -128 <= number <= 255: break number >>= 8 return DerObject.encode(self)
def test_seek_tv(self): # Test Vector #4, A.1 from # http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 key = bchr(0) + bchr(255) + bchr(0) * 30 nonce = bchr(0) * 8 cipher = ChaCha20.new(key=key, nonce=nonce) cipher.seek(64 * 2) expected_key_stream = unhexlify( b("72d54dfbf12ec44b362692df94137f32" "8fea8da73990265ec1bbbea1ae9af0ca" "13b25aa26cb4a648cb9b9d1be65b2c09" "24a66c54d545ec1b7374f4872e99f096")) ct = cipher.encrypt(bchr(0) * len(expected_key_stream)) self.assertEqual(expected_key_stream, ct)
def __init__(self, key, msg=b(""), digestmod=None): if digestmod is None: digestmod = MD5 if msg is None: msg = b("") # Size of the MAC tag self.digest_size = digestmod.digest_size self._digestmod = digestmod try: if len(key) <= digestmod.block_size: # Step 1 or 2 key_0 = key + bchr(0) * (digestmod.block_size - len(key)) else: # Step 3 hash_k = digestmod.new(key).digest() key_0 = hash_k + bchr(0) * (digestmod.block_size - len(hash_k)) except AttributeError: # Not all hash types have "block_size" raise ValueError("Hash type incompatible to HMAC") # Step 4 key_0_ipad = strxor(key_0, bchr(0x36) * len(key_0)) # Start step 5 and 6 self._inner = digestmod.new(key_0_ipad) self._inner.update(msg) # Step 7 key_0_opad = strxor(key_0, bchr(0x5c) * len(key_0)) # Start step 8 and 9 self._outer = digestmod.new(key_0_opad)