def gen_mac_login(): optestlib.p_debug('\n** Mac login details for accounts table') enc_login = {'email': Email, 'personalKey': SecretKey} muk = { 'k': optestlib.opb64e(sym_keys['mp']), 'key_ops': ['encrypt', 'decrypt'], 'alg': 'A256GCM', 'ext': True, 'key': 'oct', 'kid': 'mp' } srp = { 'hexX': optestlib.opb64e(sym_keys['srp-x']), 'params': { 'method': alg_srp, 'iterations': p2c_srp, 'alg': alg_muk, 'salt': optestlib.opb64e(p2s_srp) } } enc_login['masterUnlockKey'] = muk enc_login['SRPComputedXDictionary'] = srp optestlib.p_str("mac enc_login contents:", json.dumps(enc_login, indent=4)) return enc_login
def gen_sym_key(ekid, new_kid=None, iv=None, k=None): out = {'kid': ekid, 'cty': 'b5+jwk+json'} if new_kid != None: kid = new_kid else: kid = gen_uuid() if k != None: new_key = k else: new_key = get_random_bytes(32) key_dat = { 'alg': 'A256GCM', 'ext': True, 'key_ops': ['decrypt', 'encrypt'], 'kty': 'oct', 'kid': kid } key_dat['k'] = optestlib.opb64e(new_key) key_dat_str = json.dumps(key_dat) optestlib.p_str("New symmetric key", json.dumps(key_dat, indent=4)) sym_keys[kid] = new_key if ekid == 'mp': # sym_keys['mk'] = new_key optestlib.p_debug('\n*** Encrypting sym key with AES kid %s' % ekid) iv, ct = optestlib.enc_aes_gcm(key_dat_str, sym_keys[ekid], iv=iv) optestlib.p_data('IV', iv, dump=False) optestlib.p_data('KEY', sym_keys[ekid], dump=False) optestlib.p_data('Ciphertext', ct, dump=False) out['iv'] = optestlib.opb64e(iv) out['data'] = optestlib.opb64e(ct) out['enc'] = 'A256GCM' else: # only the primary sym_key is itself AES encrypted, rest by RSA optestlib.p_debug('\n*** Encrypting sym key with RSA kid %s\n' % ekid) jwkj = '{"keys": [%s]}' % json.dumps(pub_keys[ekid]) jwk = load_jwks(jwkj)[0] optestlib.p_str('Public key e:', jwk.e) optestlib.p_str('Public key n:', jwk.n) RSA_Key = RSA.construct((jwk.n, jwk.e)) C = PKCS1_OAEP.new(RSA_Key) ct = C.encrypt(key_dat_str) out['enc'] = 'RSA-OAEP' out['data'] = optestlib.opb64e(ct) optestlib.p_debug('') optestlib.p_data('RSA-OAEP ciphertext', ct, dump=False) return kid, out
def gen_item(name, vault, uuid, title=None, url=None, user=None, password=None): global items ekid = vault_kids[vault] overview = {'ainfo': 'account-name', 'title': title, 'url': url} iv = read_default(name + 'ov_iv') iv, enc_overview = optestlib.enc_aes_gcm(json.dumps(overview), sym_keys[ekid], iv) ov_dat = { 'data': optestlib.opb64e(enc_overview), 'iv': optestlib.opb64e(iv), 'kid': ekid, 'cty': 'b5+jwk+json', 'enc': 'A256GCM' } details = { 'fields': [{ 'name': 'username', 'type': 'T', 'value': user }, { 'name': 'password', 'type': 'P', 'value': password }] } iv = read_default(name + 'det_iv') iv, enc_details = optestlib.enc_aes_gcm(json.dumps(details), sym_keys[ekid], iv) det_dat = { 'data': optestlib.opb64e(enc_details), 'iv': optestlib.opb64e(iv), 'kid': ekid, 'cty': 'b5+jwk+json', 'enc': 'A256GCM' } out = { 'vault': vault, 'item_num': name, 'overview': ov_dat, 'details': det_dat } items[name] = out
def gen_rsa_key(ekid, pub=None, priv=None): if priv == None: new_priv = RSA.generate(2048) jwk_priv = RSAKey(key=new_priv).to_dict() iv = None else: iv = optestlib.opb64d(priv['iv']) jwk_priv = priv['key'] if pub == None: new_pub = new_priv.publickey() jwk_pub = RSAKey(key=new_pub).to_dict() else: jwk_pub = pub jwk_priv['alg'] = 'RSA-OAEP' jwk_priv['key_ops'] = ['decrypt'] jwk_priv['kid'] = ekid jwk_pub['key_ops'] = ['encrypt'] jwk_pub['alg'] = 'RSA-OAEP' jwk_pub['ext'] = True jwk_pub['kid'] = ekid optestlib.p_str("New Private key", json.dumps(jwk_priv, indent=4)) pri_keys[ekid] = jwk_priv pub_keys[ekid] = jwk_pub key_dat_str = json.dumps(jwk_priv) optestlib.p_debug('\n*** Encrypting pri key with AES kid %s' % ekid) iv, ct = optestlib.enc_aes_gcm(key_dat_str, sym_keys[ekid], iv=iv) optestlib.p_data('IV', iv, dump=False) optestlib.p_data('KEY', sym_keys[ekid], dump=False) optestlib.p_data('Ciphertext', ct, dump=False) priv_out = { 'kid': ekid, 'cty': 'b5+jwk+json', 'enc': 'A256GCM', 'data': optestlib.opb64e(ct), 'iv': optestlib.opb64e(iv) } optestlib.p_str("New Public key", json.dumps(jwk_pub, indent=4)) return jwk_pub, priv_out
def enc_mac_login(kid, mac_login_data): out_pt = json.dumps(mac_login_data) iv = read_default('mac_enc_login_iv') iv, ct = optestlib.enc_aes_gcm(out_pt, sym_keys[kid], iv=iv) out = { 'iv': optestlib.opb64e(iv), 'data': optestlib.opb64e(ct), 'enc': 'A256GCM', 'cty': 'b5+jwk+json', 'kid': kid } optestlib.p_str('Encrypted macOS enc_login:', out) return out
def gen_old_vault_data(): out = {} m_key = sym_keys['opv-mk'] m_hmac = sym_keys['opv-mk-hmac'] o_key = sym_keys['opv-ok'] o_hmac = sym_keys['opv-ok-hmac'] o_data = '{"title":"Vault entry for local private vaults","url":"www.example.com","ainfo":"-","ps":75}' o_data_enc = optestlib.encrypt_opdata(o_data, o_key, o_hmac) out['overview_data'] = optestlib.opb64e(o_data_enc) ik_iv = read_default('priv_vault_data.ik_iv') or get_random_bytes(16) ik_key = read_default('priv_vault_data.ik_key') or get_random_bytes(32) ik_hmac = read_default('priv_vault_data.ik_hmac') or get_random_bytes(32) ik_padding = read_default('priv_vault_data.ik_padding') optestlib.p_data('Item key IV', ik_iv) optestlib.p_data('Item key', ik_key) optestlib.p_data('Item HMAC key', ik_hmac) item_key_data = optestlib.encrypt_tag_cbc(ik_key + ik_hmac, ik_iv, m_key, m_hmac) check = optestlib.decrypt_verify_cbc(item_key_data, m_key, m_hmac) out['key_data'] = optestlib.opb64e(item_key_data) item_data = '{"fields": [ { "id": "OldPassword;opid=__2", "name": "OldPassword", "type": "P", "value": "notagoodpassword" }, { "designation": "password", "id": "NewPassword;opid=__3", "name": "NewPassword", "type": "P", "value": "OldSk00lRulzFTW!" } ] }' item_data_enc = optestlib.encrypt_opdata(item_data, ik_key, ik_hmac, iv=ik_iv, padding=ik_padding) out['data'] = optestlib.opb64e(item_data_enc) return out
def gen_vault_entry(name, ekid): global vaults out = {'enc': 'A256GCM', 'kid': ekid, 'cty': 'b5+jwk+json'} uuid = read_default(name + '.vault_uuid', decode=False) or gen_uuid() attrs = { 'uuid': uuid, 'name': 'Test vault: %s' % name, 'type': 'P', 'desc': 'unk-b64-blob', 'avatar': '' } iv = read_default(name + '.iv') iv, enc_attrs = optestlib.enc_aes_gcm(json.dumps(attrs), sym_keys[ekid], iv=iv) out['data'] = optestlib.opb64e(enc_attrs) out['iv'] = optestlib.opb64e(iv) vaults[name] = out
def enc_win_login(): optestlib.p_debug('\n** Windows login details for accounts table') data = json.dumps({'accountKey': SecretKey, 'password': MasterPassword}) iv = read_default('win_enc_login_iv') padding = read_default('win_enc_login_padding') op_msg = optestlib.encrypt_opdata(data, sym_keys['win-mk'], sym_keys['win-mk-hmac'], iv=iv, padding=padding) return optestlib.opb64e(op_msg)
def gen_local_vault_keys(): global sym_keys optestlib.p_debug( '\n** Generating MasterKey (MK) and OverviewKey (OK) (OnePassword local private vaults)' ) salt = read_default('local_vault.salt') or get_random_bytes(16) mkd = read_default('local_vault.mk.data') or get_random_bytes(256) mk_iv = read_default('local_vault.mk.iv') mk_padding = read_default('local_vault.mk.padding') okd = read_default('local_vault.ok.data') or get_random_bytes(64) ok_iv = read_default('local_vault.ok.iv') ok_padding = read_default('local_vault.ok.padding') data = optestlib.gen_local_vault_keys(MasterPassword, salt, mkd, mk_iv, mk_padding, okd, ok_iv, ok_padding) sym_keys['opv-mk'] = data['master_key'] sym_keys['opv-mk-hmac'] = data['master_key_hmac'] sym_keys['opv-ok'] = data['overview_key'] sym_keys['opv-ok-hmac'] = data['overview_key_hmac'] enc_master_key = data['enc_master_key_data'] enc_overview_key = data['enc_overview_key_data'] profile_data = { 'salt': optestlib.opb64e(salt), 'iterations': opk_iter, 'overview_key_data': optestlib.opb64e(enc_overview_key), 'master_key_data': optestlib.opb64e(enc_master_key) } return profile_data
def gen_local_login(mac_login): iv = read_default('local_vault.enc_login.iv') padding = read_default('local_vault.enc_login.padding') op_mk = sym_keys['opv-mk'] op_mk_hmac = sym_keys['opv-mk-hmac'] enc_login = optestlib.encrypt_opdata(json.dumps(mac_login), op_mk, op_mk_hmac, iv=iv, padding=padding) account_data = {'enc_login': optestlib.opb64e(enc_login)} return account_data
def gen_emk(): global sym_keys optestlib.p_debug('\n** Generating Encrypted Master Key (EMK) block') win_mk = read_default('win_mk') or get_random_bytes(32) sym_keys['win-mk'] = win_mk win_mk_hmac = read_default('win_mk_hmac') or get_random_bytes(32) sym_keys['win-mk-hmac'] = win_mk_hmac optestlib.p_data('New MK', win_mk) optestlib.p_data('New MK HMAC Key', win_mk_hmac) emk_salt = read_default('emk_salt') or get_random_bytes(emk_slen) raw_derived_key = hashlib.pbkdf2_hmac('sha512', MasterPassword, emk_salt, emk_iter, 64) enc_key = raw_derived_key[0:32] enc_hmac_key = raw_derived_key[32:64] optestlib.p_data('MP-derived key', enc_key) optestlib.p_data('MP-derived HMAC key', enc_hmac_key) iv = read_default('win_emk_iv') padding = read_default('win_emk_padding') op_msg = optestlib.encrypt_opdata(win_mk + win_mk_hmac, enc_key, enc_hmac_key, iv=iv, padding=padding) emk = struct.pack('<I', emk_iter) # iterations emk += struct.pack('<I', emk_slen) # salt length emk += emk_salt emk += struct.pack('<I', len(op_msg)) emk += op_msg optestlib.p_data('Final EMK block', emk) return optestlib.opb64e(emk)
def gen_keyset(name, ekid): optestlib.p_debug('** Generating %s - encrypted by %s' % (name, ekid)) out = {'encrypted_by': ekid} iv = None try: if ekid == 'mp': iv = read_default(name + '.sym.iv') new_kid = read_default(name + '.uuid', decode=False) new_key = read_default(name + '.sym.k') kid, sym_key = gen_sym_key(ekid, new_kid=new_kid, iv=iv, k=new_key) new_pub = read_default(name + '.pub', decode=False) new_priv = read_default(name + '.priv', decode=False) rsa_pub, rsa_priv = gen_rsa_key(kid, pub=new_pub, priv=new_priv) except: kid, sym_key = gen_sym_key(ekid) rsa_pub, rsa_priv = gen_rsa_key(kid) if ekid == 'mp': sym_keys['mk'] = sym_keys[kid] sym_key['p2s'] = optestlib.opb64e(p2s_muk) sym_key['p2c'] = p2c_muk sym_key['alg'] = alg_muk out['uuid'] = kid out['enc_sym_key'] = sym_key out['enc_pri_key'] = rsa_priv out['pub_key'] = rsa_pub keysets[kid] = out return kid
enc_master_key_data = optestlib.get_binary( " Enter master_key_data (hex or base64): ") enc_overview_key_data = optestlib.get_binary( " Enter overview_key_data (hex or base64): ") mk, mk_hmac, ok, ok_hmac = optestlib.get_local_vault_keys( password, salt, enc_master_key_data, enc_overview_key_data) print "\n* Derived/Decrypted/Derived Vault Keys" optestlib.p_data('Master Key', mk, dump=False) optestlib.p_data('Master HMAC Key', mk_hmac, dump=False) optestlib.p_data('Overview Key', ok, dump=False) optestlib.p_data('Overview HMAC Key', ok_hmac, dump=False) print "\n(Base-64 versions for convenience:" optestlib.p_str('Master key', optestlib.opb64e(mk)) optestlib.p_str('Master HMAC key', optestlib.opb64e(mk_hmac)) optestlib.p_str('Overview key', optestlib.opb64e(ok)) optestlib.p_str('Overview HMAC key', optestlib.opb64e(ok_hmac)) enc_login_data = optestlib.get_binary( "\nEnter encrypted login data (from accounts table) (hex / base64): ") PT = optestlib.decrypt_opdata(enc_login_data, mk, mk_hmac) optestlib.p_str('Decrypted enc_login', PT)
# # David Schuetz # November 2018 # # https://github.com/dschuetz/1password # # Given EMK blob from Windows "1Password10.sqlite" database, # and user's primary account Master Password, # decrypts EMK blob to produce master encryption and HMAC keys # import optestlib bin_emk = optestlib.get_binary( 'Enter EMK data (from config table) in base-64 or hex: ') password = raw_input("\nEnter the master password: ") PT = optestlib.decrypt_emk(bin_emk, password) enc_key = PT[0:32] hmac_key = PT[32:] optestlib.p_data('Master Enc Key', enc_key) optestlib.p_str('(base-64)', optestlib.opb64e(enc_key)) optestlib.p_data('Master HMAC Key', hmac_key) optestlib.p_str('(base-64)', optestlib.opb64e(hmac_key)) optestlib.p_str('Enc+HMAC together', optestlib.opb64e(enc_key + hmac_key))
# # Given email, Secret Key, Master Password, and elements from "enc_sym_key" # from the primary account's first keyset ("encrypted_by = mp"), # computes 1Password 2SKD result for MUK and SRP-X # import optestlib secret_key = raw_input( "\nEnter the account's Secret Key (A3-xxx....): ").upper() password = raw_input("\nEnter the master password:"******"\nEnter the email address: ") p2s = optestlib.get_binary( "\nEnter the 'p2s' parameter (salt, base-64 or hex encoded): ") p2c = raw_input("\nEnter the 'p2c' parameter (iterations count): ") p2c = int(p2c) algo = raw_input( "\nEnter the 'alg' parameter\n (PBES2g-HS256 for MUK, SRPg-4096 for SRP-x) (note: case sensitive): " ) print "\n" muk = optestlib.compute_2skd(secret_key, password, email, p2s, p2c, algo) optestlib.p_str('\nBase-64 Encoded result:', optestlib.opb64e(muk))
def main(): global p2s_muk, p2s_srp optestlib.p_debug(" *** Generating Test Data ***") optestlib.p_debug( "\n\n**************************************************************") optestlib.p_debug('* Deriving Master Unlock Key (MUK) (AES kid mp)') p2s_muk = read_default('muk_salt') or get_random_bytes(16) MUK = optestlib.compute_2skd(SecretKey, MasterPassword, Email, p2s_muk, p2c_muk, alg_muk) sym_keys['mp'] = MUK optestlib.p_debug( "\n\n**************************************************************") optestlib.p_debug('* Deriving SRP-X') p2s_srp = read_default('srp_salt') or get_random_bytes(16) SRPx = optestlib.compute_2skd(SecretKey, MasterPassword, Email, p2s_srp, p2c_srp, alg_srp) sym_keys['srp-x'] = SRPx optestlib.p_debug( "\n\n**************************************************************") optestlib.p_debug('* Generating keyset1') keyset1_kid = gen_keyset('keyset1', 'mp') optestlib.p_debug( "\n\n**************************************************************") optestlib.p_debug('* Generating keyset2') keyset2_kid = gen_keyset('keyset2', keyset1_kid) optestlib.p_debug( "\n\n**************************************************************") optestlib.p_debug('* Generating login detail records') mac_login_data = gen_mac_login() mac_login = enc_mac_login(keyset1_kid, mac_login_data) optestlib.p_debug('\n* Generating Windows EMK') emk = gen_emk() optestlib.p_debug('\n* Generating Windows login details') win_login = enc_win_login() optestlib.p_debug('\n* Generating private vault unlock keys') op_local_vault_keys = gen_local_vault_keys() op_local_vault_login = gen_local_login(mac_login_data) optestlib.p_debug( "\n\n**************************************************************") optestlib.p_debug('* Generating vaults') vault1_kid = gen_vault_key('vault1', keyset1_kid) gen_vault_entry('vault1', vault1_kid) optestlib.p_debug( "\n\n**************************************************************") optestlib.p_debug('* Generating vault items') uuid = read_default('items.1.uuid') gen_item('items.1', 'vault1', uuid, title='My test!', url='https://example.com', user='******', password='******') optestlib.p_debug('** Local private vault item') old_vault_data = gen_old_vault_data() print "\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n" print " *** Generated Data ***\n" print("MUK data:") print(" Password: %s" % MasterPassword) print(" Secret Key: %s" % SecretKey) print(" Email: %s" % Email) print(" p2s: %s" % optestlib.opb64e(p2s_muk)) print(" p2c: %d" % p2c_muk) print(" alg: %s" % alg_muk) print(" MUK: %s" % optestlib.opb64e(MUK)) print("\nSRP data") print(" p2s: %s" % optestlib.opb64e(p2s_srp)) print(" p2c: %d" % p2c_srp) print(" alg: %s" % alg_srp) print(" SRP-X: %s" % optestlib.opb64e(SRPx)) print("\n\nMaster key (mk): %s" % optestlib.opb64e(sym_keys['mk'])) print("\n\nSymmetric Keys (kid, base64-encoded key):") for k in sorted(sym_keys): print(" %-26s %s" % (k, optestlib.opb64e(sym_keys[k]))) print("\n\nPublic Keys (kid, json dump of key):") for k in sorted(pub_keys): print(" %-26s %s\n" % (k, json.dumps(pub_keys[k], indent=4))) print("\n\nPrivate Keys (kid, json dump of key):") for k in sorted(pri_keys): print(" %-26s %s\n" % (k, json.dumps(pri_keys[k], indent=4))) print("\nKeyset 1:\n%s" % json.dumps(keysets[keyset1_kid], indent=4)) print("\nKeyset 2:\n%s" % json.dumps(keysets[keyset2_kid], indent=4)) print("\nmacOS enc_login:\n%s" % json.dumps(mac_login, indent=4)) print("\nEMK:\n%s" % emk) print("\nWindows enc_login:\n%s" % win_login) print("\nLocal vault key data:\n%s" % json.dumps(op_local_vault_keys, indent=4)) print("\nAccount enc_login encrypted for local vaults:\n%s" % json.dumps(op_local_vault_login, indent=4)) for vault in ['vault1']: print("\nVault Data for %s:\n" % vault) print(" * Vault access key\n%s" % (json.dumps(vault_access[vault]))) print(" * Vault attributes\n%s" % (json.dumps(vaults[vault]))) print("\nEncrypted vault items") for item in items: print json.dumps(items[item]), "\n" print("\nLocal private vault item") print json.dumps(old_vault_data)