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; }
static bool address_validate(const ek_salt& salt, const ec_secret& secret, uint8_t version, bool compressed) { payment_address address({ secret, version, compressed }); return address ? address_validate(salt, address) : false; }
diag_t jz_msg_validate (JzMsg *self) { g_assert (self); if (self->signature != JZ_MSG_SIGNATURE) return d_invalid_signature; else if (self->version != 1) return d_unknown_version; else if (self->id < 0 || self->id >= JZ_MSG_COUNT) return d_unknown_message_type; #if 0 // Try to keep this alphabetized else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST || self->id == JZ_MSG_CLEAR_REQUEST) { if (self->lcn <= 0 || self->lcn > JZ_MSG_MAX_LCN) return d_invalid_lcn; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST ) { if (packet_rngchk (self->packet) < 0) return d_invalid_packet_facility; else if (packet_rngchk (self->packet) > 0) return d_invalid_packet_facility; else if (tput_rngchk (self->throughput) < 0) return d_invalid_throughput_facility; else if (tput_rngchk (self->throughput) > 0) return d_invalid_throughput_facility; else if (window_rngchk (self->window) < 0) return d_invalid_window_facility; else if (window_rngchk (self->window) > 0) return d_invalid_window_facility; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST ) { if (!address_validate(self->called_address)) return d_invalid_called_address; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST || self->id == JZ_MSG_CLEAR_CONFIRMATION || self->id == JZ_MSG_CONNECT ) { if (!address_validate(self->calling_address)) return d_invalid_calling_address; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST) { // Zero-length data frames are OK!! if (self->data->len > JZ_MSG_MAX_CALL_REQUEST_DATA_SIZE) return d_data_too_long; } else if (self->id == JZ_MSG_DATA) { // zero-length data frames are not allowed!! if (self->data->len == 0) return d_data_too_short; else if (self->data->len > JZ_MSG_MAX_DATA_SIZE) return d_data_too_long; } else if (self->id == JZ_MSG_CLEAR_REQUEST || self->id == JZ_MSG_DIAGNOSTIC || self->id == JZ_MSG_RESET_REQUEST) { if (!cause_validate (self->cause)) return d_invalid_cause; if (!diag_validate (self->diagnostic)) return d_invalid_diagnostic; } else if (self->id == JZ_MSG_DATA) { if (!q_validate (self->q)) return d_invalid_q; else if (seq_rngchk (self->ps) != 0) return d_invalid_ps; } else if (self->id == JZ_MSG_DATA || self->id == JZ_MSG_RR || self->id == JZ_MSG_RNR) { if (seq_rngchk (self->pr) != 0) return d_invalid_pr; } else if (self->id == JZ_MSG_CONNECT) { if (!iodir_validate (self->iodir)) return d_invalid_directionality_facility; else if (self->hostname != NULL) { if (!g_utf8_validate (self->hostname, -1, NULL) || g_utf8_strlen (self->hostname, -1) > JZ_MSG_MAX_HOSTNAME_LENGTH) return d_invalid_hostname; } } #if 0 case JZ_MSG_DIRECTORY: GET_NUMBER1 (hash_size); self->workers = zhash_new (); zhash_autofree (self->workers); while (hash_size--) { char *string; GET_STRING (string); char *value = strchr (string, '='); if (value) *value++ = 0; zhash_insert (self->workers, string, value); free (string); } #endif #endif return d_ok; }