crypto-lite 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7c97262d69928c8f9b51816fcf3fff1f5bc61ba5bf49bc81d011ec9567be877
4
- data.tar.gz: bfb41f345684cc2f27256e64d95f4a4535b908784f6353643bfef251c83262b7
3
+ metadata.gz: e32db0712ee1ed53c0720f9dee44533ffb8482e3d9ac6f5bd7a7e6a5c716cdc8
4
+ data.tar.gz: c3e8da15486a23e26d72c97c96bfc4f4c1847c420e7bff833c0ed87efe61303c
5
5
  SHA512:
6
- metadata.gz: 450adb10806e9944fafc4fdf04bb3b09a59fa6fc20ac62a8c9b48b780711ef23555174765b7f545ded98607185bad5488f116a691b34d253de7b7cd30d84fd62
7
- data.tar.gz: 524b2c9ae838156c20eb313a045057974e51339e912c48f6945864429ecfd958a7cc8236a83fbbd0121ebc119c2b4a0e76b4b55383b9e64e9ccee35363e912ea
6
+ metadata.gz: a6593de7e55dbaa353cef41df3cf25cf04fd17cef78f9e2c62fbdcf0bf234627e4ec0dc2f238a341d5de8fa8b3ae33045cb8cf468c80f5ea8a55f312ff7cc0a0
7
+ data.tar.gz: 2e54d60bd80f34568ff7a6852fc3da01d3066131d4c177c023c1c15b4497fe18af7ad28851668b9c45223cab4f7eb8089759fc9e51fac714820b4a7d3a509ef7
@@ -3,9 +3,16 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/crypto-lite.rb
6
+ lib/crypto-lite/config.rb
7
+ lib/crypto-lite/helper.rb
8
+ lib/crypto-lite/metal.rb
9
+ lib/crypto-lite/sign_rsa.rb
6
10
  lib/crypto-lite/version.rb
7
11
  lib/crypto.rb
8
12
  lib/crypto/lite.rb
9
13
  test/helper.rb
14
+ test/test_base58.rb
15
+ test/test_bitcoin_addr.rb
10
16
  test/test_hash.rb
17
+ test/test_hash_sha.rb
11
18
  test/test_version.rb
data/README.md CHANGED
@@ -12,31 +12,49 @@
12
12
 
13
13
  ### Secure Hashing / Hash Functions
14
14
 
15
- SHA256 - Secure Hash Algorithm (SHA) 256-bits (32 bytes)
15
+ **SHA256 - Secure Hash Algorithm (SHA) 256-Bit (32 Bytes)**
16
16
 
17
17
 
18
18
  ``` ruby
19
19
  require 'crypto' ## or use require 'crypto-lite'
20
20
 
21
21
  ## try abc
22
- sha256( "abc" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
23
- sha256( "abc".b ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
24
- sha256( "\x61\x62\x63" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
25
- sha256( 0x616263 ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
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.
26
42
 
27
- pp sha256hex( '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
28
- pp sha256hex( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
29
- pp sha256hex( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
30
43
 
44
+ Onwards with more sha256 examples:
31
45
 
46
+ ``` ruby
32
47
  ## try a
