def encrypt(raw, password, salt_mask, key_sz, key_iter, hmac_key_sz, hmac_key_iter, page_sz, iv_sz, reserve_sz, hmac_sz): salt_sz = 16 salt = util.random_bytes(salt_sz) enc = salt # derive key key, hmac_key = util.key_derive(salt, password, salt_mask, key_sz, key_iter, hmac_key_sz, hmac_key_iter) # encrypt pages for i in range(0, int(len(raw) / 1024)): page = util.get_page(raw, page_sz, i + 1) if i == 0: # skip header string page = page[salt_sz:] page_content = page[:-reserve_sz] iv = util.random_bytes(iv_sz) # encrypt content page_enc = util.encrypt(page_content, key, iv) # generate hmac hmac_new = util.generate_hmac(hmac_key, page_enc + iv, i + 1) enc += page_enc + iv + hmac_new if reserve_sz > iv_sz + hmac_sz: enc += util.random_bytes(reserve_sz - iv_sz - hmac_sz) return enc
def decrypt(raw, password, salt_mask, key_sz, key_iter, hmac_key_sz, hmac_key_iter, page_sz, iv_sz, reserve_sz, hmac_sz): dec = b'SQLite format 3\0' # derive key salt_sz = 16 salt = raw[:salt_sz] key, hmac_key = util.key_derive(salt, password, salt_mask, key_sz, key_iter, hmac_key_sz, hmac_key_iter) # decrypt file header, try with default page size page_sz, reserve_sz = decrypt_page_header(raw, key, salt_sz, page_sz, iv_sz, reserve_sz) if page_sz < 0 or reserve_sz < 0: raise RuntimeError('failed to decide page size or reserve size.') # decrypt pages for i in range(0, int(len(raw) / 1024)): page = util.get_page(raw, page_sz, i + 1) if i == 0: # skip salt page = page[salt_sz:] page_content = page[:-reserve_sz] reserve = page[-reserve_sz:] iv = reserve[:iv_sz] # check hmac hmac_old = reserve[iv_sz:iv_sz + hmac_sz] hmac_new = util.generate_hmac(hmac_key, page_content + iv, i + 1) if not hmac_old == hmac_new: raise RuntimeError('hmac check failed in page %d.' % (i + 1)) # decrypt content page_dec = util.decrypt(page_content, key, iv) dec += page_dec + util.random_bytes(reserve_sz) return dec
def try_get_reserve_size_for_specified_page_size(raw, key, salt_sz, page_sz, iv_sz, reserve_sz): """Try to decrypt first page with specified page size. If default reserve size fail, change reserve size. When succeed, return reserve size. If always fail, return -1. """ first_page_content = util.get_page(raw, page_sz, 1)[salt_sz:] if reserve_sz >= iv_sz: first_page_dec = decrypt_by_reserve_size(first_page_content, key, iv_sz, reserve_sz) # default reserve_sz is ok if util.is_valid_decrypted_header(first_page_dec) \ and page_sz == util.get_page_size_from_database_header(raw[:salt_sz] + first_page_dec) \ and reserve_sz == util.get_reserved_size_from_database_header(raw[:salt_sz] + first_page_dec): return reserve_sz # try every possible reserve size. # the usable size of a page is at least 480. for reserve_sz in range(iv_sz, page_sz - 480): first_page_dec = decrypt_by_reserve_size(first_page_content, key, iv_sz, reserve_sz) if util.is_valid_decrypted_header(first_page_dec) \ and page_sz == util.get_page_size_from_database_header(raw[:salt_sz] + first_page_dec) \ and reserve_sz == util.get_reserved_size_from_database_header(raw[:salt_sz] + first_page_dec): return reserve_sz return -1 # fail
def decrypt(raw, password, salt_mask, key_sz, key_iter, hmac_key_sz, hmac_key_iter, page_sz, iv_sz, reserve_sz, hmac_sz): dec = b'SQLite format 3\0' # derive key salt_sz = 16 salt = raw[:salt_sz] key, hmac_key = util.key_derive(salt, password, salt_mask, key_sz, key_iter, hmac_key_sz, hmac_key_iter) # decrypt file header, try with default page size page_sz, reserve_sz = decrypt_page_header(raw, key, salt_sz, page_sz, iv_sz, reserve_sz) if page_sz < 0 or reserve_sz < 0: raise RuntimeError('failed to decide page size or reserve size.') # decrypt pages for i in range(0, int(len(raw) / 1024)): page = util.get_page(raw, page_sz, i + 1) if i == 0: # skip salt page = page[salt_sz:] page_content = page[:-reserve_sz] reserve = page[-reserve_sz:] iv = reserve[:iv_sz] # check hmac hmac_old = reserve[iv_sz:iv_sz+hmac_sz] hmac_new = util.generate_hmac(hmac_key, page_content + iv, i + 1) if not hmac_old == hmac_new: raise RuntimeError('hmac check failed in page %d.' % (i+1)) # decrypt content page_dec = util.decrypt(page_content, key, iv) dec += page_dec + util.random_bytes(reserve_sz) return dec