crypto-lite 0.2.3 → 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,501 +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
-
42
-
43
- Onwards with more sha256 examples:
44
-
45
- ``` ruby
46
- ## try a
47
- sha256( "a" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
48
- sha256( "\x61" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
49
- sha256( 0b01100001 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
50
- sha256( 0x61 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
51
-
52
- sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
53
- sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
54
-
55
- # "auto-magic" hex string to binary string conversion heuristic
56
- sha256( '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
57
-
58
-
59
- ## try some more
60
- sha256( "Hello, Cryptos!" ) #=> "33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5"
61
- ```
62
-
63
-
64
- **SHA3-256 - Secure Hashing Algorthim (SHA) 3, 256-Bit (32 Bytes)**
65
-
66
- ``` ruby
67
- sha3_256( "Hello, Cryptos!" ) #=> "7dddf4bc9b86352b67e8823e5010ddbd2a90a854469e2517992ca7ca89e5bd58"
68
- ```
69
-
70
- Note: Yes, SHA256 vs SHA3-256 / SHA-2 vs SHA-3 the hashing functions are
71
- different (although the 256-bit hash size output is the same).
72
- The sha256 hashing function is part of the Secure Hash Algorithm (SHA) 2 family / standards first published in 2001.
73
- The sha3_256 is part of the (newer) Secure Hash Algorithm (SHA) 3 family / standards first published in 2015
74
- (and uses the Keccak cryptographic primitive "under the hood").
75
-
76
-
77
-
78
- **Keccak 256-Bit**
79
-
80
- ``` ruby
81
- keccak256( "Hello, Cryptos!" ) #=> "2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5"
82
- ```
83
-
84
-
85
- #### Aside - Keccak vs SHA3 / Original vs Official
86
-
87
- In 2004 the U.S. National Institute of Standards and Technology (NIST)
88
- changed the padding to `SHA3-256(M) = KECCAK [512] (M || 01, 256)`.
89
- This is different from the padding proposed by the Keccak team in
90
- the original Keccak SHA-3 submission version 3 (the final, winning version).
91
- The difference is the additional `'01'` bits appended to the message.
92
-
93
- To help avoid confusion the "submitted original version 3" SHA-3 Keccak
94
- hashing is now called "Keccak"
95
- and the finalized NIST SHA-3 standard "SHA3".
96
-
97
- Tip: If you don't know what variant of the hash function you have -
98
- original or official? - check your hash:
99
-
100
- For keccak 256-bit:
101
-
102
- ``` ruby
103
- keccak256( '' ) #=> "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
104
- ```
105
-
106
- For sha3 256-bit:
107
-
108
- ``` ruby
109
- sha3_256( '' ) #=> "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
110
- ```
111
-
112
-
113
-
114
- **RMD / RIPE-MD - RACE¹ Integrity Primitives Evaluation Message Digest 160-Bit**
115
-
116
- ¹: Research and development in Advanced Communications technologies in Europe
117
-
118
-
119
- ``` ruby
120
- rmd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
121
- # or use the alias / alternate name
122
- ripemd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
123
- ```
124
-
125
-
126
- #### Aside - Hex String `"0x616263"` vs Binary String `"\x61\x62\x63" == "abc"`
127
-
128
- Note: All hash functions operate on binary strings ("byte arrays")
129
- and NOT hex strings.
130
-
131
- Note: For hex strings the `0x` or `0X` prefix is optional.
132
- Examples of hex strings:
133
-
134
- ``` ruby
135
- # hex string binary string ("byte array")
136
- "61" "\x61" == "a"
137
- "0x61" "\x61" == "a"
138
-
139
- "616263" "\x61\x62\x63" == "abc"
140
- "0x616263" "\x61\x62\x63" == "abc"
141
- "0X616263" "\x61\x62\x63" == "abc"
142
-
143
- # or 160-bit hex string (hash)
144
- "93ce48570b55c42c2af816aeaba06cfee1224fae"
145
- "0x93ce48570b55c42c2af816aeaba06cfee1224fae"
146
-
147
- # or 256-bit hex string (hash)
148
- "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
149
- "0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
150
- ```
151
-
152
- You can use `[str].pack( 'H*' )`
153
- to convert a hex string into a binary string.
154
- Note: The standard `Array#pack` conversion
155
- will NOT "auto-magically" cut-off the `0x` or `0X` prefix.
156
-
157
-
158
- If you know you have a hex string use the `hex:` keyword to pass
159
- in the arg(ument)
160
- to the hash function and that will "automagically"
161
- handle the hex-to-bin conversion for you. Example:
162
-
163
- ``` ruby
164
- sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
165
- sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
166
-
167
- sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
168
- sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
169
- sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
170
- ```
171
-
172
- What about the built-in "auto-magic" hex-to-bin conversion / heuristic?
173
-
174
- Yes, if your passed in string starts with the
175
- the `0x` or `0X` prefix the string gets "auto-magically" converted
176
- to binary. Or if your passed in string is all hexadecimal characters,
177
- that is, `0-9` and `a-f` and has a minimum length of ten characters.
178
- Example:
179
-
180
-
181
- ``` ruby
182
- # "auto-magic" hex string to binary string conversion heuristic
183
-
184
- sha256( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
185
- sha256( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
186
-
187
- # or without 0x or 0X BUT with minimum heuristic length
188
- hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' )
189
- #=> "93ce48570b55c42c2af816aeaba06cfee1224fae"
190
-
191
- hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
192
- #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711"
193
-
194
- # and so on
195
- ```
196
-
197
-
198
- #### Hash Function Helpers
199
-
200
- **HASH160 - RMD160(SHA256(X))**
201
-
202
- 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.
203
-
204
-
205
- ``` ruby
206
- hash160( '02b9d1cc0b793b03b9f64d022e9c67d5f32670b03f636abf0b3147b34123d13990' )
207
- #=> "e6b145a3908a4d6616b13c1109717add8672c900"
208
-
209
- hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' )
210
- #=> "93ce48570b55c42c2af816aeaba06cfee1224fae"
211
- ```
212
-
213
-
214
- **HASH256 - SHA256(SHA256(X))**
215
-
216
- All-in-one double sha256 hash helper, that is, first hash with sha256 and than hash with sha256 again. Why? Arguably higher security.
217
-
218
- > SHA256(SHA256(X)) was proposed by Ferguson and Schneier in their excellent book "Practical Cryptography"
219
- > (later updated by Ferguson, Schneier, and Kohno and renamed "Cryptography Engineering") as a way to make SHA256 invulnerable
220
- > to "length-extension" attack. They called it "SHA256D".
221
-
222
-
223
- ``` ruby
224
- hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
225
- #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711"
226
- ```
227
-
228
- #### Base58 Encoding / Decoding Helpers
229
-
230
- **BASE58**
231
-
232
- Base58 encoding / decoding with leading zero bytes (in hex or binary strings) getting encoded from `00` to `1` and back:
233
-
234
- ``` ruby
235
- base58( "516b6fcd0f" ) #=> "ABnLTmg"
236
- base58( "00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ"
237
- # or with optional 0x or 0X prefix
238
- base58( "0x516b6fcd0f" ) #=> "ABnLTmg"
239
- base58( "0x00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ"
240
-
241
- unbase58( "ABnLTmg" ) #=> "516b6fcd0f"
242
- unbase58( "111111111143c9JGph3DZ" ) #=> "00000000000000000000123456789abcdef0"
243
- ```
244
-
245
-
246
- **BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])**
247
-
248
- Base58 encoding with an extra 4-byte secure hash checksum.
249
-
250
- ``` ruby
251
- base58check( "516b6fcd0f" ) #=> "237LSrY9NUUas"
252
- base58check( "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ) #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
253
-
254
- unbase58check( "237LSrY9NUUas" ) #=> "516b6fcd0f"
255
- unbase58check( "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" ) #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
256
- ```
257
-
258
-
259
-
260
- ### Public Key Signature Algorithms
261
-
262
- **RSA - Rivest, Shamir and Adleman**
263
-
264
-
265
-
266
- ``` ruby
267
- alice_key, alice_pub = RSA.generate_keys
268
-
269
- alice_key
270
- #=> "-----BEGIN RSA PRIVATE KEY-----
271
- # MIIEpAIBAAKCAQEAzLpmAQ+MbUTHU1XxzEaQXqiOvk0Vu/skztaMWz+UoGYWU6eW
272
- # cr7zVt/Y0SYqzD8LkYireX22FxNNFfhgu3/uC5yTl+dri6PD6NDAmrG+1cyE8kZZ
273
- # MGq91wQEemZPuesjTgKEvwZbknjodIKOAP35QycMr4PuWICSrCjhJLrClI7jInTZ
274
- # LOLtD5w5U7/xLOJAIfuhjUA4wrFCLJGPe7214KWgDCLmsan4/GVUloUKa6KAHJiH
275
- # q4tNxNdSrbOlluZbKQl8REhXOCIb5bEX2KnbQT0nPgKkuOlXgZ7jeyOIk0FG1RGa
276
- # FvcGu8LieMgT39WltcHJLblNkDr9YDRGiNiThQIDAQABAoIBAQCE/FPEPqBeXj4I
277
- # MRzHL9MZ2e4XSaVjnYjUXuN/ZnaaFpZMMuF0mfshpHiHq35DfHR8TcXtPi6pIJ2D
278
- # NvtG8JvlqQjqtKXUaEWbFvb1xZ4L7TUy12WaIMw+PlrWU11YjJg7VUF7gJq9M5L0
279
- # E9ZAaLmg2F3SKSYLEUG1WTyeij5ZFqouNjZxD2xo5U5Agy2UVm2D9aUm/n4g8Wnr
280
- # HybadhD6V9+BsZ2e9Q6CamHRah9Hs4nDPnycPFXpbs32wx9nvACPMg5+/Fqxr/ZK
281
- # cPM4syVBW0lNhpTzhHkPvimAgwgqJYvAj/o9nQnq5i1XyVyXp3uKVnld3FCddf9i
282
- # ovQMPmVlAoGBAPHtUKRehy8df/Zw6oGz0WcZCTjEwZ9DEb5rFN9Pr2IyvOhmZ3UJ
283
- # JNx9WmiiGB44dbnafMtr2Ya7u4OAM6e190BbcJKTnpWqVlsXw/wyQqIgJb3AtFu4
284
- # 91mqsDepOWsfs1IjTgmR1OM29WXjGoPHtV9E6//uVmVsciEvkCtcRfGDAoGBANij
285
- # IbZ3mL1rr8uRT/czPLkZ3KPLsJhPriuc6yyOq+tqQ6d3u/1DjKxoeYa7Jbyj7Dwl
286
- # 2wHQf9vRz3Kb2Mw+hPcHGDO9aBWxvZXjxxrVk6g1Ei0mvIP0k8ZbnlReK3cr5ktl
287
- # aY/ZWDDVPpY4aqkcOIbAAi95jPlpb2LsntijxoBXAoGABPJRP8sfAHud7jAI23YN
288
- # xgnhAmQjgVohtr8Bwj8i2uMmsanGW8JAGrIFczY9QADvh0lMW+xsmjCkeN/aLoet
289
- # 8obsGlMiXvUIpvwpabKtYhs+Kk8SYP27MP4odDrljacsR3WpVtDAhZTOF7M5C5C9
290
- # yKDkImuBILnC66LJU9mjJHkCgYEAntDxDSCeQ/dnOBh+hB323UgdXaMdAnwflm+C
291
- # ZPbvCDWuBV6c3W2g+l/Y/7HBV4rgy7OA29KreU5WA5JHHGyU87gqwPuRC55y+yiy
292
- # NXTvu7e0bI9iUmaB00AlUXp76PCw8wMUoVVX9uzN5jjT0MgUlIy8zWsRs2LdOqt3
293
- # RCDEjB8CgYAO6ZptzyJ4FS7ucjKfjig5WMOiKMcIUtTG9qedHmE2Z6vt3g0SQWaD
294
- # zJJacSoRHAdRK61vOlg4k+9/9LjffDrk9uT555BDbYqKWlmST7JMfvO7EpaIMYUu
295
- # CN7+3Rx9gSLyScqtAYiT/LgYgL1Vc6/e0XHaVjA85kPvUDKb785oFg==
296
- # -----END RSA PRIVATE KEY-----"
297
-
298
- alice_pub
299
- #=> "-----BEGIN PUBLIC KEY-----
300
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzLpmAQ+MbUTHU1XxzEaQ
301
- # XqiOvk0Vu/skztaMWz+UoGYWU6eWcr7zVt/Y0SYqzD8LkYireX22FxNNFfhgu3/u
302
- # C5yTl+dri6PD6NDAmrG+1cyE8kZZMGq91wQEemZPuesjTgKEvwZbknjodIKOAP35
303
- # QycMr4PuWICSrCjhJLrClI7jInTZLOLtD5w5U7/xLOJAIfuhjUA4wrFCLJGPe721
304
- # 4KWgDCLmsan4/GVUloUKa6KAHJiHq4tNxNdSrbOlluZbKQl8REhXOCIb5bEX2Knb
305
- # QT0nPgKkuOlXgZ7jeyOIk0FG1RGaFvcGu8LieMgT39WltcHJLblNkDr9YDRGiNiT
306
- # hQIDAQAB
307
- # -----END PUBLIC KEY-----"
308
-
309
- bob_key, bob_pub = RSA.generate_keys
310
-
311
- bob_key
312
- #=> "-----BEGIN RSA PRIVATE KEY-----
313
- # MIIEpAIBAAKCAQEAzADannvKlfVkZmKA4EDIxTW0HiJzjD6Auh8wLi02+iz2BScz
314
- # fECA65Zv+KHfc1B9AWMqGeBIwFE49NrsnXiZwZR3DqcFS8WbnVqpntvhwzlEARna
315
- # RWmZ2XjloD7fxILbXtWfMFNjwSfaK0bpArLkrt9d8eni+JI42+ptIWs/bVynACqm
316
- # DqOTjoEgajuHVpxHtskPNQrsjxzP+umsUWkbE0iaO7oN1pcgZIR4VRr0bz/3Juif
317
- # WmiCgwbDZo1WolfveoCacVsfAB1iesxeWnrGIJUjq8Mqsu9mQz1dg6RF4ElwNJ57
318
- # G3T3nlW+qpVBZDU2sHFqUFxbGmWPdRUn1yn4KwIDAQABAoIBAQCOCwotz4P/Zh3C
319
- # LFQP0Qv6RKplURejTuHStmSVwmXFTAkBDYqLuV4Kq3TLaepsIF7p2GI4IjKFtggy
320
- # dTzLaG2mm/lJ+oF1gOIZbkcslW1cwULYgWe5bQ3ynntEWIL2ESctoRB2VZnfpCAE
321
- # ghs8BdO071I6Xt/qs+VjOpdB7ar8OYhFc1vhwiI03FKbjuScH0CQOETIeLCqK5tC
322
- # qPnjMTYdaTp/NgcZujsOeOBgbARLzGtCaESbmXHO6mPDkEED5uqZzsNBtdCZIGMF
323
- # ApJkZbF6xSRizQhwwRlak1jCkAk2VCYpKPMiop1+cbjs3jU3RyP94RHc/yKo2Rzm
324
- # HCl35XYBAoGBAPJDMV9W2scRsMlLw9In3ZzWtammcouE0oXEgizK61Cg/5C5E06a
325
- # 5anrfwF5bURBANKBqTSHV0u71C2fHs1KO+B+EHzQ4DKsXldCSv2PR/0A6lmF9AIL
326
- # DFfup/mU55plbqCnjJe2BOUrOmurSd5MbWtShRdGri/LBqF58BFgT+U1AoGBANeS
327
- # RZDsCWelZPGN8Wxp9zxhu1AClNO9S7ITjZOQTYlghCVKAkS1wvB/6TIjaw8DyREs
328
- # f6WvtkzQA/vZc4mXE+YM/calL8ee3wVEJJzlGBfuh8mQhxtiLa5PTl7Icv/R8DGV
329
- # 9hU9GkJgWdi/+Plpqdcv79OWVMTB7igmoN8PAPPfAoGAKqatwI04AygYKbhPB2bB
330
- # W2Vpoi6NqAaAUdCg4mXvO8i8daw/u+0FVf8B4y6PkB6pmGX/diIFum2dE1MaRyY0
331
- # mHdZS8AyWHmEOnSPY0igceiBWbV9mgZ769c2d3hBtir5aQtWczc2cWpE5MPJQ3vN
332
- # H8HtcIWfEQb7ad5f548/QakCgYEAwFDjNRYOkePQ+Vrbjg+/HKRH+mpDId9Xv4eI
333
- # H6R2N9/eJHIxMeFCB1Ll1PAaG6wR3ftn6YWnykEtvKpTU+VvQCZI5MYLqTgH2Ofh
334
- # DgOoCfmoNF922SwuerqPvSlwxt8hPOt/PZVkbuEMZr1lPgVRGwPOHmKYP2yPrkw/
335
- # 6p+1BtsCgYABmMLgWhXVD19XxNHm8XpGnPWTEjqAYrw6I5yDUwNhB0n4129qaC+x
336
- # MWrdslKBmQh1r1U5QoSSL0CY4Ef5qN02uZl15FN1kYQzZA6kJi+MoBsjzrZCvzsc
337
- # Bbahpg363PyHC75zgvazvOr4tK3mzaRi5RNTMgivTVu4FyhkRdJ5wQ==
338
- # -----END RSA PRIVATE KEY-----"
339
-
340
- bob_pub
341
- #=> "-----BEGIN PUBLIC KEY-----
342
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzADannvKlfVkZmKA4EDI
343
- # xTW0HiJzjD6Auh8wLi02+iz2BSczfECA65Zv+KHfc1B9AWMqGeBIwFE49NrsnXiZ
344
- # wZR3DqcFS8WbnVqpntvhwzlEARnaRWmZ2XjloD7fxILbXtWfMFNjwSfaK0bpArLk
345
- # rt9d8eni+JI42+ptIWs/bVynACqmDqOTjoEgajuHVpxHtskPNQrsjxzP+umsUWkb
346
- # E0iaO7oN1pcgZIR4VRr0bz/3JuifWmiCgwbDZo1WolfveoCacVsfAB1iesxeWnrG
347
- # IJUjq8Mqsu9mQz1dg6RF4ElwNJ57G3T3nlW+qpVBZDU2sHFqUFxbGmWPdRUn1yn4
348
- # KwIDAQAB
349
- # -----END PUBLIC KEY-----"
350
-
351
-
352
- tx = "from: alice, to: bob, $21"
353
- tx_hash = sha256( tx )
354
- #=> "426a472a6c69bf68354391b7822393bea3952cde9df8949ad7a0f5f405b2fcb5"
355
-
356
- tx_signature = RSA.sign( tx_hash, alice_key )
357
- #=> "xfhzC6tzXYmA5rFAFybJ9KeWnTcTnC0Plt7cSHky6ZSdBZRKz/sfFcpyIN7w
358
- # jWrdPwEREA3nwNu/HSpiGRBFr+lu/YgWGNp6HLGPeL7uHGAfmWPyU5WRzGzf
359
- # iEs5B6kdJ3S8LSbP0hkOD8AOgZLPeU5rzA4+/Ymt8e/UOVwwka6Gj13yoBua
360
- # mSdsVuQfgh2VpySejCz4ykYlMSHK8Kx8QFt+QbyI5QZUy2dFh6HlcnHR+G9A
361
- # RMRZ1vAuQhYqtDSsxwRcZCSFsc6uctAvsgFinhqy6ls5VpcXfuKwZhKAw3Di
362
- # E2MYUnT7+i38Mq26iWzgmDbpOrVCO5tjlSiHY1731A=="
363
-
364
- RSA.valid_signature?( tx_hash, tx_signature, alice_pub )
365
- #=> true
366
-
367
- tx = "from: alice, to: bob, $22"
368
- tx_hash = sha256( tx )
369
- #=> "e899604bb4c95d2f1a7cfe561ad65941769e2064bdbbcaa79eb64ce0a2832380"
370
-
371
- RSA.valid_signature?( tx_hash, tx_signature, alice_pub )
372
- #=> false
373
- ```
374
-
375
-
376
- and some more.
377
-
378
-
379
-
380
-
381
-
382
- ## Examples
383
-
384
- ### Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key
385
-
386
- 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):
387
-
388
- ``` ruby
389
- # Lets start with the public key ("raw" hex string encoded)
390
- pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
391
-
392
- # 1. Perform SHA-256 hashing on the public key
393
- step1 = sha256( pk )
394
- #=> "0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98"
395
-
396
- # 2. Perform RIPEMD-160 hashing on the result of SHA-256
397
- step2 = ripemd160( step1 )
398
- #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
399
-
400
- # 3. Add version byte in front of RIPEMD-160 hash (0x00 for Main Network)
401
- step3 = "00" + step2
402
- #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
403
-
404
- # 4. Perform SHA-256 hash on the extended RIPEMD-160 result
405
- step4 = sha256( step3 )
406
- #=> "ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c"
407
-
408
- # 5. Perform SHA-256 hash on the result of the previous SHA-256 hash
409
- step5 = sha256( step4 )
410
- #=> "c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd"
411
-
412
- # 6. Take the first 4 bytes of the second SHA-256 hash. This is the address checksum
413
- step6 = step5[0..7] # note: 4 bytes in hex string are 8 digits/chars
414
- #=> "c7f18fe8"
415
-
416
- # 7. Add the 4 checksum bytes from step 6 at the end of
417
- # extended RIPEMD-160 hash from step 3.
418
- # This is the 25-byte binary Bitcoin Address.
419
- step7 = step3 + step6
420
- #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8"
421
-
422
- # 8. Convert the result from a byte string into a base58 string using Base58 encoding.
423
- # This is the most commonly used Bitcoin Address format.
424
- addr = base58( step7 )
425
- #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
426
- ```
427
-
428
- Or let's try again with the shortcut helpers:
429
-
430
- - `HASH160 - RMD160(SHA256(X))`
431
- - `BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])`
432
-
433
- ``` ruby
434
- # Lets start with the public key ("raw" hex string encoded)
435
- pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
436
-
437
- # 1. Perform HASH-160 hashing on the public key
438
- # a) Perform SHA-256 hashing on the public key
439
- # b) Perform RIPEMD-160 hashing on the result of SHA-256
440
- step1 = hash160( pk )
441
- #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
442
-
443
- # 2. Add version byte in front of RIPEMD-160 hash (0x00 for Main Network)
444
- step2 = "00" + step1
445
- #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31"
446
-
447
- # 3. Encode with BASE58CHECK
448
- # a) Perform SHA-256 hash on the extended RIPEMD-160 result
449
- # b) Perform SHA-256 hash on the result of the previous SHA-256 hash
450
- # c) Take the first 4 bytes of the second SHA-256 hash. This is the address checksum
451
- # d) Add the 4 checksum bytes at the end of
452
- # extended RIPEMD-160 hash from step 2.
453
- # This is the 25-byte binary Bitcoin Address.
454
- # e) Convert the result from a byte string into a base58 string
455
- # using Base58 encoding.
456
- # This is the most commonly used Bitcoin Address format.
457
- addr = base58check( step2 )
458
- #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs"
459
- ```
460
-
461
-
462
- References
463
-
464
- - [How to create Bitcoin Address](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses#How_to_create_Bitcoin_Address)
465
- - [Ruby Quiz #15 - Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key](https://github.com/planetruby/quiz/tree/master/015)
466
-
467
- Bonus: Bitcon Tip - How to Buy Bitcoin (The CO₂-Friendly Way)
468
-
469
- > 1. Take one $50 bill, five $10 bills, or ten $5 bills (I wouldn't recommend change - stay with paper money).
470
- > 2. Go to the bathroom.
471
- > 3. Lift the lid of the loo.
472
- > 4. Throw money in.
473
- > 5. Flush down water.
474
- >
475
- > Congrats! You just purchased $50 worth of Bitcoin - without fucking the planet!
476
- >
477
- > -- Trolly McTrollface, Bitcon Greater Fool Court Jester
478
-
479
- Read more [Crypto Quotes »](https://github.com/openblockchains/crypto-quotes)
480
-
481
-
482
-
483
-
484
- ## Install
485
-
486
- Just install the gem:
487
-
488
- $ gem install crypto-lite
489
-
490
-
491
- ## License
492
-
493
- The scripts are dedicated to the public domain.
494
- Use it as you please with no restrictions whatsoever.
495
-
496
-
497
- ## Questions? Comments?
498
-
499
- Send them along to the [wwwmake forum](http://groups.google.com/group/wwwmake).
500
- Thanks!
501
-
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
+