crypto-lite 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,511 +1,1023 @@
1
- # crypto-lite - Cryptographic Secure Hash Functions and Public Key Signature Algorithms Made Easy
2
-
3
-
4
-
5
- * home :: [github.com/rubycoco/blockchain](https://github.com/rubycoco/blockchain)
6
- * bugs :: [github.com/rubycoco/blockchain/issues](https://github.com/rubycoco/blockchain/issues)
7
- * gem :: [rubygems.org/gems/crypto-lite](https://rubygems.org/gems/crypto-lite)
8
- * rdoc :: [rubydoc.info/gems/crypto-lite](http://rubydoc.info/gems/crypto-lite)
9
-
10
-
11
- ## Usage
12
-
13
- ### Secure Hashing / Hash Functions
14
-
15
- **SHA256 - Secure Hash Algorithm (SHA) 256-Bit (32 Bytes)**
16
-
17
-
18
- ``` ruby
19
- require 'crypto' ## or use require 'crypto-lite'
20
-
21
- ## try abc
22
- sha256( "abc" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
23
- sha256( "abc".b ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
24
- sha256( "\x61\x62\x63" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
25
- sha256( 0x616263 ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
26
-
27
- sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
28
- sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
29
- sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
30
-
31
- # "auto-magic" hex string to binary string conversion heuristic
32
- sha256( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
33
- sha256( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
34
- ```
35
-
36
-
37
- Bonus Back Stage Tip: How does SHA256 work?
38
-
39
- Try this [amazing animation of the SHA256 hash function in your very own terminal](https://github.com/in3rsha/sha256-animation) by Greg Walker.
40
-
41
- More of a code golfer? See [½ Kilo of SHA256](https://idiosyncratic-ruby.com/51-half-kilo-of-sha256.html) by Jan Lelis - yes, the SHA256 algorithm coded (from scratch) in 500 bytes of ruby.
42
-
43
-
44
- Onwards with more sha256 examples:
45
-
46
- ``` ruby
47
- ## try a
48
- sha256( "a" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
49
- sha256( "\x61" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
50
- sha256( 0b01100001 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
51
- sha256( 0x61 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
52
-
53
- sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
54
- sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
55
-
56
- # "auto-magic" hex string to binary string conversion heuristic
57
- sha256( '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
58
-
59
-
60
- ## try some more
61
- sha256( "Hello, Cryptos!" ) #=> "33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5"
62
- ```
63
-
64
-
65
- **SHA3-256 - Secure Hashing Algorthim (SHA) 3, 256-Bit (32 Bytes)**
66
-
67
- ``` ruby
68
- sha3_256( "Hello, Cryptos!" ) #=> "7dddf4bc9b86352b67e8823e5010ddbd2a90a854469e2517992ca7ca89e5bd58"
69
- ```
70
-
71
- Note: Yes, SHA256 vs SHA3-256 / SHA-2 vs SHA-3 the hashing functions are
72
- different (although the 256-bit hash size output is the same).
73
- The sha256 hashing function is part of the Secure Hash Algorithm (SHA) 2 family / standards first published in 2001.
74
- The sha3_256 is part of the (newer) Secure Hash Algorithm (SHA) 3 family / standards first published in 2015
75
- (and uses the Keccak cryptographic primitive "under the hood").
76
-
77
-
78
-
79
- **Keccak 256-Bit**
80
-
81
- ``` ruby
82
- keccak256( "Hello, Cryptos!" ) #=> "2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5"
83
- ```
84
-
85
-
86
- #### Aside - Keccak vs SHA3 / Original vs Official
87
-
88
- In 2004 the U.S. National Institute of Standards and Technology (NIST)
89
- changed the padding to `SHA3-256(M) = KECCAK [512] (M || 01, 256)`.
90
- This is different from the padding proposed by the Keccak team in
91
- the original Keccak SHA-3 submission version 3 (the final, winning version).
92
- The difference is the additional `'01'` bits appended to the message.
93
-
94
- To help avoid confusion the "submitted original version 3" SHA-3 Keccak
95
- hashing is now called "Keccak"
96
- and the finalized NIST SHA-3 standard "SHA3".
97
-
98
- Tip: If you don't know what variant of the hash function you have -
99
- original or official? - check your hash:
100
-
101
- For keccak 256-bit:
102
-
103
- ``` ruby
104
- keccak256( '' ) #=> "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
105
- ```
106
-
107
- For sha3 256-bit:
108
-
109
- ``` ruby
110
- sha3_256( '' ) #=> "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
111
- ```
112
-
113
-
114
-
115
- **RMD / RIPE-MD - RACE¹ Integrity Primitives Evaluation Message Digest 160-Bit**
116
-
117
- ¹: Research and development in Advanced Communications technologies in Europe
118
-
119
-
120
- ``` ruby
121
- rmd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
122
- # or use the alias / alternate name
123
- ripemd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
124
- ```
125
-
126
-
127
- #### Aside - Hex String `"0x616263"` vs Binary String `"\x61\x62\x63" == "abc"`
128
-
129
- Note: All hash functions operate on binary strings ("byte arrays")
130
- and NOT hex strings.
131
-
132
- Note: For hex strings the `0x` or `0X` prefix is optional.
133
- Examples of hex strings:
134
-
135
- ``` ruby
136
- # hex string binary string ("byte array")
137
- "61" "\x61" == "a"
138
- "0x61" "\x61" == "a"
139
-
140
- "616263" "\x61\x62\x63" == "abc"
141
- "0x616263" "\x61\x62\x63" == "abc"
142
- "0X616263" "\x61\x62\x63" == "abc"
143
-
144
- # or 160-bit hex string (hash)
145
- "93ce48570b55c42c2af816aeaba06cfee1224fae"
146
- "0x93ce48570b55c42c2af816aeaba06cfee1224fae"
147
-
148
- # or 256-bit hex string (hash)
149
- "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
150
- "0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
151
- ```
152
-
153
- You can use `[str].pack( 'H*' )`
154
- to convert a hex string into a binary string.
155
- Note: The standard `Array#pack` conversion
156
- will NOT "auto-magically" cut-off the `0x` or `0X` prefix.
157
-
158
-
159
- If you know you have a hex string use the `hex:` keyword to pass
160
- in the arg(ument)
161
- to the hash function and that will "automagically"
162
- handle the hex-to-bin conversion for you. Example:
163
-
164
- ``` ruby
165
- sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
166
- sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
167
-
168
- sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
169
- sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
170
- sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
171
- ```
172
-
173
- What about the built-in "auto-magic" hex-to-bin conversion / heuristic?
174
-
175
- Yes, if your passed in string starts with the
176
- the `0x` or `0X` prefix the string gets "auto-magically" converted
177
- to binary. Or if your passed in string is all hexadecimal characters,
178
- that is, `0-9` and `a-f` and has a minimum length of ten characters.
179
- Example:
180
-
181
-
182
- ``` ruby
183
- # "auto-magic" hex string to binary string conversion heuristic
184
-
185
- sha256( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
186
- sha256( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
187
-
188
- # or without 0x or 0X BUT with minimum heuristic length
189
- hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' )
190
- #=> "93ce48570b55c42c2af816aeaba06cfee1224fae"
191
-
192
- hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
193
- #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711"
194
-
195
- # and so on
196
- ```
197
-
198
-
199
- #### Hash Function Helpers
200
-
201
- **HASH160 - RMD160(SHA256(X))**
202
-
203
- All-in-one "best-of-both-worlds" helper - first hash with sha256 and than hash with rmd160. Why? Get the higher security of sha256 and the smaller size of rmd160.
204
-
205
-
206
- ``` ruby
207
- hash160( '02b9d1cc0b793b03b9f64d022e9c67d5f32670b03f636abf0b3147b34123d13990' )
208
- #=> "e6b145a3908a4d6616b13c1109717add8672c900"
209
-
210
- hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' )
211
- #=> "93ce48570b55c42c2af816aeaba06cfee1224fae"
212
- ```
213
-
214
-
215
- **HASH256 - SHA256(SHA256(X))**
216
-
217
- All-in-one double sha256 hash helper, that is, first hash with sha256 and than hash with sha256 again. Why? Arguably higher security.
218
-
219
- > SHA256(SHA256(X)) was proposed by Ferguson and Schneier in their excellent book "Practical Cryptography"
220
- > (later updated by Ferguson, Schneier, and Kohno and renamed "Cryptography Engineering") as a way to make SHA256 invulnerable
221
- > to "length-extension" attack. They called it "SHA256D".
222
-
223
-
224
- ``` ruby
225
- hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
226
- #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711"
227
- ```
228
-
229
- #### Base58 Encoding / Decoding Helpers
230
-
231
- **BASE58**
232
-
233
- Base58 encoding / decoding with leading zero bytes (in hex or binary strings) getting encoded from `00` to `1` and back:
234
-
235
- ``` ruby
236
- base58( "516b6fcd0f" ) #=> "ABnLTmg"
237
- base58( "00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ"
238
- # or with optional 0x or 0X prefix
239
- base58( "0x516b6fcd0f" ) #=> "ABnLTmg"
240
- base58( "0x00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ"
241
-
242
- unbase58( "ABnLTmg" ) #=> "516b6fcd0f"
243
- unbase58( "111111111143c9JGph3DZ" ) #=> "00000000000000000000123456789abcdef0"
244
- ```
245
-
246
-
247
- **BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])**
248
-
249
- Base58 encoding with an extra 4-byte secure hash checksum.
250
-
251
- ``` ruby
252
- base58check( "516b6fcd0f" ) #=> "237LSrY9NUUas"
253
- base58check( "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ) #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
254
-
255
- unbase58check( "237LSrY9NUUas" ) #=> "516b6fcd0f"
256
- unbase58check( "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" ) #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
257
- ```
258
-
259
-
260
-
261
- ### Public Key Signature Algorithms
262
-
263
-
264
- **Elliptic Curve Digital Signature Algorithm (ECDSA)**
265
-
266
-
267
- Private Key
268
-
269
- An ECDSA (Elliptic Curve Digital Signature Algorithm) private key is a random number between 1 and the order of the elliptic curve group.
270
-
271
-
272
- ``` ruby
273
- # Auto-generate (random) private key
274
- private_key = EC::PrivateKey.generate # by default uses Secp256k1 curve (used in Bitcoin and Ethereum)
275
-
276
- private_key.to_i
277
- #=> 72190737707147846840353520312904745954595478835413056312168022784020322830309
278
- ```
279
-
280
-
281
- (Auto-)Calculate the Public Key - Enter Elliptic Curve (EC) Cryptography
282
-
283
- The public key are two numbers (that is, a point with the coordinates x and y) computed by multiplying
284
- the generator point (`G`) of the curve with the private key.
285
- This is equivalent to adding the generator to itself `private_key` times.
286
- Magic?
287
- Let's try:
288
-
289
-
290
- ``` ruby
291
- # This private key is just an example. It should be much more secure!
292
- private_key = EC::PrivateKey.new( 1234 ) # by default uses Secp256k1 curve (used in Bitcoin and Ethereum)
293
-
294
- public_key = private_key.public_key ## the "magic" one-way K=k*G curve multiplication (K=public key,k=private key, G=generator point)
295
- point = public_key.point
296
-
297
- point.x
298
- #=> 102884003323827292915668239759940053105992008087520207150474896054185180420338
299
- point.y
300
- #=> 49384988101491619794462775601349526588349137780292274540231125201115197157452
301
-
302
- point.x.to_s(16)
303
- #=> "e37648435c60dcd181b3d41d50857ba5b5abebe279429aa76558f6653f1658f2"
304
- point.y.to_s(16)
305
- #=> "6d2ee9a82d4158f164ae653e9c6fa7f982ed8c94347fc05c2d068ff1d38b304c"
306
- ```
307
-
308
-
309
- Sign a transaction with an (elliptic curve) private key:
310
-
311
- ``` ruby
312
- # Step 1 - Calculate the Transaction (tx) Hash
313
- tx = 'from: Alice to: Bob cryptos: 43_000_000_000'
314
- txhash = sha256( tx )
315
-
316
- # Step 2 - Get the Signer's Private key
317
- private_key = EC::PrivateKey.new( 1234 ) # This private key is just an example. It should be much more secure!
318
-
319
- # Sign!
320
- signature = private_key.sign( txhash )
321
- # -or-
322
- signature = EC.sign( txhash, private_key )
323
-
324
- signature.r
325
- #=> 80563021554295584320113598933963644829902821722081604563031030942154621916407
326
- signature.s
327
- #=> 58316177618967642068351252425530175807242657664855230973164972803783751708604
328
-
329
- signature.r.to_s(16)
330
- #=> "3306a2f81ad2b2f62ebe0faec129545bc772babe1ca5e70f6e56556b406464c0"
331
- signature.s.to_s(16)
332
- #=> "4fe202bb0835758f514cd4a0787986f8f6bf303df629dc98c5b1a438a426f49a"
333
- ```
334
-
335
-
336
- Verify a signed transaction with an (elliptic curve) public key:
337
-
338
- ``` ruby
339
- # Step 1 - Calculate the Transaction (tx) Hash
340
- tx = 'from: Alice to: Bob cryptos: 43_000_000_000'
341
- txhash = sha256( tx )
342
-
343
- # Step 2 - Get the Signer's Public Key
344
- public_key = EC::PublicKey.new(
345
- 102884003323827292915668239759940053105992008087520207150474896054185180420338,
346
- 49384988101491619794462775601349526588349137780292274540231125201115197157452
347
- )
348
-
349
- # Step 3 - Get the Transaction's Signature
350
- signature = EC::Signature.new(
351
- 80563021554295584320113598933963644829902821722081604563031030942154621916407,
352
- 58316177618967642068351252425530175807242657664855230973164972803783751708604
353
- )
354
-
355
- # Don't Trust - Verify
356
- public_key.verify?( txhash, signature )
357
- # -or-
358
- EC.verify?( txhash, signature, public_key )
359
- #=> true
360
-
361
-
362
- # or using hexadecimal numbers
363
-
364
- public_key = EC::PublicKey.new(
365
- 0xe37648435c60dcd181b3d41d50857ba5b5abebe279429aa76558f6653f1658f2,
366
- 0x6d2ee9a82d4158f164ae653e9c6fa7f982ed8c94347fc05c2d068ff1d38b304c
367
- )
368
-
369
- signature = EC::Signature.new(
370
- 0x3306a2f81ad2b2f62ebe0faec129545bc772babe1ca5e70f6e56556b406464c0,
371
- 0x4fe202bb0835758f514cd4a0787986f8f6bf303df629dc98c5b1a438a426f49a
372
- )
373
-
374
- public_key.verify?( txhash, signature )
375
- # -or-
376
- EC.verify?( txhash, signature, public_key )
377
- #=> true
378
- ```
379
-
380
-
381
- To sum up:
382
-
383
- - The (raw) private key is a 256-bit unsigned integer number
384
- - The (raw) public key is a point (x,y), that is, two 256-bit unsigned integer numbers - derived (calculated) from the private key
385
- - A (raw) signature is composed of (r,s), that is, two 256-bit unsigned integer numbers
386
-
387
- That's all the magic.
388
-
389
-
390
-
391
-
392
- ## Examples
393
-
394
- ### Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key
395
-
396
- Let's follow the steps from [How to create Bitcoin Address](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses#How_to_create_Bitcoin_Address):
397
-
398
- ``` ruby
399
- # Lets start with the public key ("raw" hex string encoded)
400
- pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
401
-
402
- # 1. Perform SHA-256 hashing on the public key
403
- step1 = sha256( pk )
404
- #=> "0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98"
405
-
406
- # 2. Perform RIPEMD-160 hashing on the result of SHA-256
407
- step2 = ripemd160( step1 )
408
- #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
409
-
410
- # 3. Add version byte in front of RIPEMD-160 hash (0x00 for Main Network)
411
- step3 = "00" + step2
412
- #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
413
-
414
- # 4. Perform SHA-256 hash on the extended RIPEMD-160 result
415
- step4 = sha256( step3 )
416
- #=> "ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c"
417
-
418
- # 5. Perform SHA-256 hash on the result of the previous SHA-256 hash
419
- step5 = sha256( step4 )
420
- #=> "c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd"
421
-
422
- # 6. Take the first 4 bytes of the second SHA-256 hash. This is the address checksum
423
- step6 = step5[0..7] # note: 4 bytes in hex string are 8 digits/chars
424
- #=> "c7f18fe8"
425
-
426
- # 7. Add the 4 checksum bytes from step 6 at the end of
427
- # extended RIPEMD-160 hash from step 3.
428
- # This is the 25-byte binary Bitcoin Address.
429
- step7 = step3 + step6
430
- #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8"
431
-
432
- # 8. Convert the result from a byte string into a base58 string using Base58 encoding.
433
- # This is the most commonly used Bitcoin Address format.
434
- addr = base58( step7 )
435
- #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
436
- ```
437
-
438
- Or let's try again with the shortcut helpers:
439
-
440
- - `HASH160 - RMD160(SHA256(X))`
441
- - `BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])`
442
-
443
- ``` ruby
444
- # Lets start with the public key ("raw" hex string encoded)
445
- pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
446
-
447
- # 1. Perform HASH-160 hashing on the public key
448
- # a) Perform SHA-256 hashing on the public key
449
- # b) Perform RIPEMD-160 hashing on the result of SHA-256
450
- step1 = hash160( pk )
451
- #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
452
-
453
- # 2. Add version byte in front of RIPEMD-160 hash (0x00 for Main Network)
454
- step2 = "00" + step1
455
- #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
456
-
457
- # 3. Encode with BASE58CHECK
458
- # a) Perform SHA-256 hash on the extended RIPEMD-160 result
459
- # b) Perform SHA-256 hash on the result of the previous SHA-256 hash
460
- # c) Take the first 4 bytes of the second SHA-256 hash. This is the address checksum
461
- # d) Add the 4 checksum bytes at the end of
462
- # extended RIPEMD-160 hash from step 2.
463
- # This is the 25-byte binary Bitcoin Address.
464
- # e) Convert the result from a byte string into a base58 string
465
- # using Base58 encoding.
466
- # This is the most commonly used Bitcoin Address format.
467
- addr = base58check( step2 )
468
- #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
469
- ```
470
-
471
-
472
- References
473
-
474
- - [How to create Bitcoin Address](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses#How_to_create_Bitcoin_Address)
475
- - [Ruby Quiz #15 - Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key](https://github.com/planetruby/quiz/tree/master/015)
476
-
477
- Bonus: Bitcon Tip - How to Buy Bitcoin (The CO₂-Friendly Way)
478
-
479
- > 1. Take one $50 bill, five $10 bills, or ten $5 bills (I wouldn't recommend change - stay with paper money).
480
- > 2. Go to the bathroom.
481
- > 3. Lift the lid of the loo.
482
- > 4. Throw money in.
483
- > 5. Flush down water.
484
- >
485
- > Congrats! You just purchased $50 worth of Bitcoin - without fucking the planet!
486
- >
487
- > -- Trolly McTrollface, Bitcon Greater Fool Court Jester
488
-
489
- Read more [Crypto Quotes »](https://github.com/openblockchains/crypto-quotes)
490
-
491
-
492
-
493
-
494
- ## Install
495
-
496
- Just install the gem:
497
-
498
- $ gem install crypto-lite
499
-
500
-
501
- ## License
502
-
503
- The scripts are dedicated to the public domain.
504
- Use it as you please with no restrictions whatsoever.
505
-
506
-
507
- ## Questions? Comments?
508
-
509
- Send them along to the [wwwmake forum](http://groups.google.com/group/wwwmake).
510
- Thanks!
511
-
1
+ # crypto-lite - Cryptographic Secure Hash Functions and Public Key Signature Algorithms Made Easy
2
+
3
+
4
+
5
+ * home :: [github.com/rubycocos/blockchain](https://github.com/rubycocos/blockchain)
6
+ * bugs :: [github.com/rubycocos/blockchain/issues](https://github.com/rubycocos/blockchain/issues)
7
+ * gem :: [rubygems.org/gems/crypto-lite](https://rubygems.org/gems/crypto-lite)
8
+ * rdoc :: [rubydoc.info/gems/crypto-lite](http://rubydoc.info/gems/crypto-lite)
9
+
10
+
11
+ ## Usage
12
+
13
+ ### Secure Hashing / Hash Functions
14
+
15
+ **SHA256 - Secure Hash Algorithm (SHA) 256-Bit (32 Bytes)**
16
+
17
+
18
+ ``` ruby
19
+ require 'crypto' ## or use require 'crypto-lite'
20
+
21
+ ## try abc
22
+ sha256( "abc" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
23
+ sha256( "abc".b ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
24
+ sha256( "\x61\x62\x63" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
25
+ sha256( 0x616263 ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
26
+
27
+ sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
28
+ sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
29
+ sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
30
+
31
+ # "auto-magic" hex string to binary string conversion heuristic
32
+ sha256( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
33
+ sha256( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
34
+ ```
35
+
36
+
37
+ Bonus Back Stage Tip: How does SHA256 work?
38
+
39
+ Try this [amazing animation of the SHA256 hash function in your very own terminal](https://github.com/in3rsha/sha256-animation) by Greg Walker.
40
+
41
+ More of a code golfer? See [½ Kilo of SHA256](https://idiosyncratic-ruby.com/51-half-kilo-of-sha256.html) by Jan Lelis - yes, the SHA256 algorithm coded (from scratch) in 500 bytes of ruby.
42
+
43
+
44
+ Onwards with more sha256 examples:
45
+
46
+ ``` ruby
47
+ ## try a
48
+ sha256( "a" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
49
+ sha256( "\x61" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
50
+ sha256( 0b01100001 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
51
+ sha256( 0x61 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
52
+
53
+ sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
54
+ sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
55
+
56
+ # "auto-magic" hex string to binary string conversion heuristic
57
+ sha256( '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
58
+
59
+
60
+ ## try some more
61
+ sha256( "Hello, Cryptos!" ) #=> "33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5"
62
+ ```
63
+
64
+
65
+ **SHA3-256 - Secure Hashing Algorthim (SHA) 3, 256-Bit (32 Bytes)**
66
+
67
+ ``` ruby
68
+ sha3_256( "Hello, Cryptos!" ) #=> "7dddf4bc9b86352b67e8823e5010ddbd2a90a854469e2517992ca7ca89e5bd58"
69
+ ```
70
+
71
+ Note: Yes, SHA256 vs SHA3-256 / SHA-2 vs SHA-3 the hashing functions are
72
+ different (although the 256-bit hash size output is the same).
73
+ The sha256 hashing function is part of the Secure Hash Algorithm (SHA) 2 family / standards first published in 2001.
74
+ The sha3_256 is part of the (newer) Secure Hash Algorithm (SHA) 3 family / standards first published in 2015
75
+ (and uses the Keccak cryptographic primitive "under the hood").
76
+
77
+
78
+
79
+ **Keccak 256-Bit**
80
+
81
+ ``` ruby
82
+ keccak256( "Hello, Cryptos!" ) #=> "2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5"
83
+ ```
84
+
85
+
86
+ #### Aside - Keccak vs SHA3 / Original vs Official
87
+
88
+ In 2004 the U.S. National Institute of Standards and Technology (NIST)
89
+ changed the padding to `SHA3-256(M) = KECCAK [512] (M || 01, 256)`.
90
+ This is different from the padding proposed by the Keccak team in
91
+ the original Keccak SHA-3 submission version 3 (the final, winning version).
92
+ The difference is the additional `'01'` bits appended to the message.
93
+
94
+ To help avoid confusion the "submitted original version 3" SHA-3 Keccak
95
+ hashing is now called "Keccak"
96
+ and the finalized NIST SHA-3 standard "SHA3".
97
+
98
+ Tip: If you don't know what variant of the hash function you have -
99
+ original or official? - check your hash:
100
+
101
+ For keccak 256-bit:
102
+
103
+ ``` ruby
104
+ keccak256( '' ) #=> "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
105
+ ```
106
+
107
+ For sha3 256-bit:
108
+
109
+ ``` ruby
110
+ sha3_256( '' ) #=> "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
111
+ ```
112
+
113
+
114
+
115
+ **RMD / RIPE-MD - RACE¹ Integrity Primitives Evaluation Message Digest 160-Bit**
116
+
117
+ ¹: Research and development in Advanced Communications technologies in Europe
118
+
119
+
120
+ ``` ruby
121
+ rmd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
122
+ # or use the alias / alternate name
123
+ ripemd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
124
+ ```
125
+
126
+
127
+ #### Aside - Hex String `"0x616263"` vs Binary String `"\x61\x62\x63" == "abc"`
128
+
129
+ Note: All hash functions operate on binary strings ("byte arrays")
130
+ and NOT hex strings.
131
+
132
+ Note: For hex strings the `0x` or `0X` prefix is optional.
133
+ Examples of hex strings:
134
+
135
+ ``` ruby
136
+ # hex string binary string ("byte array")
137
+ "61" "\x61" == "a"
138
+ "0x61" "\x61" == "a"
139
+
140
+ "616263" "\x61\x62\x63" == "abc"
141
+ "0x616263" "\x61\x62\x63" == "abc"
142
+ "0X616263" "\x61\x62\x63" == "abc"
143
+
144
+ # or 160-bit hex string (hash)
145
+ "93ce48570b55c42c2af816aeaba06cfee1224fae"
146
+ "0x93ce48570b55c42c2af816aeaba06cfee1224fae"
147
+
148
+ # or 256-bit hex string (hash)
149
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
150
+ "0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
151
+ ```
152
+
153
+ You can use `[str].pack( 'H*' )`
154
+ to convert a hex string into a binary string.
155
+ Note: The standard `Array#pack` conversion
156
+ will NOT "auto-magically" cut-off the `0x` or `0X` prefix.
157
+
158
+
159
+ If you know you have a hex string use the `hex:` keyword to pass
160
+ in the arg(ument)
161
+ to the hash function and that will "automagically"
162
+ handle the hex-to-bin conversion for you. Example:
163
+
164
+ ``` ruby
165
+ sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
166
+ sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
167
+
168
+ sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
169
+ sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
170
+ sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
171
+ ```
172
+
173
+ What about the built-in "auto-magic" hex-to-bin conversion / heuristic?
174
+
175
+ Yes, if your passed in string starts with the
176
+ the `0x` or `0X` prefix the string gets "auto-magically" converted
177
+ to binary. Or if your passed in string is all hexadecimal characters,
178
+ that is, `0-9` and `a-f` and has a minimum length of ten characters.
179
+ Example:
180
+
181
+
182
+ ``` ruby
183
+ # "auto-magic" hex string to binary string conversion heuristic
184
+
185
+ sha256( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
186
+ sha256( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
187
+
188
+ # or without 0x or 0X BUT with minimum heuristic length
189
+ hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' )
190
+ #=> "93ce48570b55c42c2af816aeaba06cfee1224fae"
191
+
192
+ hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
193
+ #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711"
194
+
195
+ # and so on
196
+ ```
197
+
198
+
199
+ #### Hash Function Helpers
200
+
201
+ **HASH160 - RMD160(SHA256(X))**
202
+
203
+ All-in-one "best-of-both-worlds" helper - first hash with sha256 and than hash with rmd160. Why? Get the higher security of sha256 and the smaller size of rmd160.
204
+
205
+
206
+ ``` ruby
207
+ hash160( '02b9d1cc0b793b03b9f64d022e9c67d5f32670b03f636abf0b3147b34123d13990' )
208
+ #=> "e6b145a3908a4d6616b13c1109717add8672c900"
209
+
210
+ hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' )
211
+ #=> "93ce48570b55c42c2af816aeaba06cfee1224fae"
212
+ ```
213
+
214
+
215
+ **HASH256 - SHA256(SHA256(X))**
216
+
217
+ All-in-one double sha256 hash helper, that is, first hash with sha256 and than hash with sha256 again. Why? Arguably higher security.
218
+
219
+ > SHA256(SHA256(X)) was proposed by Ferguson and Schneier in their excellent book "Practical Cryptography"
220
+ > (later updated by Ferguson, Schneier, and Kohno and renamed "Cryptography Engineering") as a way to make SHA256 invulnerable
221
+ > to "length-extension" attack. They called it "SHA256D".
222
+
223
+
224
+ ``` ruby
225
+ hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
226
+ #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711"
227
+ ```
228
+
229
+ #### Base58 Encoding / Decoding Helpers
230
+
231
+ **BASE58**
232
+
233
+ Base58 encoding / decoding with leading zero bytes (in hex or binary strings) getting encoded from `00` to `1` and back:
234
+
235
+ ``` ruby
236
+ base58( "516b6fcd0f" ) #=> "ABnLTmg"
237
+ base58( "00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ"
238
+ # or with optional 0x or 0X prefix
239
+ base58( "0x516b6fcd0f" ) #=> "ABnLTmg"
240
+ base58( "0x00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ"
241
+
242
+ unbase58( "ABnLTmg" ) #=> "516b6fcd0f"
243
+ unbase58( "111111111143c9JGph3DZ" ) #=> "00000000000000000000123456789abcdef0"
244
+ ```
245
+
246
+
247
+ **BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])**
248
+
249
+ Base58 encoding with an extra 4-byte secure hash checksum.
250
+
251
+ ``` ruby
252
+ base58check( "516b6fcd0f" ) #=> "237LSrY9NUUas"
253
+ base58check( "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ) #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
254
+
255
+ unbase58check( "237LSrY9NUUas" ) #=> "516b6fcd0f"
256
+ unbase58check( "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" ) #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
257
+ ```
258
+
259
+
260
+
261
+ ### Public Key Signature Algorithms
262
+
263
+
264
+ **Elliptic Curve Digital Signature Algorithm (ECDSA)**
265
+
266
+
267
+ Private Key
268
+
269
+ An ECDSA (Elliptic Curve Digital Signature Algorithm) private key is a random number between 1 and the order of the elliptic curve group.
270
+
271
+
272
+ ``` ruby
273
+ # Auto-generate (random) private key
274
+ private_key = EC::PrivateKey.generate # by default uses Secp256k1 curve (used in Bitcoin and Ethereum)
275
+
276
+ private_key.to_i
277
+ #=> 29170346885894798724849267297784761178669026868482995474159965944722616190552
278
+ private_key.to_s
279
+ #=> "407dd4ccde53d30f3a9cda74ceccb247f3997466964786b59e4d68e93e8f8658"
280
+ ```
281
+
282
+
283
+ Derive / (Auto-)Calculate the Public Key - Enter Elliptic Curve (EC) Cryptography
284
+
285
+ The public key (`K`) are two numbers (that is, a point with the coordinates x and y) computed by multiplying
286
+ the generator point (`G`) of the curve with the private key (`k`) e.g. `K=k*G`.
287
+ This is equivalent to adding the generator to itself `k` times.
288
+ Magic?
289
+ Let's try:
290
+
291
+
292
+ ``` ruby
293
+ # This private key is just an example. It should be much more secure!
294
+ private_key = EC::PrivateKey.new( 1234 ) # by default uses Secp256k1 curve (used in Bitcoin and Ethereum)
295
+
296
+ public_key = private_key.public_key ## the "magic" one-way K=k*G curve multiplication (K=public key,k=private key, G=generator point)
297
+ point = public_key.point
298
+
299
+ point.x
300
+ #=> 102884003323827292915668239759940053105992008087520207150474896054185180420338
301
+ point.y
302
+ #=> 49384988101491619794462775601349526588349137780292274540231125201115197157452
303
+
304
+ point.x.to_s(16)
305
+ #=> "e37648435c60dcd181b3d41d50857ba5b5abebe279429aa76558f6653f1658f2"
306
+ point.y.to_s(16)
307
+ #=> "6d2ee9a82d4158f164ae653e9c6fa7f982ed8c94347fc05c2d068ff1d38b304c"
308
+ ```
309
+
310
+
311
+ Sign a transaction with an (elliptic curve) private key:
312
+
313
+ ``` ruby
314
+ # Step 1 - Calculate the Transaction (tx) Hash
315
+ tx = 'from: Alice to: Bob cryptos: 43_000_000_000'
316
+ txhash = sha256( tx )
317
+
318
+ # Step 2 - Get the Signer's Private key
319
+ private_key = EC::PrivateKey.new( 1234 ) # This private key is just an example. It should be much more secure!
320
+
321
+ # Sign!
322
+ signature = private_key.sign( txhash )
323
+ # -or-
324
+ signature = EC.sign( txhash, private_key )
325
+
326
+ signature.r
327
+ #=> 80563021554295584320113598933963644829902821722081604563031030942154621916407
328
+ signature.s
329
+ #=> 58316177618967642068351252425530175807242657664855230973164972803783751708604
330
+
331
+ signature.r.to_s(16)
332
+ #=> "3306a2f81ad2b2f62ebe0faec129545bc772babe1ca5e70f6e56556b406464c0"
333
+ signature.s.to_s(16)
334
+ #=> "4fe202bb0835758f514cd4a0787986f8f6bf303df629dc98c5b1a438a426f49a"
335
+ ```
336
+
337
+
338
+ Verify a signed transaction with an (elliptic curve) public key:
339
+
340
+ ``` ruby
341
+ # Step 1 - Calculate the Transaction (tx) Hash
342
+ tx = 'from: Alice to: Bob cryptos: 43_000_000_000'
343
+ txhash = sha256( tx )
344
+
345
+ # Step 2 - Get the Signer's Public Key
346
+ public_key = EC::PublicKey.new(
347
+ 102884003323827292915668239759940053105992008087520207150474896054185180420338,
348
+ 49384988101491619794462775601349526588349137780292274540231125201115197157452
349
+ )
350
+
351
+ # Step 3 - Get the Transaction's Signature
352
+ signature = EC::Signature.new(
353
+ 80563021554295584320113598933963644829902821722081604563031030942154621916407,
354
+ 58316177618967642068351252425530175807242657664855230973164972803783751708604
355
+ )
356
+
357
+ # Don't Trust - Verify
358
+ public_key.verify?( txhash, signature )
359
+ # -or-
360
+ EC.verify?( txhash, signature, public_key )
361
+ #=> true
362
+
363
+
364
+ # or using hexadecimal numbers
365
+
366
+ public_key = EC::PublicKey.new(
367
+ 0xe37648435c60dcd181b3d41d50857ba5b5abebe279429aa76558f6653f1658f2,
368
+ 0x6d2ee9a82d4158f164ae653e9c6fa7f982ed8c94347fc05c2d068ff1d38b304c
369
+ )
370
+
371
+ signature = EC::Signature.new(
372
+ 0x3306a2f81ad2b2f62ebe0faec129545bc772babe1ca5e70f6e56556b406464c0,
373
+ 0x4fe202bb0835758f514cd4a0787986f8f6bf303df629dc98c5b1a438a426f49a
374
+ )
375
+
376
+ public_key.verify?( txhash, signature )
377
+ # -or-
378
+ EC.verify?( txhash, signature, public_key )
379
+ #=> true
380
+ ```
381
+
382
+
383
+ To sum up:
384
+
385
+ - The (raw) private key is a 256-bit unsigned integer number
386
+ - The (raw) public key is a point (x,y), that is, two 256-bit unsigned integer numbers - derived (calculated) from the private key
387
+ - A (raw) signature is composed of (r,s), that is, two 256-bit unsigned integer numbers
388
+
389
+ That's all the magic.
390
+
391
+
392
+
393
+
394
+
395
+ ## Real-World Examples / Cookbook
396
+
397
+ **Bitcoin Chains**
398
+
399
+ - [Derive the Bitcoin (Elliptic Curve) Public Key from the Private Key](#derive-the-bitcoin-elliptic-curve-public-key-from-the-private-key)
400
+ - [Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key](#generate-the-bitcoin-base58-address-from-the-elliptic-curve-public-key)
401
+ - [Encode the Bitcoin Private Key in the Wallet Import Format (WIF)](#encode-the-bitcoin-private-key-in-the-wallet-import-format-wif)
402
+
403
+ **Dodge "Shiba Inu" Chains**
404
+
405
+ - [Derive the Dodge (Elliptic Curve) Public Key from the Private Key](#derive-the-dodge-elliptic-curve-public-key-from-the-private-key)
406
+ - [Generate the Dodge Address from the (Elliptic Curve) Public Key](#generate-the-dodge-address-from-the-elliptic-curve-public-key)
407
+
408
+
409
+ **Litecoin Chains**
410
+ - [Derive the Litecoin (Elliptic Curve) Public Key from the Private Key](#derive-the-litecoin-elliptic-curve-public-key-from-the-private-key)
411
+ - [Generate the Litecoin Address from the (Elliptic Curve) Public Key](#generate-the-litecoin-address-from-the-elliptic-curve-public-key)
412
+
413
+
414
+
415
+ **Ethereum Chains**
416
+
417
+ - [Derive the Ethereum (Elliptic Curve) Public Key from the Private Key](#derive-the-ethereum-elliptic-curve-public-key-from-the-private-key)
418
+ - [Generate the Ethereum Address from the (Elliptic Curve) Public Key](#generate-the-ethereum-address-from-the-elliptic-curve-public-key)
419
+
420
+
421
+
422
+
423
+ ## Bitcoin (BTC), Bitcoin Cash (BCH), Bitcoin Cash Satoshi Vision (BSV), Bitcoin Cash ABC (BCHA)
424
+
425
+ **Bitcon Public Service Announcement:**
426
+
427
+ > Bitcoin number go up because more people want bitcoin. Bitcoin becomes more and more valuable.
428
+ >
429
+ > - 1,000 HODLers
430
+ > - 10,000 HODLers
431
+ > - 100,000 HODLers
432
+ > - 1,000,000 HODLers
433
+ > - 10,000,000 HODLers
434
+ > - 100,000,000 HODLers
435
+ > - 1,000,000,000 HODLers
436
+ > - 10,000,000,000 HODLers
437
+ > - 100,000,000,000 HODLers and on and on
438
+ >
439
+ > People will come to understand bitcon.
440
+ >
441
+ > -- Dan McArdle, Bitcoin "There is No Alternative", Bitcoin is the New (Gold) Standard
442
+
443
+ **[BEWARE: Yes, Bitcoin Is a Ponzi - Learn How the Investment Fraud Works »](https://github.com/openblockchains/bitcoin-ponzi)**
444
+
445
+
446
+ ### Derive the Bitcoin (Elliptic Curve) Public Key from the Private Key
447
+
448
+ A private key in bitcoin is a 32-byte (256-bit) unsigned / positive integer number.
449
+
450
+ Or more precise the private key is a random number between 1
451
+ and the order of the elliptic curve secp256k1.
452
+
453
+ ``` ruby
454
+ EC::SECP256K1.order
455
+ #=> 115792089237316195423570985008687907852837564279074904382605163141518161494337
456
+
457
+ # or in hexadecimal (base16)
458
+ EC::SECP256K1.order.to_s(16)
459
+ #=> "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
460
+ ```
461
+
462
+ #### Step 1 - Let's generate a private key
463
+
464
+ ``` ruby
465
+ private_key = EC::PrivateKey.generate # alice
466
+ private_key.to_i
467
+ #=> 50303382071965675924643368363408442017264130870580001935435312336103014915707
468
+ private_key.to_s
469
+ #=> "6f36b48dd130618049ca27e1909debdf3665cf0df0ade0986f0c50123107de7b"
470
+
471
+ private_key = EC::PrivateKey.generate # bob
472
+ private_key.to_i
473
+ #=> 96396065671557366547785856940504404648366202869823009146014078671352808008442
474
+ private_key.to_s
475
+ #=> "d51e3d5ce8fbc6e574cf78d1c46e8936c26f38b002b954d0eac8aef195d6eafa"
476
+ ```
477
+
478
+ Or use your own (secure) random generator.
479
+ Trivia Note: The smallest possible (BUT HIGHLY UNSECURE)
480
+ private key is 1 (not 0).
481
+
482
+ ``` ruby
483
+ def generate_key
484
+ 1 + SecureRandom.random_number( EC::SECP256K1.order - 1 )
485
+ end
486
+
487
+ generate_key # alice
488
+ #=> 66010624277151619503613090016410344678572543187504521309126248385615121289833
489
+
490
+ generate_key # bob
491
+ #=> 10004433477200726182517873544056418402326985168039465080040800405880945722868
492
+ ```
493
+
494
+
495
+ Aside: What's Base 6? Let's Roll the Dice
496
+
497
+ An important part of creating a private key is ensuring the random number
498
+ is truly random.
499
+ Physical randomness is better than computer generated pseudo-randomness.
500
+ The easiest way to generate physical randomness is with a dice.
501
+ To create a private key you only need one six-sided die
502
+ which you roll ninety nine times.
503
+ Stopping each time to record the value of the die.
504
+ When recording the values follow these rules: 1=1, 2=2, 3=3, 4=4, 5=5, 6=0.
505
+ By doing this you are recording the big random number, your private key,
506
+ in base 6 format.
507
+
508
+ ``` ruby
509
+ def roll_dice
510
+ SecureRandom.random_number( 6 ) ## returning 0,1,2,3,4, or 5
511
+ end
512
+
513
+ priv_base6 = 99.times.reduce('') { |buf,_| buf << roll_dice.to_s }
514
+ #=> "413130205513310000115530450343345150251504444013455422453552225503020102150031231134314351124254004"
515
+ ```
516
+
517
+ Exercise:
518
+ Turn the ninety nine character base 6 private key into a base 10 or base 16 number.
519
+
520
+ ``` ruby
521
+ priv = priv_base6.to_i(6) ## convert to decimal (base 10) from roll-the-dice (base 6) string
522
+ #=> 77254760463198588454157792320308725646096652667800343330432100522222375944308
523
+ priv.to_s(16)
524
+ #=> "aacca516ccbf72dac2c4c447b9f64d12855685e99810ffcf7763a12da6c04074"
525
+ ```
526
+
527
+
528
+ Aside: What's Base 2? Let's Flip A Coin - Heads or Tails?
529
+
530
+ Triva Quiz: For an (unsigned) 256-bit number - how many times
531
+ do you need to flip the coin?
532
+
533
+
534
+
535
+
536
+ #### Step 2 - Let's derive / calculate the public key from the private key - Enter elliptic curve (EC) cryptography
537
+
538
+ The public key (`K`) are two numbers (that is, a point with the coordinates x and y) computed by multiplying
539
+ the generator point (`G`) of the curve with the private key (`k`) e.g. `K=k*G`.
540
+ This is equivalent to adding the generator to itself `k` times.
541
+ Magic?
542
+ Let's try:
543
+
544
+
545
+ ``` ruby
546
+ # note: by default uses Secp256k1 curve (used in Bitcoin)
547
+ private_key = EC::PrivateKey.new( 50303382071965675924643368363408442017264130870580001935435312336103014915707 )
548
+
549
+ public_key = private_key.public_key ## the "magic" one-way K=k*G curve multiplication (K=public key,k=private key, G=generator point)
550
+ point = public_key.point
551
+
552
+ point.x
553
+ #=> 17761672841523182714332746445483761684317159074072585653954580096478387916431
554
+ point.y
555
+ #=> 81286693084077906561204577435230199871025343781583806206090259868058973358862
556
+ ```
557
+
558
+ and convert the point to the compressed or uncompressed
559
+ Standards for Efficient Cryptography (SEC)
560
+ format used in Bitcoin:
561
+
562
+ ``` ruby
563
+ point.to_s( :compressed )
564
+ #=> "022744c02580b4905349bc481a60c308c2d98d823d44888835047f6bc5c38c4e8f"
565
+ point.to_s( :uncompressed )
566
+ #=> "042744c02580b4905349bc481a60c308c2d98d823d44888835047f6bc5c38c4e8fb3b6a34b90a571f6c2a1113dd5ff4576f61bbf3e970a6e148fa02bf9eb7bcb0e"
567
+ ```
568
+
569
+
570
+ References
571
+
572
+ - [Private key @ Learn me a bitcoin](https://learnmeabitcoin.com/technical/private-key)
573
+ - [Public key @ Learn me a bitcoin](https://learnmeabitcoin.com/technical/public-key)
574
+
575
+
576
+ ### Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key
577
+
578
+ Let's follow the steps from [How to create Bitcoin Address](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses#How_to_create_Bitcoin_Address):
579
+
580
+ ``` ruby
581
+ # Lets start with the public key ("raw" hex string encoded in compressed format)
582
+ pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
583
+
584
+ # 1. Perform SHA-256 hashing on the public key
585
+ step1 = sha256( pk )
586
+ #=> "0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98"
587
+
588
+ # 2. Perform RIPEMD-160 hashing on the result of SHA-256
589
+ step2 = ripemd160( step1 )
590
+ #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
591
+
592
+ # 3. Add version byte in front of RIPEMD-160 hash (0x00 for Bitcoin Main Network)
593
+ step3 = "00" + step2
594
+ #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
595
+
596
+ # 4. Perform SHA-256 hash on the extended RIPEMD-160 result
597
+ step4 = sha256( step3 )
598
+ #=> "ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c"
599
+
600
+ # 5. Perform SHA-256 hash on the result of the previous SHA-256 hash
601
+ step5 = sha256( step4 )
602
+ #=> "c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd"
603
+
604
+ # 6. Take the first 4 bytes of the second SHA-256 hash. This is the address checksum
605
+ step6 = step5[0..7] # note: 4 bytes in hex string are 8 digits/chars
606
+ #=> "c7f18fe8"
607
+
608
+ # 7. Add the 4 checksum bytes from step 6 at the end of
609
+ # extended RIPEMD-160 hash from step 3.
610
+ # This is the 25-byte binary Bitcoin Address.
611
+ step7 = step3 + step6
612
+ #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8"
613
+
614
+ # 8. Convert the result from a byte string into a base58 string using Base58 encoding.
615
+ # This is the most commonly used Bitcoin Address format.
616
+ addr = base58( step7 )
617
+ #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
618
+ ```
619
+
620
+ Or let's try again with the shortcut helpers:
621
+
622
+ - `HASH160 - RMD160(SHA256(X))`
623
+ - `BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])`
624
+
625
+ ``` ruby
626
+ # Lets start with the public key ("raw" hex string encoded in compressed format)
627
+ pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
628
+
629
+ # 1. Perform HASH-160 hashing on the public key
630
+ # a) Perform SHA-256 hashing on the public key
631
+ # b) Perform RIPEMD-160 hashing on the result of SHA-256
632
+ step1 = hash160( pk )
633
+ #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
634
+
635
+ # 2. Add version byte in front of RIPEMD-160 hash (0x00 for Bitoin Main Network)
636
+ step2 = "00" + step1
637
+ #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
638
+
639
+ # 3. Encode with BASE58CHECK
640
+ # a) Perform SHA-256 hash on the extended RIPEMD-160 result
641
+ # b) Perform SHA-256 hash on the result of the previous SHA-256 hash
642
+ # c) Take the first 4 bytes of the second SHA-256 hash. This is the address checksum
643
+ # d) Add the 4 checksum bytes at the end of
644
+ # extended RIPEMD-160 hash from step 2.
645
+ # This is the 25-byte binary Bitcoin Address.
646
+ # e) Convert the result from a byte string into a base58 string
647
+ # using Base58 encoding.
648
+ # This is the most commonly used Bitcoin Address format.
649
+ addr = base58check( step2 )
650
+ #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
651
+ ```
652
+
653
+
654
+ References
655
+
656
+ - [How to create Bitcoin Address](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses#How_to_create_Bitcoin_Address)
657
+ - [Ruby Quiz #15 - Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key](https://github.com/planetruby/quiz/tree/master/015)
658
+
659
+
660
+
661
+ ### Encode the Bitcoin Private Key in the Wallet Import Format (WIF)
662
+
663
+
664
+ A Wallet Import Format (WIF) private key is a standard private key, but with a few added extras:
665
+
666
+ - Version Byte prefix - The network the private key is to be used on.
667
+ - `0x80` = Mainnet
668
+ - `0xEF` = Testnet
669
+ - Compression Byte suffix (optional) - Flag if the private key is used to create a compressed public key.
670
+ - `0x01`
671
+ - Checksum - Useful for detecting errors/typos when you type out your private key; calculated using the first 4 bytes of the double sha256 hash `SHA256(SHA256(X))[:4]`.
672
+
673
+ This is all then converted to Base58, which shortens the string and makes it easier to transcribe.
674
+
675
+ ``` ruby
676
+ privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2"
677
+ extended = "80" + privatekey + "01"
678
+ #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db201"
679
+ checksum = hash256( extended )[0..7]
680
+ #=> "66557e53"
681
+ extendedchecksum = extended + checksum
682
+ #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db20166557e53"
683
+ wif = base58( extendedchecksum )
684
+ #=> "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6"
685
+ ```
686
+
687
+ Or let's try again with the base58check (`BASE58(X || SHA256(SHA256(X))[:4])`) shortcut helper:
688
+
689
+ ``` ruby
690
+ privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2"
691
+ extended = "80" + privatekey + "01"
692
+ #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db201"
693
+ wif = base58check( extended )
694
+ #=> "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6"
695
+ ```
696
+
697
+ References
698
+
699
+ - [How to create a WIF private key @ Learn me a bitcoin](https://learnmeabitcoin.com/technical/wif)
700
+ - [Private key to WIF @ Wallet import format](https://en.bitcoin.it/wiki/Wallet_import_format)
701
+
702
+
703
+ Bonus: Bitcon Tip - How to Buy Bitcoin (The CO₂-Friendly Way)
704
+
705
+ > 1. Take one $50 bill, five $10 bills, or ten $5 bills (I wouldn't recommend change - stay with paper money).
706
+ > 2. Go to the bathroom.
707
+ > 3. Lift the lid of the loo.
708
+ > 4. Throw money in.
709
+ > 5. Flush down water.
710
+ >
711
+ > Congrats! You just purchased $50 worth of Bitcoin - without fucking the planet!
712
+ >
713
+ > -- Trolly McTrollface, Bitcon Greater Fool Court Jester
714
+
715
+ Read more [Crypto Quotes »](https://github.com/openblockchains/crypto-quotes)
716
+
717
+
718
+
719
+
720
+
721
+ ## Dodge
722
+
723
+ > Even fun money is money, and a toy cryptocurrency can be turned into real money;
724
+ > the supply of gullibility is deep, if not infinite.
725
+ > So the shibes started dreaming of getting rich for free...
726
+ >
727
+ > -- David Gerard, [Confused About Dogecoin? Here's How It (Doesn't) Work](https://foreignpolicy.com/2021/02/11/dogecoin-how-does-it-work-elon-musk-cryptocurrency/)
728
+ >
729
+ >
730
+ > Dogecoin is the people's crypto.
731
+ > The future currency of earth and mars. Much wow!
732
+ >
733
+ > -- Elon Musk, [February 2021](https://twitter.com/elonmusk/status/1357241340313141249)
734
+
735
+ <!--
736
+ sources:
737
+ https://twitter.com/elonmusk/status/1357241340313141249
738
+ https://twitter.com/elonmusk/status/1357914696645414913
739
+ https://twitter.com/elonmusk/status/1357902434580918274
740
+ -->
741
+
742
+
743
+
744
+ ### Derive the Dodge (Elliptic Curve) Public Key from the Private Key
745
+
746
+ Short version: Same as in Ethereum, Bitcoin, Litecoin
747
+
748
+ Long version:
749
+ A private key in dodge is a 32-byte (256-bit) unsigned / positive integer number.
750
+
751
+ Or more precise the private key is a random number between 1
752
+ and the order of the elliptic curve secp256k1.
753
+
754
+
755
+ ``` ruby
756
+ EC::SECP256K1.order
757
+ #=> 115792089237316195423570985008687907852837564279074904382605163141518161494337
758
+
759
+ # or in hexadecimal (base16)
760
+ EC::SECP256K1.order.to_s(16)
761
+ #=> "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
762
+ ```
763
+
764
+
765
+ #### Step 1 - Let's generate a private key
766
+
767
+ ``` ruby
768
+ private_key = EC::PrivateKey.generate # alice
769
+ private_key.to_i
770
+ #=> 50303382071965675924643368363408442017264130870580001935435312336103014915707
771
+ private_key.to_s
772
+ #=> "6f36b48dd130618049ca27e1909debdf3665cf0df0ade0986f0c50123107de7b"
773
+
774
+ private_key = EC::PrivateKey.generate # bob
775
+ private_key.to_i
776
+ #=> 96396065671557366547785856940504404648366202869823009146014078671352808008442
777
+ private_key.to_s
778
+ #=> "d51e3d5ce8fbc6e574cf78d1c46e8936c26f38b002b954d0eac8aef195d6eafa"
779
+ ```
780
+
781
+
782
+ #### Step 2 - Let's derive / calculate the public key from the private key - Enter elliptic curve (EC) cryptography
783
+
784
+ The public key (`K`) are two numbers (that is, a point with the coordinates x and y) computed by multiplying
785
+ the generator point (`G`) of the curve with the private key (`k`) e.g. `K=k*G`.
786
+ This is equivalent to adding the generator to itself `k` times.
787
+ Magic?
788
+ Let's try:
789
+
790
+
791
+ ``` ruby
792
+ # note: by default uses Secp256k1 curve (used in Dodge)
793
+ private_key = EC::PrivateKey.new( 50303382071965675924643368363408442017264130870580001935435312336103014915707 )
794
+
795
+ public_key = private_key.public_key ## the "magic" one-way K=k*G curve multiplication (K=public key,k=private key, G=generator point)
796
+ point = public_key.point
797
+
798
+ point.x
799
+ #=> 17761672841523182714332746445483761684317159074072585653954580096478387916431
800
+ point.y
801
+ #=> 81286693084077906561204577435230199871025343781583806206090259868058973358862
802
+ ```
803
+
804
+ and convert the point to the compressed or uncompressed
805
+ Standards for Efficient Cryptography (SEC)
806
+ format used in Dodge:
807
+
808
+ ``` ruby
809
+ point.to_s( :compressed )
810
+ #=> "022744c02580b4905349bc481a60c308c2d98d823d44888835047f6bc5c38c4e8f"
811
+ point.to_s( :uncompressed )
812
+ #=> "042744c02580b4905349bc481a60c308c2d98d823d44888835047f6bc5c38c4e8fb3b6a34b90a571f6c2a1113dd5ff4576f61bbf3e970a6e148fa02bf9eb7bcb0e"
813
+ ```
814
+
815
+ ### Generate the Dodge Address from the (Elliptic Curve) Public Key
816
+
817
+ Short version:
818
+ Same as bitcoin or litecoin.
819
+ Only difference - Add the version byte `0x1e` prefix for Dodge Main Network - P2PKH (pay to public key hash).
820
+
821
+
822
+ Long version:
823
+ Let's use the shortcut hash function helpers:
824
+
825
+ - `HASH160 - RMD160(SHA256(X))`
826
+ - `BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])`
827
+
828
+ ``` ruby
829
+ # Lets start with the public key ("raw" hex string encoded in compressed format)
830
+ pk = "022744c02580b4905349bc481a60c308c2d98d823d44888835047f6bc5c38c4e8f"
831
+
832
+ # 1. Perform HASH-160 hashing on the public key
833
+ # a) Perform SHA-256 hashing on the public key
834
+ # b) Perform RIPEMD-160 hashing on the result of SHA-256
835
+ step1 = hash160( pk )
836
+ #=> "a1f37969bcb547cd9c3a28fa07c2269ef813340a"
837
+
838
+ # 2. Add version byte in front of RIPEMD-160 hash (0x1e for Dodge Main Network)
839
+ step2 = "1e" + step1
840
+ #=> "1ea1f37969bcb547cd9c3a28fa07c2269ef813340a"
841
+
842
+ # 3. Encode with BASE58CHECK
843
+ # a) Perform SHA-256 hash on the extended RIPEMD-160 result
844
+ # b) Perform SHA-256 hash on the result of the previous SHA-256 hash
845
+ # c) Take the first 4 bytes of the second SHA-256 hash. This is the address checksum
846
+ # d) Add the 4 checksum bytes at the end of
847
+ # extended RIPEMD-160 hash from step 2.
848
+ # This is the 25-byte binary Dodge Address.
849
+ # e) Convert the result from a byte string into a base58 string
850
+ # using Base58 encoding.
851
+ # This is the most commonly used Dodge Address format.
852
+ addr = base58check( step2 )
853
+ #=> "DKuR12onkdp5GxC5c8DgXhGe4Z2AqCK3Xh"
854
+ ```
855
+
856
+
857
+ ## Litecoin
858
+
859
+ ### Derive the Litecoin (Elliptic Curve) Public Key from the Private Key
860
+
861
+ Short version: Same as in Ethereum, Bitcoin, Dodge.
862
+
863
+ ### Generate the Litecoin Address from the (Elliptic Curve) Public Key
864
+
865
+ Short version: Same as in Bitcoin or Dodge.
866
+ Only difference - Add the version byte `0x30` prefix for Litecoin Main Network - P2PKH (pay to public key hash).
867
+
868
+
869
+
870
+
871
+
872
+ ## Ethereum
873
+
874
+ ### Derive the Ethereum (Elliptic Curve) Public Key from the Private Key
875
+
876
+ A private key in ethereum is a 32-byte (256-bit) unsigned / positive integer number.
877
+
878
+ Or more precise the private key is a random number between 1
879
+ and the order of the elliptic curve secp256k1.
880
+
881
+
882
+ ``` ruby
883
+ EC::SECP256K1.order
884
+ #=> 115792089237316195423570985008687907852837564279074904382605163141518161494337
885
+
886
+ # or in hexadecimal (base16)
887
+ EC::SECP256K1.order.to_s(16)
888
+ #=> "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
889
+ ```
890
+
891
+ Note: A "raw" private key in ethereum is the same as in bitcoin, litecoin, dodge & co using the same elliptic curve secp256k1.
892
+ See [Derive the Bitcoin (Elliptic Curve) Public Key from the Private Key](#derive-the-bitcoin-elliptic-curve-public-key-from-the-private-key) above.
893
+
894
+
895
+
896
+ #### Step 1 - Let's generate a private key
897
+
898
+ ``` ruby
899
+ private_key = EC::PrivateKey.generate # alice
900
+ private_key.to_i
901
+ #=> 50303382071965675924643368363408442017264130870580001935435312336103014915707
902
+ private_key.to_s
903
+ #=> "6f36b48dd130618049ca27e1909debdf3665cf0df0ade0986f0c50123107de7b"
904
+
905
+ private_key = EC::PrivateKey.generate # bob
906
+ private_key.to_i
907
+ #=> 96396065671557366547785856940504404648366202869823009146014078671352808008442
908
+ private_key.to_s
909
+ #=> "d51e3d5ce8fbc6e574cf78d1c46e8936c26f38b002b954d0eac8aef195d6eafa"
910
+ ```
911
+
912
+ Or use your own (secure) random number.
913
+ Let's follow along the example
914
+ in the [Mastering Ethereum book](https://github.com/ethereumbook/ethereumbook/blob/develop/04keys-addresses.asciidoc#generating-a-private-key-from-a-random-number) and let's use the random number:
915
+ `0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315`.
916
+
917
+ ``` ruby
918
+ private_key = EC::PrivateKey.new( 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 )
919
+ private_key.to_i
920
+ #=> 112612889188223089164322846106333497020645518262799935528047458345719983960853
921
+ private_key.to_s
922
+ #=> "f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315"
923
+ ```
924
+
925
+ #### Step 2 - Let's derive / calculate the public key from the private key - Enter elliptic curve (EC) cryptography
926
+
927
+ The public key (`K`) are two numbers (that is, a point with the coordinates x and y) computed by multiplying
928
+ the generator point (`G`) of the curve with the private key (`k`) e.g. `K=k*G`.
929
+ This is equivalent to adding the generator to itself `k` times.
930
+ Magic?
931
+ Let's try:
932
+
933
+
934
+ ``` ruby
935
+ # note: by default uses Secp256k1 curve (used in Ethereum)
936
+ private_key = EC::PrivateKey.new( 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 )
937
+
938
+ public_key = private_key.public_key ## the "magic" one-way K=k*G curve multiplication (K=public key,k=private key, G=generator point)
939
+ point = public_key.point
940
+
941
+ point.x
942
+ #=> 17761672841523182714332746445483761684317159074072585653954580096478387916431
943
+ point.y
944
+ #=> 81286693084077906561204577435230199871025343781583806206090259868058973358862
945
+
946
+ # or in hexa(decimal) - base 16
947
+ point.x.to_s(16)
948
+ #=> "6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b"
949
+ point.y.to_s(16)
950
+ #=> "83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0"
951
+ ```
952
+
953
+ and convert the point to the raw uncompressed
954
+ format used in Ethereum:
955
+
956
+ ``` ruby
957
+ ## add together the two points (x,y) in a hex string
958
+ "%64x%64x" % [point.x, point.y]
959
+ #=> "6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0"
960
+
961
+ # or
962
+ ("%64x" % point.x) + ("%64x" % point.y)
963
+ #=> "6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0"
964
+ ```
965
+
966
+ References
967
+
968
+ - [Keys and Addresses in Mastering Ethereum](https://github.com/ethereumbook/ethereumbook/blob/develop/04keys-addresses.asciidoc#keys-and-addresses)
969
+
970
+
971
+
972
+ ### Generate the Ethereum Address from the (Elliptic Curve) Public Key
973
+
974
+ Let's again follow along the example
975
+ in the [Mastering Ethereum book](https://github.com/ethereumbook/ethereumbook/blob/develop/04keys-addresses.asciidoc#ethereum-addresses) and let's (re)use the public key (from above):
976
+
977
+
978
+ Step 1: Use the keccak256 hashing function
979
+ to calculate the hash of the public key
980
+
981
+ ``` ruby
982
+ pub = "6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0"
983
+ hash = keccak256( pub )
984
+ #=> "2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9"
985
+ ```
986
+
987
+ Step 2: Keep only the last 20 bytes (least significant bytes), this is the ethereum address
988
+
989
+ ``` ruby
990
+ hash[24,40] ## last 20 bytes of 32 (skip first 12 bytes (12x2=24 hex chars))
991
+ hash[-40..-1] ## -or- last 20 bytes (40 hex chars)
992
+ hash[-40,40] ## -or- last 20 bytes (40 hex chars)
993
+ #=> "001d3f1ef827552ae1114027bd3ecf1f086ba0f9"
994
+ ```
995
+
996
+ Note: Most often you will see ethereum addresses with the prefix `0x` that indicates
997
+ they are hexadecimal-encoded, like this: `0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9`.
998
+
999
+ References
1000
+
1001
+ - [Keys and Addresses in Mastering Ethereum](https://github.com/ethereumbook/ethereumbook/blob/develop/04keys-addresses.asciidoc#keys-and-addresses)
1002
+
1003
+
1004
+
1005
+
1006
+ ## Install
1007
+
1008
+ Just install the gem:
1009
+
1010
+ $ gem install crypto-lite
1011
+
1012
+
1013
+ ## License
1014
+
1015
+ The scripts are dedicated to the public domain.
1016
+ Use it as you please with no restrictions whatsoever.
1017
+
1018
+
1019
+ ## Questions? Comments?
1020
+
1021
+ Send them along to the [wwwmake forum](http://groups.google.com/group/wwwmake).
1022
+ Thanks!
1023
+