├── .gitignore
├── README.md
├── package.json
├── private-key-generator.js
└── public-key-generator
    ├── Makefile
    └── ecdsapubkey.c
/.gitignore:
--------------------------------------------------------------------------------
1 | .*~
2 | *~
3 | node_modules/
4 | public-key-generator/ecdsapubkey
5 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | Bitcoin 2 of 3 Multisig
  2 | =========
  3 | 
  4 | This is an example walkthrough of using bitcoind RPC commands to generate a 2
  5 | of 3 multisignature address. We will:
  6 | 
  7 |   - Generate three private keys
  8 |   - Find the ECDSA public key for each address
  9 |   - Generate a 2 of 3 multisig address
 10 |   - Send coins to the multisig address
 11 |   - Generate a transaction to spend funds out of the multisig address
 12 |   - Sign the transaction with two of the keys
 13 |   - Broadcast that transaction on the network
 14 | 
 15 | Prerequisites
 16 | --------------
 17 | 
 18 |   - bitcoind (in particular, bitcoin-cli - you don't need a full copy of the blockchain)
 19 |   - node.js
 20 |   - c++
 21 | 
 22 | Installation
 23 | --------------
 24 | 
 25 | ```sh
 26 | npm install
 27 | cd public-key-generator
 28 | make
 29 | cd ..
 30 | ```
 31 | 
 32 | Steps
 33 | -----
 34 | First we will generate some private keys. It is very important that this
 35 | process is as random as possible. I'd suggest a hardware true random number
 36 | generator such as the [FST-01](https://www.youtube.com/watch?v=iDuhLQ43tvQ).
 37 | 
 38 | ```sh
 39 | node private-key-generator
 40 | ```
 41 | 
 42 | You will get something like this:
 43 | 
 44 | ```sh
 45 | Private Key in Hex: f3d03f863d9dd6ed35b9c15739f34d8c8fdd07797cc5cc6f2e610721d06bb816
 46 | Private Key in WIF: 5KffUB9YUsvoGjrcn76PjVnC61PcWLzws4QPfrT9RFNd85utCkZ
 47 | ```
 48 | Note: WIF stands for Wallet Import Format - a bitcoin specific way of representing 
 49 | an address which includes a checksum capability.
 50 | 
 51 | You will want to generate a total of three private keys. Here is a second one:
 52 | 
 53 | ```sh
 54 | Private Key in Hex: e919e62a30f8ca06b66d7c9c22c176c77646c3db2c06d3ed1db0a9b2cc9f4b58
 55 | Private Key in WIF: 5KawqZHB1H6Af12ZhgTBXwQUY1jACgvGMywET7NF5bdYYzCxomY
 56 | ```
 57 | 
 58 | And a last one:
 59 | 
 60 | ```sh
 61 | Private Key in Hex: f99974355fbe8865e522643421914acb8f3efc0e3a1a746aa2fe68993e700d4e
 62 | Private Key in WIF: 5KiDGG8sfmTNnzKDmm1MteWHV2TQQaUBbaEY3huVLwVz1i6i5be
 63 | ```
 64 | 
 65 | Next you will want to generate a ECDSA public key that corrosponds to each of
 66 | the private keys. Let's use the hex value of each private key to find an associated
 67 | ECDSA public key:
 68 | 
 69 | ```sh
 70 | cd public-key-generator
 71 | ./ecdsapubkey f3d03f863d9dd6ed35b9c15739f34d8c8fdd07797cc5cc6f2e610721d06bb816
 72 | 04A97B658C114D77DC5F71736AB78FBE408CE632ED1478D7EAA106EEF67C55D58A91C6449DE4858FAF11721E85FE09EC850C6578432EB4BE9A69C76232AC593C3B
 73 | ./ecdsapubkey e919e62a30f8ca06b66d7c9c22c176c77646c3db2c06d3ed1db0a9b2cc9f4b58
 74 | 04019EF04A316792F0ECBE5AB1718C833C3964DEE3626CFABE19D97745DBCAA5198919081B456E8EEEA5898AFA0E36D5C17AB693A80D728721128ED8C5F38CDBA0
 75 | ./ecdsapubkey f99974355fbe8865e522643421914acb8f3efc0e3a1a746aa2fe68993e700d4e
 76 | 04A04F29F308160E6F945B33D943304B1B471ED8F9EACEEB5412C04E60A0FAB0376871D9D1108948B67CAFBC703E565A18F8351FB8558FD7C7482D7027EECD687C
 77 | ```
 78 | 
 79 | Now we will create our multisig address given the three hex public keys. The parameter "2"
 80 | tells bitcoind to create an address that requires the signature of at least two private keys.
 81 | The fact that we are presenting three ECDSA keys as well is what makes it a two of three 
 82 | address. You can use any number of keys as long as it is equal to or greater than the 
 83 | "minimum required to sign" parameter. Two of two and three of five are other common 
 84 | strategies.
 85 | 
 86 | ```sh
 87 | bitcoin-cli createmultisig 2 '["04A97B658C114D77DC5F71736AB78FBE408CE632ED1478D7EAA106EEF67C55D58A91C6449DE4858FAF11721E85FE09EC850C6578432EB4BE9A69C76232AC593C3B","04019EF04A316792F0ECBE5AB1718C833C3964DEE3626CFABE19D97745DBCAA5198919081B456E8EEEA5898AFA0E36D5C17AB693A80D728721128ED8C5F38CDBA0","04A04F29F308160E6F945B33D943304B1B471ED8F9EACEEB5412C04E60A0FAB0376871D9D1108948B67CAFBC703E565A18F8351FB8558FD7C7482D7027EECD687C"]'
 88 | {
 89 |     "address" : "38aNB81yPqNp6X2T3rXYZN8Z3C4pSbqEvs",
 90 |     "redeemScript" : "524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53ae"
 91 | }
 92 | ```
 93 | 
 94 | So in this case, our address is 38aNB81yPqNp6X2T3rXYZN8Z3C4pSbqEvs. Let's send it some coins:
 95 | 
 96 | ```sh
 97 | bitcoin-cli sendtoaddress 38aNB81yPqNp6X2T3rXYZN8Z3C4pSbqEvs 0.001
 98 | 7e69687c94c57a878cf711a39870383c6fe93b420f26184a21d020d8ace2df83
 99 | ```
100 | 
101 | The resulting transaction (transaction number 
102 | 7e69687c94c57a878cf711a39870383c6fe93b420f26184a21d020d8ace2df83) is a spend to our new address. 
103 | That transaction will show some coin going in and other coin being returned as change. We will 
104 | need the vout and the scriptPubKey of the output that we can now spend. Let's take a look:
105 | 
106 | ```sh
107 | bitcoin-cli getrawtransaction 7e69687c94c57a878cf711a39870383c6fe93b420f26184a21d020d8ace2df83 1
108 | ...
109 |         {
110 |             "value" : 0.00100000,
111 |             "n" : 1,
112 |             "scriptPubKey" : {
113 |                 "asm" : "OP_HASH160 4b86dfac7f503de1127366815d1d452413282466 OP_EQUAL",
114 |                 "hex" : "a9144b86dfac7f503de1127366815d1d45241328246687",
115 |                 "reqSigs" : 1,
116 |                 "type" : "scripthash",
117 |                 "addresses" : [
118 |                     "38aNB81yPqNp6X2T3rXYZN8Z3C4pSbqEvs"
119 |                 ]
120 |             }
121 |         }
122 | ...
123 | ```
124 | 
125 | Let's spend that money out of the address. To do that, we'll create a spend transaction
126 | that spends away 0.0009 BTC leaving the remainder (0.0001 BTC) to cover fees for the 
127 | miners.
128 | 
129 | ```sh
130 | bitcoin-cli createrawtransaction '[{"txid":"7e69687c94c57a878cf711a39870383c6fe93b420f26184a21d020d8ace2df83","vout":1}]' '{"19ijkHfTosmo6rHtVKte145XPnQQNqVn46":0.0009}'
131 | 010000000183dfe2acd820d0214a18260f423be96f3c387098a311f78c877ac5947c68697e0100000000ffffffff01905f0100000000001976a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac00000000
132 | ```
133 | 
134 | Note: the JSON here is very picky. For example, it doesn't tollerate things like spaces after 
135 | commas and other standard patterns. Also be careful to escape things properly in the shell. 
136 | If you get stuck, try copying the example EXACTLY and just replace the transaction id and 
137 | multi-sig address.
138 | 
139 | Now we have an unsigned raw transaction. It means nothing right now and can safely be sent
140 | through untrusted mediums such as unencrypted email.
141 | 
142 | Let's go sign it with one of the private keys. In this case we will use the private key in 
143 | Wallet Import Format. (WIF)
144 | 
145 | Note: When doing this using the `bitcoin-abc` Bitcoin Cash (BCH / BCC) or `bgold-cli` Bitcoin Gold (BTG)
146 | you will need to also add an `amount` property to each input specifying the amount of each input.
147 | (the original input value without subtracting miner's fees) The JSON will look something like
148 | `..."vout":1,amount:0.001,"scriptPubKey"...`.
149 | 
150 | ```sh
151 | bitcoin-cli signrawtransaction '010000000183dfe2acd820d0214a18260f423be96f3c387098a311f78c877ac5947c68697e0100000000ffffffff01905f0100000000001976a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac00000000' '[{"txid":"7e69687c94c57a878cf711a39870383c6fe93b420f26184a21d020d8ace2df83","vout":1,"scriptPubKey":"a9144b86dfac7f503de1127366815d1d45241328246687","redeemScript":"524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53ae"}]' '["5KffUB9YUsvoGjrcn76PjVnC61PcWLzws4QPfrT9RFNd85utCkZ"]'
152 | {
153 |     "hex" : "010000000183dfe2acd820d0214a18260f423be96f3c387098a311f78c877ac5947c68697e01000000fd150100483045022100acb79a21e7e6cea47a598254e02639f87b5fa9a08c0ec8455503da0a479c19560220724014c241ac64ffc108d4457302644d5d057fbc4f2edbf33a86f24cf0b10447014cc9524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53aeffffffff01905f0100000000001976a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac00000000",
154 |     "complete" : false
155 | }
156 | ```
157 | 
158 | The resulting transaction in hex format is a bit longer but still marked as incomplete
159 | because we only have one signature on it. Likewise, it can be sent through insecure mediums
160 | such as email because it isn't completely signed. Even if it were, an abuser wouldn't be able 
161 | to alter the transaction sending the coin to another address because that would invalidate 
162 | the original signature.
163 | 
164 | However, I should point out that the transaction isn't encrypted. Let's take a look at it to
165 | demonstrate that.
166 | 
167 | ```sh
168 | bitcoin-cli decoderawtransaction '010000000183dfe2acd820d0214a18260f423be96f3c387098a311f78c877ac5947c68697e01000000fd150100483045022100acb79a21e7e6cea47a598254e02639f87b5fa9a08c0ec8455503da0a479c19560220724014c241ac64ffc108d4457302644d5d057fbc4f2edbf33a86f24cf0b10447014cc9524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53aeffffffff01905f0100000000001976a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac00000000'
169 | {
170 |     "txid" : "3312407d07de68d09eba1c9bee333aa947f46075c6f491eaeda2025c513aa45f",
171 |     "version" : 1,
172 |     "locktime" : 0,
173 |     "vin" : [
174 |         {
175 |             "txid" : "7e69687c94c57a878cf711a39870383c6fe93b420f26184a21d020d8ace2df83",
176 |             "vout" : 1,
177 |             "scriptSig" : {
178 |                 "asm" : "0 3045022100acb79a21e7e6cea47a598254e02639f87b5fa9a08c0ec8455503da0a479c19560220724014c241ac64ffc108d4457302644d5d057fbc4f2edbf33a86f24cf0b1044701 524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53ae",
179 |                 "hex" : "00483045022100acb79a21e7e6cea47a598254e02639f87b5fa9a08c0ec8455503da0a479c19560220724014c241ac64ffc108d4457302644d5d057fbc4f2edbf33a86f24cf0b10447014cc9524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53ae"
180 |             },
181 |             "sequence" : 4294967295
182 |         }
183 |     ],
184 |     "vout" : [
185 |         {
186 |             "value" : 0.00090000,
187 |             "n" : 0,
188 |             "scriptPubKey" : {
189 |                 "asm" : "OP_DUP OP_HASH160 5fa5be58f939d6ae79636c2143fa9e7924102c15 OP_EQUALVERIFY OP_CHECKSIG",
190 |                 "hex" : "76a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac",
191 |                 "reqSigs" : 1,
192 |                 "type" : "pubkeyhash",
193 |                 "addresses" : [
194 |                     "19ijkHfTosmo6rHtVKte145XPnQQNqVn46"
195 |                 ]
196 |             }
197 |         }
198 |     ]
199 | }
200 | ```
201 | 
202 | Sure enough, in the vout section you can see that this is a spend of 0.00090000 BTC to 19ijkHfTosmo6rHtVKte145XPnQQNqVn46.
203 | 
204 | Moving on, let's add another signature to this transaction:
205 | 
206 | ```sh
207 | bitcoin-cli signrawtransaction '010000000183dfe2acd820d0214a18260f423be96f3c387098a311f78c877ac5947c68697e01000000fd150100483045022100acb79a21e7e6cea47a598254e02639f87b5fa9a08c0ec8455503da0a479c19560220724014c241ac64ffc108d4457302644d5d057fbc4f2edbf33a86f24cf0b10447014cc9524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53aeffffffff01905f0100000000001976a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac00000000' '[{"txid":"7e69687c94c57a878cf711a39870383c6fe93b420f26184a21d020d8ace2df83","vout":1,"scriptPubKey":"a9144b86dfac7f503de1127366815d1d45241328246687","redeemScript":"524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53ae"}]' '["5KiDGG8sfmTNnzKDmm1MteWHV2TQQaUBbaEY3huVLwVz1i6i5be"]'
208 | {
209 |     "hex" : "010000000183dfe2acd820d0214a18260f423be96f3c387098a311f78c877ac5947c68697e01000000fd5d0100483045022100acb79a21e7e6cea47a598254e02639f87b5fa9a08c0ec8455503da0a479c19560220724014c241ac64ffc108d4457302644d5d057fbc4f2edbf33a86f24cf0b10447014730440220338862b4a13d67415fdaac35d408bd2a6d86e4c3be03b7abc92ee769b254dbe1022043ba94f304aff774fdb957af078c9b302425976370cc66f42ae05382c84ea5ea014cc9524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53aeffffffff01905f0100000000001976a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac00000000",
210 |     "complete" : true
211 | }
212 | ```
213 | 
214 | Now our transaction is marked complete. Again, an attacker can't alter the transaction 
215 | without invalidating it so it is still in a resonably safe condition. Additionally, if 
216 | our private keys were to be kept in distant and secure locations, at no point were our
217 | private keys in the same place at the same time. You can see how this strategy might be
218 | better than simply splitting a private key into multiple peices and combining them later
219 | to spend.
220 | 
221 | All that is left is to transmit our signed transaction on the network:
222 | 
223 | ```sh
224 | bitcoin-cli sendrawtransaction 010000000183dfe2acd820d0214a18260f423be96f3c387098a311f78c877ac5947c68697e01000000fd5d0100483045022100acb79a21e7e6cea47a598254e02639f87b5fa9a08c0ec8455503da0a479c19560220724014c241ac64ffc108d4457302644d5d057fbc4f2edbf33a86f24cf0b10447014730440220338862b4a13d67415fdaac35d408bd2a6d86e4c3be03b7abc92ee769b254dbe1022043ba94f304aff774fdb957af078c9b302425976370cc66f42ae05382c84ea5ea014cc9524104a97b658c114d77dc5f71736ab78fbe408ce632ed1478d7eaa106eef67c55d58a91c6449de4858faf11721e85fe09ec850c6578432eb4be9a69c76232ac593c3b4104019ef04a316792f0ecbe5ab1718c833c3964dee3626cfabe19d97745dbcaa5198919081b456e8eeea5898afa0e36d5c17ab693a80d728721128ed8c5f38cdba04104a04f29f308160e6f945b33d943304b1b471ed8f9eaceeb5412c04e60a0fab0376871d9d1108948b67cafbc703e565a18f8351fb8558fd7c7482d7027eecd687c53aeffffffff01905f0100000000001976a9145fa5be58f939d6ae79636c2143fa9e7924102c1588ac00000000
225 | 78126ea4aaf1acd232711b1efa3dc15832bd45d89bd5718c1cd15ec57d802497
226 | ```
227 | 
228 | Now we should be able to see our spend transaction populate across the network. Search for
229 | [78126ea4aaf1acd232711b1efa3dc15832bd45d89bd5718c1cd15ec57d802497](https://blockchain.info/tx/78126ea4aaf1acd232711b1efa3dc15832bd45d89bd5718c1cd15ec57d802497) in a block explorer to
230 | verify.
231 | 
232 | We have now successfully created a multi-sig bitcoin address, sent funds to it and retrieved 
233 | the funds out the other side. (minus a small transaction fee)
234 | 
235 | License
236 | ----
237 | 
238 | MIT
239 | 
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "bitcoin-2-of-3-multisig",
 3 |   "version": "0.0.1",
 4 |   "description": "A bitcoin private key generator.",
 5 |   "main": "private-key-generator.js",
 6 |   "scripts": {
 7 |     "test": "echo \"Error: no test specified\" && exit 1"
 8 |   },
 9 |   "keywords": [
10 |     "bitcoin",
11 |     "private",
12 |     "key"
13 |   ],
14 |   "author": "Anders Brownworth",
15 |   "license": "MIT",
16 |   "dependencies": {
17 |     "bignum": "^0.9.0"
18 |   }
19 | }
20 | 
--------------------------------------------------------------------------------
/private-key-generator.js:
--------------------------------------------------------------------------------
 1 | var bignum = require('bignum');
 2 | var crypto = require('crypto');
 3 | var util = require('util');
 4 | 
 5 | var key = getRandomPrivateKey();
 6 | console.log('Private Key in Hex: '+key.toString('hex'));
 7 | console.log('Private Key in WIF: '+walletImportFormat(key));
 8 | 
 9 | function getRandomPrivateKey() {
10 |     var buf = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
11 | 			  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
12 | 			  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
13 | 			  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
14 | 
15 |     // not every random 32 bytes is a valid private key. this is the top
16 |     var top = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
17 | 			  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
18 | 			  0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
19 | 			  0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]);
20 | 
21 |     while (bignum.fromBuffer(buf) > bignum.fromBuffer(top)) {
22 | 	try {
23 | 	    buf = crypto.randomBytes(32);
24 | 	}
25 | 	catch (ex) {
26 | 	    console.log(ex);
27 | 	}
28 |     }
29 |     return(buf);
30 | }
31 | 
32 | function walletImportFormat(buf) {
33 |     //console.log('add 0x80 in the front for main net');
34 |     var extBuf = new Buffer(buf.length+1);
35 |     extBuf[0] = 0x80;
36 |     buf.copy(extBuf, 1);
37 | 
38 |     //console.log('double sha256 the result');
39 |     var digest = sha256(sha256(extBuf));
40 | 
41 |     //console.log('add the first 4 bytes of the double sha256 to the end as a checksum')
42 |     var chkbuf = new Buffer(extBuf.length+4);
43 |     extBuf.copy(chkbuf, 0);
44 |     chkbuf[33] = digest[0];
45 |     chkbuf[34] = digest[1];
46 |     chkbuf[35] = digest[2];
47 |     chkbuf[36] = digest[3];
48 | 
49 |     //console.log('base58 that');
50 |     return base58Encode(chkbuf);
51 | }
52 | 
53 | function sha256(data) {
54 |   return new Buffer(crypto.createHash('sha256').update(data).digest('binary'), 'binary');
55 | }
56 | 
57 | function base58Encode(buf) {
58 |     var globalBuffer = new Buffer(1024);
59 |     var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
60 |     var ALPHABET_BUF = new Buffer(ALPHABET, 'ascii');
61 |     var str;
62 |     var x = bignum.fromBuffer(buf);
63 |     var r;
64 | 
65 |     if (buf.length < 512)
66 |       str = globalBuffer;
67 |     else
68 |       str = new Buffer(buf.length << 1);
69 |     var i = str.length - 1;
70 |     while (x.gt(0)) {
71 |       r = x.mod(58);
72 |       x = x.div(58);
73 |       str[i] = ALPHABET_BUF[r.toNumber()];
74 |       i--;
75 |     }
76 | 
77 |     // deal with leading zeros
78 |     var j=0;
79 |     while (buf[j] == 0) {
80 |       str[i] = ALPHABET_BUF[0];
81 |       j++;
82 |       i--;
83 |     }
84 | 
85 |     return str.slice(i+1, str.length).toString('ascii');
86 | }
87 | 
--------------------------------------------------------------------------------
/public-key-generator/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | 	gcc -Wall ecdsapubkey.c -o ecdsapubkey -lcrypto
3 | clean:
4 | 	rm -rf ecdsapubkey
5 | 
--------------------------------------------------------------------------------
/public-key-generator/ecdsapubkey.c:
--------------------------------------------------------------------------------
 1 | #include 
 2 | #include 
 3 | #include 
 4 | #include 
 5 | #include 
 6 | #include 
 7 | 
 8 | int main(int argc, char *argv[]) {
 9 |   char prv_hex[64];
10 |   EC_KEY *eckey = NULL;
11 |   EC_POINT *pub_key = NULL;
12 |   const EC_GROUP *group = NULL;
13 |   BIGNUM start;
14 |   BIGNUM *res;
15 |   BN_CTX *ctx;
16 | 
17 |   strcpy(prv_hex, argv[1]);
18 | 
19 |   BN_init(&start);
20 |   ctx = BN_CTX_new(); // ctx is an optional buffer to save time from allocating and deallocating memory whenever required
21 | 
22 |   res = &start;
23 |   BN_hex2bn(&res,prv_hex);
24 | 
25 |   /*
26 |   BIO *out=NULL;
27 |   out=BIO_new(BIO_s_file());
28 |   if (out == NULL) exit(1);
29 |   BIO_set_fp(out,stdout,BIO_NOCLOSE);
30 |   BN_print(out,res);
31 |   printf("\n");
32 |   */
33 | 
34 |   eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
35 |   group = EC_KEY_get0_group(eckey);
36 |   pub_key = EC_POINT_new(group);
37 | 
38 |   EC_KEY_set_private_key(eckey, res);
39 | 
40 |   /* pub_key is a new uninitialized `EC_POINT*`.  priv_key res is a `BIGNUM*`. */
41 |   if (!EC_POINT_mul(group, pub_key, res, NULL, NULL, ctx))
42 |     printf("Error at EC_POINT_mul.\n");
43 | 
44 |   //assert(EC_POINT_bn2point(group, &res, pub_key, ctx)); // Null here
45 | 
46 |   EC_KEY_set_public_key(eckey, pub_key);
47 | 
48 |   char *cc = EC_POINT_point2hex(group, pub_key, 4, ctx);
49 |   char *c = cc;
50 |   int i;
51 | 
52 |   for (i=0; i<130; i++) { // 1 byte 0x42, 32 bytes for X coordinate, 32 bytes for Y coordinate
53 |     printf("%c", *c++);
54 |   }
55 |   printf("\n");
56 | 
57 |   BN_CTX_free(ctx);
58 |   free(cc);
59 | 
60 |   return 0;
61 | }
62 | 
--------------------------------------------------------------------------------