33
48
  sha256( "a" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
34
49
  sha256( "\x61" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
35
50
  sha256( 0b01100001 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
36
51
  sha256( 0x61 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
37
52
 
38
- sha256hex( '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
39
- sha256hex( '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
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"
40
58
 
41
59
 
42
60
  ## try some more
@@ -44,125 +62,431 @@ sha256( "Hello, Cryptos!" ) #=> "33eedea60b0662c66c289ceba71863a864cf84b00e1000
44
62
  ```
45
63
 
46
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
+
47
259
 
48
260
 
49
261
  ### Public Key Signature Algorithms
50
262
 
51
- RSA - Rivest-Shamir-Adleman
52
-
53
-
54
-
55
- ``` ruby
56
- alice_key, alice_pub = RSA.generate_keys
57
-
58
- alice_key
59
- #=> "-----BEGIN RSA PRIVATE KEY-----
60
- # MIIEpAIBAAKCAQEAzLpmAQ+MbUTHU1XxzEaQXqiOvk0Vu/skztaMWz+UoGYWU6eW
61
- # cr7zVt/Y0SYqzD8LkYireX22FxNNFfhgu3/uC5yTl+dri6PD6NDAmrG+1cyE8kZZ
62
- # MGq91wQEemZPuesjTgKEvwZbknjodIKOAP35QycMr4PuWICSrCjhJLrClI7jInTZ
63
- # LOLtD5w5U7/xLOJAIfuhjUA4wrFCLJGPe7214KWgDCLmsan4/GVUloUKa6KAHJiH
64
- # q4tNxNdSrbOlluZbKQl8REhXOCIb5bEX2KnbQT0nPgKkuOlXgZ7jeyOIk0FG1RGa
65
- # FvcGu8LieMgT39WltcHJLblNkDr9YDRGiNiThQIDAQABAoIBAQCE/FPEPqBeXj4I
66
- # MRzHL9MZ2e4XSaVjnYjUXuN/ZnaaFpZMMuF0mfshpHiHq35DfHR8TcXtPi6pIJ2D
67
- # NvtG8JvlqQjqtKXUaEWbFvb1xZ4L7TUy12WaIMw+PlrWU11YjJg7VUF7gJq9M5L0
68
- # E9ZAaLmg2F3SKSYLEUG1WTyeij5ZFqouNjZxD2xo5U5Agy2UVm2D9aUm/n4g8Wnr
69
- # HybadhD6V9+BsZ2e9Q6CamHRah9Hs4nDPnycPFXpbs32wx9nvACPMg5+/Fqxr/ZK
70
- # cPM4syVBW0lNhpTzhHkPvimAgwgqJYvAj/o9nQnq5i1XyVyXp3uKVnld3FCddf9i
71
- # ovQMPmVlAoGBAPHtUKRehy8df/Zw6oGz0WcZCTjEwZ9DEb5rFN9Pr2IyvOhmZ3UJ
72
- # JNx9WmiiGB44dbnafMtr2Ya7u4OAM6e190BbcJKTnpWqVlsXw/wyQqIgJb3AtFu4
73
- # 91mqsDepOWsfs1IjTgmR1OM29WXjGoPHtV9E6//uVmVsciEvkCtcRfGDAoGBANij
74
- # IbZ3mL1rr8uRT/czPLkZ3KPLsJhPriuc6yyOq+tqQ6d3u/1DjKxoeYa7Jbyj7Dwl
75
- # 2wHQf9vRz3Kb2Mw+hPcHGDO9aBWxvZXjxxrVk6g1Ei0mvIP0k8ZbnlReK3cr5ktl
76
- # aY/ZWDDVPpY4aqkcOIbAAi95jPlpb2LsntijxoBXAoGABPJRP8sfAHud7jAI23YN
77
- # xgnhAmQjgVohtr8Bwj8i2uMmsanGW8JAGrIFczY9QADvh0lMW+xsmjCkeN/aLoet
78
- # 8obsGlMiXvUIpvwpabKtYhs+Kk8SYP27MP4odDrljacsR3WpVtDAhZTOF7M5C5C9
79
- # yKDkImuBILnC66LJU9mjJHkCgYEAntDxDSCeQ/dnOBh+hB323UgdXaMdAnwflm+C
80
- # ZPbvCDWuBV6c3W2g+l/Y/7HBV4rgy7OA29KreU5WA5JHHGyU87gqwPuRC55y+yiy
81
- # NXTvu7e0bI9iUmaB00AlUXp76PCw8wMUoVVX9uzN5jjT0MgUlIy8zWsRs2LdOqt3
82
- # RCDEjB8CgYAO6ZptzyJ4FS7ucjKfjig5WMOiKMcIUtTG9qedHmE2Z6vt3g0SQWaD
83
- # zJJacSoRHAdRK61vOlg4k+9/9LjffDrk9uT555BDbYqKWlmST7JMfvO7EpaIMYUu
84
- # CN7+3Rx9gSLyScqtAYiT/LgYgL1Vc6/e0XHaVjA85kPvUDKb785oFg==
85
- # -----END RSA PRIVATE KEY-----"
86
-
87
- alice_pub
88
- #=> "-----BEGIN PUBLIC KEY-----
89
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzLpmAQ+MbUTHU1XxzEaQ
90
- # XqiOvk0Vu/skztaMWz+UoGYWU6eWcr7zVt/Y0SYqzD8LkYireX22FxNNFfhgu3/u
91
- # C5yTl+dri6PD6NDAmrG+1cyE8kZZMGq91wQEemZPuesjTgKEvwZbknjodIKOAP35
92
- # QycMr4PuWICSrCjhJLrClI7jInTZLOLtD5w5U7/xLOJAIfuhjUA4wrFCLJGPe721
93
- # 4KWgDCLmsan4/GVUloUKa6KAHJiHq4tNxNdSrbOlluZbKQl8REhXOCIb5bEX2Knb
94
- # QT0nPgKkuOlXgZ7jeyOIk0FG1RGaFvcGu8LieMgT39WltcHJLblNkDr9YDRGiNiT
95
- # hQIDAQAB
96
- # -----END PUBLIC KEY-----"
97
-
98
- bob_key, bob_pub = RSA.generate_keys
99
-
100
- bob_key
101
- #=> "-----BEGIN RSA PRIVATE KEY-----
102
- # MIIEpAIBAAKCAQEAzADannvKlfVkZmKA4EDIxTW0HiJzjD6Auh8wLi02+iz2BScz
103
- # fECA65Zv+KHfc1B9AWMqGeBIwFE49NrsnXiZwZR3DqcFS8WbnVqpntvhwzlEARna
104
- # RWmZ2XjloD7fxILbXtWfMFNjwSfaK0bpArLkrt9d8eni+JI42+ptIWs/bVynACqm
105
- # DqOTjoEgajuHVpxHtskPNQrsjxzP+umsUWkbE0iaO7oN1pcgZIR4VRr0bz/3Juif
106
- # WmiCgwbDZo1WolfveoCacVsfAB1iesxeWnrGIJUjq8Mqsu9mQz1dg6RF4ElwNJ57
107
- # G3T3nlW+qpVBZDU2sHFqUFxbGmWPdRUn1yn4KwIDAQABAoIBAQCOCwotz4P/Zh3C
108
- # LFQP0Qv6RKplURejTuHStmSVwmXFTAkBDYqLuV4Kq3TLaepsIF7p2GI4IjKFtggy
109
- # dTzLaG2mm/lJ+oF1gOIZbkcslW1cwULYgWe5bQ3ynntEWIL2ESctoRB2VZnfpCAE
110
- # ghs8BdO071I6Xt/qs+VjOpdB7ar8OYhFc1vhwiI03FKbjuScH0CQOETIeLCqK5tC
111
- # qPnjMTYdaTp/NgcZujsOeOBgbARLzGtCaESbmXHO6mPDkEED5uqZzsNBtdCZIGMF
112
- # ApJkZbF6xSRizQhwwRlak1jCkAk2VCYpKPMiop1+cbjs3jU3RyP94RHc/yKo2Rzm
113
- # HCl35XYBAoGBAPJDMV9W2scRsMlLw9In3ZzWtammcouE0oXEgizK61Cg/5C5E06a
114
- # 5anrfwF5bURBANKBqTSHV0u71C2fHs1KO+B+EHzQ4DKsXldCSv2PR/0A6lmF9AIL
115
- # DFfup/mU55plbqCnjJe2BOUrOmurSd5MbWtShRdGri/LBqF58BFgT+U1AoGBANeS
116
- # RZDsCWelZPGN8Wxp9zxhu1AClNO9S7ITjZOQTYlghCVKAkS1wvB/6TIjaw8DyREs
117
- # f6WvtkzQA/vZc4mXE+YM/calL8ee3wVEJJzlGBfuh8mQhxtiLa5PTl7Icv/R8DGV
118
- # 9hU9GkJgWdi/+Plpqdcv79OWVMTB7igmoN8PAPPfAoGAKqatwI04AygYKbhPB2bB
119
- # W2Vpoi6NqAaAUdCg4mXvO8i8daw/u+0FVf8B4y6PkB6pmGX/diIFum2dE1MaRyY0
120
- # mHdZS8AyWHmEOnSPY0igceiBWbV9mgZ769c2d3hBtir5aQtWczc2cWpE5MPJQ3vN
121
- # H8HtcIWfEQb7ad5f548/QakCgYEAwFDjNRYOkePQ+Vrbjg+/HKRH+mpDId9Xv4eI
122
- # H6R2N9/eJHIxMeFCB1Ll1PAaG6wR3ftn6YWnykEtvKpTU+VvQCZI5MYLqTgH2Ofh
123
- # DgOoCfmoNF922SwuerqPvSlwxt8hPOt/PZVkbuEMZr1lPgVRGwPOHmKYP2yPrkw/
124
- # 6p+1BtsCgYABmMLgWhXVD19XxNHm8XpGnPWTEjqAYrw6I5yDUwNhB0n4129qaC+x
125
- # MWrdslKBmQh1r1U5QoSSL0CY4Ef5qN02uZl15FN1kYQzZA6kJi+MoBsjzrZCvzsc
126
- # Bbahpg363PyHC75zgvazvOr4tK3mzaRi5RNTMgivTVu4FyhkRdJ5wQ==
127
- # -----END RSA PRIVATE KEY-----"
128
-
129
- bob_pub
130
- #=> "-----BEGIN PUBLIC KEY-----
131
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzADannvKlfVkZmKA4EDI
132
- # xTW0HiJzjD6Auh8wLi02+iz2BSczfECA65Zv+KHfc1B9AWMqGeBIwFE49NrsnXiZ
133
- # wZR3DqcFS8WbnVqpntvhwzlEARnaRWmZ2XjloD7fxILbXtWfMFNjwSfaK0bpArLk
134
- # rt9d8eni+JI42+ptIWs/bVynACqmDqOTjoEgajuHVpxHtskPNQrsjxzP+umsUWkb
135
- # E0iaO7oN1pcgZIR4VRr0bz/3JuifWmiCgwbDZo1WolfveoCacVsfAB1iesxeWnrG
136
- # IJUjq8Mqsu9mQz1dg6RF4ElwNJ57G3T3nlW+qpVBZDU2sHFqUFxbGmWPdRUn1yn4
137
- # KwIDAQAB
138
- # -----END PUBLIC KEY-----"
139
-
140
-
141
- tx = "from: alice, to: bob, $21"
142
- tx_hash = sha256( tx )
143
- #=> "426a472a6c69bf68354391b7822393bea3952cde9df8949ad7a0f5f405b2fcb5"
144
-
145
- tx_signature = RSA.sign( tx_hash, alice_key )
146
- #=> "xfhzC6tzXYmA5rFAFybJ9KeWnTcTnC0Plt7cSHky6ZSdBZRKz/sfFcpyIN7w
147
- # jWrdPwEREA3nwNu/HSpiGRBFr+lu/YgWGNp6HLGPeL7uHGAfmWPyU5WRzGzf
148
- # iEs5B6kdJ3S8LSbP0hkOD8AOgZLPeU5rzA4+/Ymt8e/UOVwwka6Gj13yoBua
149
- # mSdsVuQfgh2VpySejCz4ykYlMSHK8Kx8QFt+QbyI5QZUy2dFh6HlcnHR+G9A
150
- # RMRZ1vAuQhYqtDSsxwRcZCSFsc6uctAvsgFinhqy6ls5VpcXfuKwZhKAw3Di
151
- # E2MYUnT7+i38Mq26iWzgmDbpOrVCO5tjlSiHY1731A=="
152
-
153
- RSA.valid_signature?( tx_hash, tx_signature, alice_pub )
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 )
154
359
  #=> true
155
360
 
156
- tx = "from: alice, to: bob, $22"
157
- tx_hash = sha256( tx )
158
- #=> "e899604bb4c95d2f1a7cfe561ad65941769e2064bdbbcaa79eb64ce0a2832380"
159
361
 
160
- RSA.valid_signature?( tx_hash, tx_signature, alice_pub )
161
- #=> false
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
162
378
  ```
163
379
 
164
380
 
165
- and some more.
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)
166
490
 
167
491
 
168
492