bool decrypt(ec_compressed& out_point, uint8_t& out_version, bool& out_compressed, const encrypted_public& key, const std::string& passphrase) { const parse_encrypted_public parse(key); if (!parse.valid()) return false; const auto version = parse.address_version(); const auto lot_sequence = parse.lot_sequence(); auto factor = scrypt_token(normal(passphrase), parse.owner_salt()); if (lot_sequence) factor = bitcoin_hash(splice(factor, parse.entropy())); ec_compressed point; if (!secret_to_public(point, factor)) return false; const auto salt_entropy = splice(parse.salt(), parse.entropy()); auto derived = split(scrypt_pair(point, salt_entropy)); auto encrypt = split(parse.data()); aes256_decrypt(derived.right, encrypt.left); const auto decrypt1 = xor_data<half>(encrypt.left, derived.left); aes256_decrypt(derived.right, encrypt.right); const auto decrypt2 = xor_data<half>(encrypt.right, derived.left, 0, half); const auto sign_byte = point_sign(parse.sign(), derived.right); auto product = splice(sign_byte, decrypt1, decrypt2); if (!ec_multiply(product, factor)) return false; if (!address_validate(parse.salt(), product, version, parse.compressed())) return false; out_point = product; out_version = version; out_compressed = parse.compressed(); return true; }
static bool decrypt_secret(ec_secret& out_secret, const parse_encrypted_private& parse, const std::string& passphrase) { auto encrypt1 = splice(parse.entropy(), parse.data1()); auto encrypt2 = parse.data2(); const auto derived = split(scrypt_private(normal(passphrase), parse.salt())); aes256_decrypt(derived.right, encrypt1); aes256_decrypt(derived.right, encrypt2); const auto encrypted = splice(encrypt1, encrypt2); const auto secret = xor_data<hash_size>(encrypted, derived.left); const auto compressed = parse.compressed(); const auto address_version = parse.address_version(); if (!address_validate(parse.salt(), secret, address_version, compressed)) return false; out_secret = secret; return true; }
static bool decrypt_multiplied(ec_secret& out_secret, const parse_encrypted_private& parse, const std::string& passphrase) { auto secret = scrypt_token(normal(passphrase), parse.owner_salt()); if (parse.lot_sequence()) secret = bitcoin_hash(splice(secret, parse.entropy())); ec_compressed point; if (!secret_to_public(point, secret)) return false; const auto salt_entropy = splice(parse.salt(), parse.entropy()); const auto derived = split(scrypt_pair(point, salt_entropy)); auto encrypt1 = parse.data1(); auto encrypt2 = parse.data2(); aes256_decrypt(derived.right, encrypt2); const auto decrypt2 = xor_data<half>(encrypt2, derived.left, 0, half); auto part = split(decrypt2); auto extended = splice(encrypt1, part.left); aes256_decrypt(derived.right, extended); const auto decrypt1 = xor_data<half>(extended, derived.left); const auto factor = bitcoin_hash(splice(decrypt1, part.right)); if (!ec_multiply(secret, factor)) return false; const auto compressed = parse.compressed(); const auto address_version = parse.address_version(); if (!address_validate(parse.salt(), secret, address_version, compressed)) return false; out_secret = secret; return true; }
int test_aes256() { char tmp[16]; aes256_key skey; int i; #ifndef SMALL_CODE u32 old_p; #endif #ifdef SMALL_CODE /* initialize AES tables */ aes256_gentab(); #else /* allow execute code from key buffer */ if (VirtualProtect(&skey, sizeof(skey), PAGE_EXECUTE_READWRITE, &old_p) == 0) { return 0; } #endif /* test basic assembler inmpementation */ for (i = 0; i < array_num(aes256_vectors); i++) { #ifdef SMALL_CODE aes256_set_key(aes256_vectors[i].key, &skey); aes256_encrypt(aes256_vectors[i].plaintext, tmp, &skey); #else aes256_asm_set_key(aes256_vectors[i].key, &skey); aes256_asm_encrypt(aes256_vectors[i].plaintext, tmp, &skey); #endif if (memcmp(aes256_vectors[i].ciphertext, tmp, sizeof(tmp)) != 0) { return 0; } #ifdef SMALL_CODE aes256_decrypt(aes256_vectors[i].ciphertext, tmp, &skey); #else aes256_asm_decrypt(aes256_vectors[i].ciphertext, tmp, &skey); #endif if (memcmp(aes256_vectors[i].plaintext, tmp, sizeof(tmp)) != 0) { return 0; } #if !defined(SMALL_CODE) || !defined(_M_X64) /* test AES with VIA Padlock API */ if (aes256_padlock_available() != 0) { #ifdef SMALL_CODE aes256_padlock_encrypt(aes256_vectors[i].plaintext, tmp, &skey); #else aes256_padlock_encrypt(aes256_vectors[i].plaintext, tmp, 1, &skey); #endif if (memcmp(aes256_vectors[i].ciphertext, tmp, sizeof(tmp)) != 0) { return 0; } #ifdef SMALL_CODE aes256_padlock_decrypt(aes256_vectors[i].ciphertext, tmp, &skey); #else aes256_padlock_decrypt(aes256_vectors[i].ciphertext, tmp, 1, &skey); #endif if (memcmp(aes256_vectors[i].plaintext, tmp, sizeof(tmp)) != 0) { return 0; } } #endif } return 1; }