def new_random_key(maker, kek, purpose, user, klen=32): from cryptoe.KeyMgmt import newkey_rnd from cryptoe.KeyWrap import KWP session = maker() no_salt = session.query(Salt).filter_by(salt='').first() if len(no_salt.salt) != 0: raise SaltLengthError('Salt length for new_random_key should be 0') k = Key() k.bits = klen * 8 k.purpose = purpose k.user = user k.salt_id = no_salt.id k_actual = newkey_rnd(klen) if len(k_actual) != klen: raise KeyLengthError( 'Key returned by newkey_rnd does not match requested length (%d != %d)' % (len(k_actual), klen)) k.key = KWP.wrap(kek, k_actual) k_hash = SHAd256.new(k_actual).hexdigest() k.key_hash = k_hash k.related_hash = SHAd256.new(kek).hexdigest() session.add(k) session.commit() session.close() return k_actual
def new_derived_key(maker, kek, kdk, purpose, user, klen=32): from cryptoe.KeyWrap import KWP from cryptoe.KeyMgmt import newkey_hkdf session = maker() k = Key() k.bits = klen * 8 k.purpose = purpose k_salt = new_salt(maker, klen) if len(k_salt.salt) != klen: raise SaltLengthError( 'HKDF salt must be the same length as the derivation key') k.salt_id = k_salt.id k.user = user k_actual = newkey_hkdf(klen, kdk, k_salt.salt, pack_hkdf_info(k.purpose, k.user)) if len(k_actual) != klen: raise KeyLengthError( 'HKDF returned a key with an incorrect length (%d != %d)' % (len(k_actual), klen)) if kek == '': k.key = '' else: k.key = KWP.wrap(kek, k_actual) k.related_hash = SHAd256.new(kdk).hexdigest() k_hash = SHAd256.new(k_actual).hexdigest() k.key_hash = k_hash session.add(k) session.commit() session.close() return k_actual
def test_python_vs_c_RND(self): from Crypto import Random from cryptoe.Hash import SHAd256 as ct_SHAd256 rnd_buf_lens = sorted( list(set([random.randint(0, 4096) for _ in xrange(0, 64)]))) for r in xrange(0, len(rnd_buf_lens)): data = Random.new().read(rnd_buf_lens[r]) ct_hash = ct_SHAd256.new(data).digest() py_hash = py_SHAd256(data) self.assertEqual(ct_hash, py_hash)
def test_python_vs_c_NIST(self): from cryptoe.Hash import SHAd256 as ct_SHAd256 for v in NIST_FIPS_VECTORS: data = v[1] if isinstance(data, int): data = long2ba(data) if isinstance(data, long): data = long2ba(data) data = bytes(data) ct_hash = ct_SHAd256.new(data).digest() py_hash = py_SHAd256(data) self.assertEqual(ct_hash, py_hash)
def unlock_db(maker): from getpass import getpass from cryptoe.KeyMgmt import newkey_pbkdf from utils import yubikey_passphrase_cr session = maker() mk = session.query(MasterKey).order_by(MasterKey.created.desc()).one() if not mk: print('[UNLOCK] no master key found. cannot proceed.') sys.exit(0) pw = getpass('passphrase: ').rstrip() pw = yubikey_passphrase_cr(pw) mk_key = newkey_pbkdf(32, pw, mk.salt.salt, mk.rounds) mk_key_hash = SHAd256.new(mk_key).hexdigest() if mk_key_hash != mk.key_hash: return None else: return mk_key
def yubikey_passphrase_cr(passphrase): """ This function: Takes an input passphrase generates the SHAd256 hash of it sends that hash to a Yubikey configured for HMAC-SHA1 on slot 2 computes the whirlpool hash of the HMAC-SHA1 response received from the Yubikey returns the whirlpool hash :param passphrase: passphrase (plaintext) :type passphrase: str :return: whirlpool digest (hex) :rtype: str """ try: import yubico except ImportError: yubico = None if not yubico: del yubico return passphrase try: yubikey = yubico.find_yubikey() except yubico.yubikey.YubiKeyError: return passphrase if yubikey: challenge = SHAd256.new(passphrase).hexdigest() print('[YubiKey] Sending challenge') try: response = yubikey.challenge_response(challenge, slot=YUBIKEY_HMAC_CR_SLOT) print('[YubiKey] Got response') except yubico.yubikey.YubiKeyTimeout: print('[YubiKey] Timeout. Not using Yubikey.') return passphrase passphrase = whirlpool.new(response).hexdigest() return passphrase
def init_keys(maker, use_yubikey=False): from getpass import getpass from cryptoe.exceptions import KeyLengthError from cryptoe.KeyMgmt import newkey_pbkdf password_transforms = {} if use_yubikey is True: from cryptoe.utils import yubikey_passphrase_cr password_transforms['YK-HMAC-SHA1'] = yubikey_passphrase_cr passphrase_ready = 0 session = maker() passphrase = '' while not passphrase_ready: passphrase = getpass('passphrase: ').rstrip() if len(passphrase) < KEYDB_PASSPHRASE_LENGTH: print('passphrase is too short.') continue else: confirm = getpass('passphrase (confirm): ').rstrip() if confirm == passphrase: passphrase_ready = 1 del passphrase_ready roundcount = KEYDB_PBKDF2_ITERATIONS print('[INIT->PASSPHRASE] applying passphrase transformations') for tr in password_transforms: trnam = tr.upper() tr_func = password_transforms[tr] print('[INIT->%s] running' % trnam) opp = passphrase passphrase = tr_func(passphrase) if opp == passphrase: print('[INIT->%s] no change' % trnam) else: print('[INIT->%s] old length: %d bytes, new length: %d bytes' % (trnam, len(opp), len(passphrase))) klen_bits = 256 klen = klen_bits / 8 slen = klen / 2 print('[INIT->SALT] creating new salt for PBKDF (salt len = %d)' % slen) mk_salt = new_salt(maker, klen) print('[INIT->SALT] salt created (id=%d)' % mk_salt.id) mk = MasterKey() mk.bits = klen_bits mk.prf_hash = DEFAULT_PRF_HASH.__name__.split('.')[-1] mk.rounds = roundcount mk.salt_id = mk_salt.id print('[INIT->PBKDF] newkey_pbkdf(%d,<passphrase>,<salt>,%d)' % (klen, roundcount)) mk_key = newkey_pbkdf(klen, passphrase, mk_salt.salt, roundcount) print('[INIT->PBKDF] %d-bit master key derived' % (len(mk_key) * 8)) if len(mk_key) != klen: raise KeyLengthError( 'PBKDF key is not of requested length (%d != %d)' % (len(mk_key), klen)) mk_hash = SHAd256.new(mk_key).hexdigest() mk.key_hash = mk_hash session.add(mk) session.commit() session.close() mk = None mk_salt = '\x00' * klen del mk del mk_salt kp = KEYDB_PURPOSE_WRAPPING wk = new_derived_key(maker, '', mk_key, kp, KEYDB_USER, klen) print('[INIT->KDF] %d-bit key (purpose: %s) derived' % (len(wk) * 8, kp)) if len(wk) != klen: raise KeyLengthError('[INIT->KDF] %d != %d' % (len(wk), klen)) mk_key = '\x00' * klen del mk_key dbk_list = [ [ 'encryption', 32, KEYDB_PURPOSE_ENCRYPTION, ], [ 'authentication', 32, KEYDB_PURPOSE_HMAC, ], [ 'authentication', 48, KEYDB_PURPOSE_HMAC, ], [ 'authentication', 64, KEYDB_PURPOSE_HMAC, ], ] for k in dbk_list: rk = new_random_key(maker, wk, k[2], KEYDB_USER, k[1]) if len(rk) != k[1]: raise KeyLengthError('[INIT->RND] %d != %d' % (len(rk), k[1])) else: print('[INIT->RND] %d-bit key "%s" created and wrapped' % (len(rk) * 8, k[2])) rk = '\x00' * klen del rk wk = '\x00' * 32 del wk
def _shad256_new(*args): _new_funcs['SHAd256'] = _new_funcs['shad256'] = SHAd256.new return SHAd256.new(*args)