def check_vectors(self, filename): mode = filename[:3].lower() fh = open("test_vectors/" + filename, "r") type = fh.readline().strip()[1:-1].lower() fh.readline() data = {} for line in fh: line = line.strip() if not line and data: key = b16decode(data["key"].encode(), True) iv = b16decode(data.get("iv", "").encode(), True) pt = b16decode(data["plaintext"].encode(), True) ct = b16decode(data["ciphertext"].encode(), True) cipher = Cipher(key=key, iv=iv or None, cipher="aes", mode=mode) if type == "encrypt": res = cipher.encrypt(pt) self.assertEqual( res, ct, "%s #%s: %s != %s" % (filename, data["count"], b16encode(res), data["ciphertext"]) ) data = {} if " = " not in line: continue k, v = line.lower().split(" = ") data[k] = v fh.close()
def check_openssl(self, cipher_name, keysize, mode): cipher_desc = Descriptor(cipher=cipher_name) for i in range(1, 2): key = os.urandom(keysize // 8) iv = os.urandom(cipher_desc.block_size) pt = os.urandom(i * 128 // 8) if cipher_name == "aes": cipher_spec = "aes-%d-%s" % (keysize, mode) elif cipher_name == "des": cipher_spec = "des-%s" % mode elif cipher_name == "blowfish": cipher_spec = "bf-%s" % mode proc = Popen( ( "openssl enc -e -%s -nopad -nosalt -K %s -iv %s" % (cipher_spec, b16encode(key).decode(), b16encode(iv).decode()) ).split(), stdin=PIPE, stdout=PIPE, stderr=PIPE, ) out, err = proc.communicate(pt) self.assertFalse(err, err) cipher = Cipher(key=key, iv=iv, cipher=cipher_name, mode=mode) ct = cipher.encrypt(pt) self.assertEqual( ct, out, "%s %s %s: %s != %s" % (cipher_name, keysize, mode, b16encode(ct).decode(), b16encode(out).decode()), )
def check_openssl(self, cipher_name, keysize, mode): cipher_desc = Descriptor(cipher=cipher_name) for i in range(1, 2): key = os.urandom(keysize//8) iv = None if mode == 'ecb' else os.urandom(cipher_desc.block_size) pt = os.urandom(i * 128 // 8) if cipher_name == 'aes': cipher_spec = 'aes-%d-%s' % (keysize, mode) elif cipher_name == 'des': cipher_spec = 'des-%s' % mode elif cipher_name == 'blowfish': cipher_spec = 'bf-%s' % mode proc = Popen(('openssl enc -e -%s -nopad -nosalt -K %s -iv %s' % (cipher_spec, b16encode(key).decode(), b16encode(iv or b'\0').decode())).split(), stdin=PIPE, stdout=PIPE, stderr=PIPE) out, err = proc.communicate(pt) self.assertFalse(err, err) cipher = Cipher(key=key, iv=iv, cipher=cipher_name, mode=mode) ct = cipher.encrypt(pt) self.assertEqual(ct, out, '%s %s %s: %s != %s' % (cipher_name, keysize, mode, b16encode(ct).decode(), b16encode(out).decode()))
def check_vectors(self, filename): mode = filename[:3].lower() fh = open('test_vectors/' + filename, 'r') type = fh.readline().strip()[1:-1].lower() fh.readline() data = {} for line in fh: line = line.strip() if not line and data: key = b16decode(data['key'].encode(), True) iv = b16decode(data.get('iv', '').encode(), True) pt = b16decode(data['plaintext'].encode(), True) ct = b16decode(data['ciphertext'].encode(), True) cipher = Cipher(key=key, iv=iv or None, cipher='aes', mode=mode) if type == 'encrypt': res = cipher.encrypt(pt) self.assertEqual(res, ct, '%s #%s: %s != %s' % (filename, data['count'], b16encode(res), data['ciphertext'])) data = {} if ' = ' not in line: continue k, v = line.lower().split(' = ') data[k] = v fh.close()
def dumps(key, data, encrypt=True, add_time=True, nonce=16, max_age=None, extra={}, depends_on={}): """ Basic example without encryption: >>> key = '0123456789abcdef' >>> encoded = dumps(key, 'abc123', encrypt=False) >>> encoded #doctest: +ELLIPSIS 'abc123.n:...,s:...,t:...' >>> loads(key, encoded) 'abc123' Basic example with encryption: >>> encoded = dumps(key, 'abc123') >>> encoded #doctest: +ELLIPSIS '....i:...,s:...' >>> loads(key, encoded) 'abc123' It fails when modified: >>> loads(key, encoded + 'extra', strict=True) Traceback (most recent call last): ... ValueError: invalid signature We can add expiry times: >>> encoded = dumps(key, 'abc123', encrypt=False, max_age=3600) >>> encoded #doctest: +ELLIPSIS 'abc123.n:...,s:...,t:...,x:...' >>> encoded = dumps(key, 'abc123', max_age=60) >>> loads(key, encoded) 'abc123' >>> import mock >>> with mock.patch('time.time', returns=time.time() + 3600): ... loads(key, encoded, strict=True) Traceback (most recent call last): ... ValueError: signature has expired Adding dependant data: >>> encoded = dumps(key, 'abc123', encrypt=False, depends_on=dict(key='value')) >>> encoded #doctest: +ELLIPSIS 'abc123.n:...,s:...,t:...' >>> loads(key, encoded, strict=True) Traceback (most recent call last): ... ValueError: invalid signature >>> loads(key, encoded, depends_on=dict(key='value')) 'abc123' Unicode: >>> encoded = dumps(key, u'¡™£¢∞§¶•') >>> restored = loads(key, encoded) >>> type(restored) is unicode True >>> restored == u'¡™£¢∞§¶•' True >>> data = u''.join(unichr(i) for i in range(512)) >>> encoded = dumps(key, data) >>> restored = loads(key, encoded) >>> type(restored) is unicode True >>> restored == data True Repr-able types: >>> encoded = dumps(key, range(10), encrypt=False) >>> encoded # doctest: +ELLIPSIS '$5b0,1,2,3,4,5,6,7,8,9$5d.f:r,n:...,s:...,t:...' >>> loads(key, encoded) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> encoded = dumps(key, {'list': [True, False], ('tuple', 'keys'): {'sub': 1234}}, encrypt=False) >>> encoded # doctest: +ELLIPSIS "$7b'list':$5bTrue,False$5d,('tuple','keys'):$7b'sub':1234$7d$7d.f:r,n:...,s:...,t:..." >>> loads(key, encoded) {('tuple', 'keys'): {'sub': 1234}, 'list': [True, False]} Pickle-able types: >>> encoded = dumps(key, set('hello'), encrypt=False) >>> encoded # doctest: +ELLIPSIS 'gAJjX19idWlsdGluX18Kc2V0CnEAXXEBKFUBaHECVQFlcQNVAWxxBFUBb3EFZYVxBlJxBy4.f:p,n:...,s:...,t:...' >>> loads(key, encoded) set(['h', 'e', 'l', 'o']) """ if encrypt: inner_meta = dict(extra) outer_meta = {} nonce = max(0, nonce - 16) else: inner_meta = outer_meta = dict(extra) if add_time: inner_meta[CREATION_TIME_KEY] = encode_int(time.time()) if max_age: inner_meta[EXPIRATION_TIME_KEY] = encode_int(time.time() + max_age) # Deal with different types. if type(data) is bytes: pass elif type(data) is unicode: data = data.encode('utf8') inner_meta[DATA_FORMAT_KEY] = 'u' else: try: data = deterministic_repr.dumps(data, minimize=True) inner_meta[DATA_FORMAT_KEY] = 'r' except TypeError: data = pickle.dumps(data, protocol=2) inner_meta[DATA_FORMAT_KEY] = 'p' # Try compressing the data. Only use the compressed form if requested or # there is enough of a savings to justify it. If we are not encrypting then # the compression must also do better than the base64 encoding that would # be required. data_compressed = zlib.compress(data) if len(data) / len(data_compressed) > (1 if encrypt else 4 / 3): data = data_compressed inner_meta[COMPRESSION_FLAG_KEY] = '1' if encrypt: # Pack up the inner payload. data = encode_seal(data, inner_meta) # Encrypt it. iv = os.urandom(16) outer_meta[ENCRYPTION_IV_KEY] = encode_binary(iv) cipher = tomcrypt.cipher.aes(key, iv, mode='ctr') data = cipher.encrypt(data) if encrypt or COMPRESSION_FLAG_KEY in inner_meta or inner_meta.get(DATA_FORMAT_KEY) == 'p': # Make it transport safe. data = encode_binary(data) # Sign it. outer_meta = sign(key, data, add_time=False, nonce=nonce, hash=hashlib.sha256, extra=outer_meta, depends_on=depends_on) # Pack up outer payload. return encode_seal(data, outer_meta)