<p>You are hashing everything as hex strings. However that is not the proper way to hash stuff. They should all be hashed as bytes (i.e. the raw data), not strings of hexadecimal.</p>

CC BY-SA 3.0
2017-11-05T04:31:11.423Z
Unless I am mistaken the package I am using, crypto-js, takes in a string. Does this alter the data in a way that will result in incorrect hashes?
crypto_rob
CC BY-SA 3.0
2017-11-05T04:35:31.757Z
Yes, that will result in incorrect hashes. It takes in a string, and hashes that string. It does not seem to convert that string to the bytes that the string represents so that will result in a different hash.
Ava Chow
CC BY-SA 3.0
2017-11-05T04:38:13.253Z
Ok, so to confirm, I should take the uncompressed public key, then convert it to bytes if it isn't already bytes, hash that (SHA256). Then, take the bytes from that hash and hash it again (RIPEMD160). So basically convert to bytes each time before hashing?
crypto_rob
CC BY-SA 3.0
2017-11-05T04:50:05.713Z
Yes, everything should be bytes, not a hex string representing the bytes.
Ava Chow
CC BY-SA 3.0
2017-11-05T04:08:07.373Z
2017-11-05T04:08:07.373Z
Ava Chow
<p>I am following the process for bitcoin address creation as outlined in Mastering Bitcoin, however, when I try to reference this address in my <code>bitcoin-cli</code>, which is set to regtest, it responds with an invalid address error. I am attempting to write some JS to interact with my bitcoin node via the bitcoin-core package, but instead of just using all the built in commands, write some of the code myself to solidify my understanding.</p>
<p>I am using the following npm packages:</p>
<pre><code>const EC = require('elliptic').ec;
const ec = new EC('secp256k1');
const bs58 = require('bs58')
const SHA256 = require(&quot;crypto-js/sha256&quot;);
const RIPEMD160 = require(&quot;crypto-js/ripemd160&quot;);
</code></pre>
<p>Here is my address creation function.</p>
<pre><code>function createNewAddress() {
  // Get the private key
  const privateKey = ec.genKeyPair()
  // Get the public point from the private key
  const publicPoint = privateKey.getPublic();
  // Uncompressed public key
  const uncompressedPK = publicPoint.encode('hex');
  // SHA256 then RIPEMD160, aka HASH160
  const hashedPK = RIPEMD160(SHA256(uncompressedPK).toString()).toString();
  // Prepend the version, here we use 6F got the testnet (we are using regtest)
  const prependedPK = &quot;6F&quot;+hashedPK;
  // Calculate the checksum and take the first 4 btyes
  const checksum = SHA256(SHA256(prependedPK).toString()).toString().substring(0,9);
  // Append the checksum to the end
  const unencodedPK = prependedPK + checksum;
  // Base58Encode the unencodedPK
  const bytes = Buffer.from(unencodedPK, 'hex');
  const bitcoinAddress = bs58.encode(bytes);
  return (bitcoinAddress);
}
</code></pre>
<p>Here is a simple output:
mtURXDaisk6ustpeo7LuiZYje9yV31JhBN</p>

CC BY-SA 3.0
2017-11-05T03:30:30.130Z
That's a testnet versioned P2PKH address.
Claris
CC BY-SA 3.0
2017-11-05T04:02:02.020Z
I was looking for a regtest prefix here: https://en.bitcoin.it/wiki/List_of_address_prefixes could not find one
crypto_rob
CC BY-SA 3.0
2017-11-05T04:08:18.080Z
regtest and testnet use the same version byte.
Ava Chow
CC BY-SA 3.0
2017-11-05T04:26:10.780Z
That is what I figured
crypto_rob
<address-generation><javascript><mastering-bitcoin>
Generate Bitcoin Address JS Step-By-Step "Invalid Address" Error
crypto_rob
# Generate Bitcoin Address JS Step-By-Step "Invalid Address" Error

(Asked by: username_0 on 2017-11-05)

I am following the process for bitcoin address creation as outlined in Mastering Bitcoin, however, when I try to reference this address in my bitcoin-cli, which is set to regtest, it responds with an invalid address error. I am attempting to write some JS to interact with my bitcoin node via the bitcoin-core package, but instead of just using all the built in commands, write some of the code myself to solidify my understanding.
I am using the following npm packages:
const EC = require('elliptic').ec;
const ec = new EC('secp256k1');
const bs58 = require('bs58')
const SHA256 = require("crypto-js/sha256");
const RIPEMD160 = require("crypto-js/ripemd160");

Here is my address creation function.
function createNewAddress() {
  // Get the private key
  const privateKey = ec.genKeyPair()
  // Get the public point from the private key
  const publicPoint = privateKey.getPublic();
  // Uncompressed public key
  const uncompressedPK = publicPoint.encode('hex');
  // SHA256 then RIPEMD160, aka HASH160
  const hashedPK = RIPEMD160(SHA256(uncompressedPK).toString()).toString();
  // Prepend the version, here we use 6F got the testnet (we are using regtest)
  const prependedPK = "6F"+hashedPK;
  // Calculate the checksum and take the first 4 btyes
  const checksum = SHA256(SHA256(prependedPK).toString()).toString().substring(0,9);
  // Append the checksum to the end
  const unencodedPK = prependedPK + checksum;
  // Base58Encode the unencodedPK
  const bytes = Buffer.from(unencodedPK, 'hex');
  const bitcoinAddress = bs58.encode(bytes);
  return (bitcoinAddress);
}

Here is a simple output:
mtURXDaisk6ustpeo7LuiZYje9yV31JhBN

**Tags:** address-generation, javascript, mastering-bitcoin

> **Comments:**
> **username_1**: That's a testnet versioned P2PKH address.  
> **username_0**: I was looking for a regtest prefix here: https://en.bitcoin.it/wiki/List_of_address_prefixes could not find one  
> **username_2**: regtest and testnet use the same version byte.  
> **username_0**: That is what I figured  

---

## 1 answers

### Answer by username_2 on 2017-11-05. Score: 1 | Accepted answer

You are hashing everything as hex strings. However that is not the proper way to hash stuff. They should all be hashed as bytes (i.e. the raw data), not strings of hexadecimal.

> **Comments:**
> **username_0**: Unless I am mistaken the package I am using, crypto-js, takes in a string. Does this alter the data in a way that will result in incorrect hashes?  
> **username_2**: Yes, that will result in incorrect hashes. It takes in a string, and hashes that string. It does not seem to convert that string to the bytes that the string represents so that will result in a different hash.  
> **username_0**: Ok, so to confirm, I should take the uncompressed public key, then convert it to bytes if it isn't already bytes, hash that (SHA256). Then, take the bytes from that hash and hash it again (RIPEMD160). So basically convert to bytes each time before hashing?  
> **username_2**: Yes, everything should be bytes, not a hex string representing the bytes.  

---

