crypto-lite 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb39c213dfc1d3d5f0625fceed1aa57ba57094838d6b4fa792388aa914764ec5
4
- data.tar.gz: 9222110e4d2a56e99704ae234213438251cc6259d446ea974bb3dcc6f7195669
3
+ metadata.gz: 7326c07c1553f4f15d79ddbfa19df2ad5dd04bb18e769ccbf564ee521aa97405
4
+ data.tar.gz: 9602382da425f288147cc4a1a9e5f0fc373dc9f8838204886c990a9e4b611be6
5
5
  SHA512:
6
- metadata.gz: f644ce38c52fb2b6bb670616619548752a261147515461558dda726309fed4bba5f1e6f1bdb21eaa9923c8cecfd4bd92dd8d30717487f1dc994d48183848867d
7
- data.tar.gz: 594fb0787715b39c9995384f650ed261c4455dd0827d08d65286410d8b9b5f77ce27afae8297f78e558ea0006f592fca6dd52dac55f453528f7b62d90fd43b3e
6
+ metadata.gz: 8b607671748a9035dce0b505ec757397416f2a70193e8d5890a90815bba03bbeff874ec878462b950427a372657889344f16b04c8349286165a70a61fd48fa86
7
+ data.tar.gz: bc6ad174e2d5fe8c0b75853bd66e7b69ee963024c33f797b9043a836cbe25fee7b5ada35c2c5c144fc5dad93b80859de4e9b3fb09fe34b5390c0a58b654c7363
@@ -4,12 +4,15 @@ README.md
4
4
  Rakefile
5
5
  lib/crypto-lite.rb
6
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
7
10
  lib/crypto-lite/version.rb
8
11
  lib/crypto.rb
9
12
  lib/crypto/lite.rb
10
13
  test/helper.rb
11
14
  test/test_base58.rb
12
15
  test/test_bitcoin_addr.rb
13
- test/test_hash_keccak.rb
16
+ test/test_hash.rb
14
17
  test/test_hash_sha.rb
15
18
  test/test_version.rb
data/README.md CHANGED
@@ -24,23 +24,33 @@ sha256( "abc".b ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb
24
24
  sha256( "\x61\x62\x63" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
25
25
  sha256( 0x616263 ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
26
26
 
27
- sha256hex( '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
28
- sha256hex( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
29
- sha256hex( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
27
+ sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
28
+ sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
29
+ sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
30
30
 
31
31
  # "auto-magic" hex string to binary string conversion heuristic
32
32
  sha256( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
33
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.
34
40
 
35
41
 
42
+
43
+ Onwards with more sha256 examples:
44
+
45
+ ``` ruby
36
46
  ## try a
37
47
  sha256( "a" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
38
48
  sha256( "\x61" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
39
49
  sha256( 0b01100001 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
40
50
  sha256( 0x61 ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
41
51
 
42
- sha256hex( '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
43
- sha256hex( '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
52
+ sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
53
+ sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
44
54
 
45
55
  # "auto-magic" hex string to binary string conversion heuristic
46
56
  sha256( '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
@@ -51,6 +61,67 @@ sha256( "Hello, Cryptos!" ) #=> "33eedea60b0662c66c289ceba71863a864cf84b00e1000
51
61
  ```
52
62
 
53
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
+
54
125
 
55
126
  #### Aside - Hex String `"0x616263"` vs Binary String `"\x61\x62\x63" == "abc"`
56
127
 
@@ -84,15 +155,18 @@ Note: The standard `Array#pack` conversion
84
155
  will NOT "auto-magically" cut-off the `0x` or `0X` prefix.
85
156
 
86
157
 
87
- If you know you have a hex string use the hex-variant of the hash function that will handle the hex-to-bin conversion for you. Example:
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:
88
162
 
89
163
  ``` ruby
90
- sha256hex( '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
91
- sha256hex( '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
164
+ sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
165
+ sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
92
166
 
93
- sha256hex( '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
94
- sha256hex( '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
95
- sha256hex( '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
167
+ sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
168
+ sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
169
+ sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
96
170
  ```
97
171
 
98
172
  What about the built-in "auto-magic" hex-to-bin conversion / heuristic?
@@ -121,59 +195,6 @@ hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
121
195
  ```
122
196
 
123
197
 
124
-
125
- **Keccak 256-Bit**
126
-
127
- ``` ruby
128
- keccak256( "Hello, Cryptos!" ) #=> "2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5"
129
- keccak256( '' ) #=> "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
130
- ```
131
-
132
-
133
- #### Aside - Keccak vs SHA3 / Original vs Official
134
-
135
- In 2004 the U.S. National Institute of Standards and Technology (NIST)
136
- changed the padding to `SHA3-256(M) = KECCAK [512] (M || 01, 256)`.
137
- This is different from the padding proposed by the Keccak team in
138
- the original Keccak SHA-3 submission version 3 (the final, winning version).
139
- The difference is the additional `'01'` bits appended to the message.
140
-
141
- To help avoid confusion the "submitted original version 3" SHA-3 Keccak
142
- hashing is now called "Keccak"
143
- and the finalized NIST SHA-3 standard "SHA3".
144
-
145
- Tip: If you don't know what variant of the hash function you have -
146
- original or official? - check your hash:
147
-
148
- For keccak 256-bit:
149
-
150
- ``` ruby
151
- keccak256( '' ) #=> "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
152
- keccak256( 'Hello, Cryptos!' ) #=> "2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5"
153
- ```
154
-
155
- For sha3 256-bit:
156
-
157
- ``` ruby
158
- sha3_256( '' ) #=> "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
159
- sha3_256( 'Hello, Cryptos!' ) #=> "7dddf4bc9b86352b67e8823e5010ddbd2a90a854469e2517992ca7ca89e5bd58"
160
- ```
161
-
162
-
163
-
164
- **RMD - RACE¹ Integrity Primitives Evaluation Message Digest 160-Bit**
165
-
166
- ¹: Research and development in Advanced Communications technologies in Europe
167
-
168
-
169
- ``` ruby
170
- rmd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
171
- # or use the alias / alternate name
172
- ripemd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53"
173
- ```
174
-
175
-
176
-
177
198
  #### Hash Function Helpers
178
199
 
179
200
  **HASH160 - RMD160(SHA256(X))**
@@ -204,7 +225,7 @@ hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' )
204
225
  #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711"
205
226
  ```
206
227
 
207
- ##### Base58 Encoding / Decoding Helpers
228
+ #### Base58 Encoding / Decoding Helpers
208
229
 
209
230
  **BASE58**
210
231
 
@@ -443,6 +464,20 @@ References
443
464
  - [How to create Bitcoin Address](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses#How_to_create_Bitcoin_Address)
444
465
  - [Ruby Quiz #15 - Generate the Bitcoin (Base58) Address from the (Elliptic Curve) Public Key](https://github.com/planetruby/quiz/tree/master/015)
445
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
+
446
481
 
447
482
 
448
483
 
@@ -17,199 +17,89 @@ require 'base58-alphabets'
17
17
  ## our own code
18
18
  require 'crypto-lite/version' # note: let version always go first
19
19
  require 'crypto-lite/config'
20
+ require 'crypto-lite/metal'
20
21
 
21
22
 
22
23
 
23
24
 
24
25
  module Crypto
25
26
 
26
- ## check if it is a hex (string)
27
- ## - allow optiona 0x or 0X and allow abcdef and ABCDEF
28
- HEX_RE = /\A(?:0x)?[0-9a-f]+\z/i
29
-
30
-
31
-
32
- def self.base58bin( input )
33
- ## todo/check: input must be a (binary) string - why? why not?
34
- Base58::Bitcoin.encode_bin( input )
27
+ def self.base58( *args, **kwargs )
28
+ input = args_to_input( args, kwargs )
29
+ Metal.base58bin( input )
35
30
  end
36
31
 
37
- def self.base58( input )
38
- input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
39
- base58bin( input )
40
- end
41
-
42
- def self.base58hex( input )
43
- raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry" unless input =~ HEX_RE
44
-
45
- input = strip0x( input ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
46
- base58bin( [input].pack( 'H*' ) )
47
- end
48
-
49
-
50
- def self.base58bin_check( input )
51
- ## todo/check: input must be a (binary) string - why? why not?
52
- hash256 = hash256bin( input )
53
- base58bin( input + hash256[0,4] )
54
- end
55
-
56
- def self.base58check( input )
57
- input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
58
- base58bin_check( input )
59
- end
60
-
61
- def self.base58hex_check( input )
62
- raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry" unless input =~ HEX_RE
63
-
64
- input = strip0x( input ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
65
- base58bin_check( [input].pack( 'H*' ) )
32
+ def self.base58check( *args, **kwargs )
33
+ input = args_to_input( args, kwargs )
34
+ Metal.base58bin_check( input )
66
35
  end
67
36
 
68
37
 
69
38
  ########################
70
39
  # (secure) hash functions
71
40
 
72
- def self.message( input ) ## convert input to (binary) string
73
- if debug?
74
- input_type = if input.is_a?( String )
75
- "#{input.class.name}/#{input.encoding}"
76
- else
77
- input.class.name
78
- end
79
- puts " input: #{input} (#{input_type})"
80
- end
81
-
82
- message = if input.is_a?( Integer ) ## assume byte if single (unsigned) integer
83
- raise ArgumentError, "expected unsigned byte (0-255) - got #{input} (0x#{input.to_s(16)}) - can't pack negative number; sorry" if input < 0
84
- ## note: pack - H (String) => hex string (high nibble first)
85
- ## todo/check: is there a better way to convert integer number to (binary) string!!!
86
- [input.to_s(16)].pack('H*')
87
- else ## assume (binary) string
88
- input
89
- end
90
-
91
- if debug?
92
- bytes = message.bytes
93
- bin = bytes.map {|byte| byte.to_s(2).rjust(8, "0")}.join( ' ' )
94
- hex = bytes.map {|byte| byte.to_s(16).rjust(2, "0")}.join( ' ' )
95
- puts " #{pluralize( bytes.size, 'byte')}: #{bytes.inspect}"
96
- puts " binary: #{bin}"
97
- puts " hex: #{hex}"
98
- end
99
-
100
- message
41
+ def self.keccak256( *args, **kwargs )
42
+ input = args_to_input( args, kwargs )
43
+ Metal.keccak256bin( input ).unpack( 'H*' )[0]
101
44
  end
102
45
 
103
46
 
104
-
105
- def self.keccak256bin( input )
106
- message = message( input ) ## "normalize" / convert to (binary) string
107
- Digest::SHA3.digest( message, 256 )
108
- end
109
-
110
- def self.keccak256( input )
111
- input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
112
- keccak256bin( input ).unpack( 'H*' )[0]
113
- end
114
-
115
-
116
-
117
- def self.rmd160bin( input )
118
- message = message( input ) ## "normalize" / convert to (binary) string
119
- Digest::RMD160.digest( message )
120
- end
121
-
122
- def self.rmd160( input )
123
- input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
124
- rmd160bin( input ).unpack( 'H*' )[0]
47
+ def self.rmd160( *args, **kwargs )
48
+ input = args_to_input( args, kwargs )
49
+ Metal.rmd160bin( input ).unpack( 'H*' )[0]
125
50
  end
126
51
 
127
52
  ## add alias RIPEMD160 - why? why not?
128
53
  class << self
129
54
  alias_method :ripemd160, :rmd160
130
- alias_method :ripemd160bin, :rmd160bin
131
55
  end
132
56
 
133
57
 
134
-
135
- def self.sha256bin( input, engine=nil ) ## todo/check: add alias sha256b or such to - why? why not?
136
- message = message( input ) ## "normalize" / convert to (binary) string
137
-
138
- if engine && ['openssl'].include?( engine.to_s.downcase )
139
- puts " engine: #{engine}" if debug?
140
- digest = OpenSSL::Digest::SHA256.new
141
- digest.update( message )
142
- digest.digest
143
- else ## use "built-in" hash function from digest module
144
- Digest::SHA256.digest( message )
145
- end
146
- end
147
-
148
- def self.sha256( input, engine=nil )
149
- input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
150
- sha256bin( input, engine ).unpack( 'H*' )[0]
58
+ def self.sha256( *args, **kwargs )
59
+ input = args_to_input( args, kwargs )
60
+ engine = kwargs[:engine]
61
+ Metal.sha256bin( input, engine ).unpack( 'H*' )[0]
151
62
  end
152
63
 
153
-
154
- def self.sha256hex( input, engine=nil ) ## convenience helper - lets you pass in hex string
155
- raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry" unless input =~ HEX_RE
156
-
157
- input = strip0x( input ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
158
- sha256bin( [input].pack( 'H*' ), engine ).unpack( 'H*' )[0]
64
+ def self.sha3_256( *args, **kwargs )
65
+ input = args_to_input( args, kwargs )
66
+ Metal.sha3_256bin( input ).unpack( 'H*' )[0]
159
67
  end
160
68
 
161
69
 
162
70
 
163
- ####
164
- ## helper
165
- # def hash160( pubkey )
166
- # binary = [pubkey].pack( "H*" ) # Convert to binary first before hashing
167
- # sha256 = Digest::SHA256.digest( binary )
168
- # ripemd160 = Digest::RMD160.digest( sha256 )
169
- # ripemd160.unpack( "H*" )[0] # Convert back to hex
170
- # end
171
-
172
- def self.hash160bin( input )
173
- message = message( input ) ## "normalize" / convert to (binary) string
174
-
175
- rmd160bin(sha256bin( message ))
71
+ def self.hash160( *args, **kwargs )
72
+ input = args_to_input( args, kwargs )
73
+ Metal.hash160bin( input ).unpack( 'H*' )[0]
176
74
  end
177
75
 
178
- def self.hash160( input )
179
- input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
180
- hash160bin( input ).unpack( 'H*' )[0]
181
- end
182
-
183
- def self.hash160hex( input ) ## convenience helper - lets you pass in hex string
184
- raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry" unless input =~ HEX_RE
185
-
186
- input = strip0x( input ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
187
- hash160bin( [input].pack( 'H*' ) ).unpack( 'H*' )[0]
76
+ def self.hash256( *args, **kwargs )
77
+ input = args_to_input( args, kwargs )
78
+ Metal.hash256bin( input ).unpack( 'H*' )[0]
188
79
  end
189
80
 
190
81
 
191
82
 
192
- def self.hash256bin( input )
193
- message = message( input ) ## "normalize" / convert to (binary) string
194
-
195
- sha256bin(sha256bin( message ))
196
- end
197
-
198
- def self.hash256( input )
199
- input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
200
- hash256bin( input ).unpack( 'H*' )[0]
201
- end
202
-
203
- def self.hash256hex( input ) ## convenience helper - lets you pass in hex string
204
- raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry" unless input =~ HEX_RE
83
+ ########
84
+ # more helpers
85
+ ## check if it is a hex (string)
86
+ ## - allow optiona 0x or 0X and allow abcdef and ABCDEF
87
+ HEX_RE = /\A(?:0x)?[0-9a-f]+\z/i
205
88
 
206
- input = strip0x( input ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
207
- hash256bin( [input].pack( 'H*' ) ).unpack( "H*" )[0]
89
+ def self.args_to_input( args, kwargs )
90
+ if kwargs[:hex]
91
+ hex = kwargs[:hex]
92
+ raise ArgumentError, "expected hex string (0-9a-f) - got >#{hex}< - can't pack string; sorry" unless hex =~ HEX_RE
93
+
94
+ hex = strip0x( hex ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
95
+ [hex].pack( 'H*' )
96
+ else ## assume single input arg for now
97
+ input = args[0]
98
+ input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not?
99
+ input
100
+ end
208
101
  end
209
102
 
210
-
211
- ########
212
- # more helpers
213
103
  def self.hex_to_bin_automagic( input )
214
104
  ## todo/check/fix: add configure setting to turn off automagic - why? why not?
215
105
  if input.is_a?( String ) && input =~ HEX_RE
@@ -234,78 +124,24 @@ module Crypto
234
124
  (str[0,2] == '0x' || str[0,2] == '0X') ? str[2..-1] : str
235
125
  end
236
126
 
237
- def self.hex_to_bin( str )
238
- str = strip0x( str ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
239
- [str].pack( 'H*' )
240
- end
241
-
242
- def self.pluralize( count, noun )
243
- count == 1 ? "#{count} #{noun}" : "#{count} #{noun}s"
244
- end
245
-
246
-
247
-
248
-
249
- module RSA
250
- def self.generate_keys ## todo/check: add a generate alias - why? why not?
251
- key_pair = OpenSSL::PKey::RSA.new( 2048 )
252
- private_key = key_pair.export
253
- public_key = key_pair.public_key.export
127
+ # def self.hex_to_bin( str )
128
+ # str = strip0x( str ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!
129
+ # [str].pack( 'H*' )
130
+ # end
254
131
 
255
- [private_key, public_key]
256
- end
257
-
258
-
259
- def self.sign( plaintext, private_key )
260
- private_key = OpenSSL::PKey::RSA.new( private_key ) ## note: convert/wrap into to obj from exported text format
261
- Base64.encode64( private_key.private_encrypt( plaintext ))
262
- end
263
-
264
- def self.decrypt( ciphertext, public_key )
265
- public_key = OpenSSL::PKey::RSA.new( public_key ) ## note: convert/wrap into to obj from exported text format
266
- public_key.public_decrypt( Base64.decode64( ciphertext ))
267
- end
268
-
269
-
270
- def self.valid_signature?( plaintext, ciphertext, public_key )
271
- plaintext == decrypt( ciphertext, public_key )
272
- end
273
- end # module RSA
274
132
  end # module Crypto
275
133
 
276
134
 
277
135
 
278
136
 
279
- ## add convenience "top-level" helpers
280
- def sha256( input, engine=nil ) Crypto.sha256( input, engine ); end
281
- def sha256hex( input, engine=nil ) Crypto.sha256hex( input, engine ); end
282
-
283
- def keccak256( input ) Crypto.keccak256( input ); end
284
-
285
- def rmd160( input ) Crypto.rmd160( input ); end
286
- def ripemd160( input ) Crypto.rmd160( input ); end
287
- ## alias_method :ripemd160, :rmd160
288
-
289
- def hash160( input ) Crypto.hash160( input ); end
290
- def hash160hex( input ) Crypto.hash160hex( input ); end
291
-
292
- def hash256( input ) Crypto.hash256( input ); end
293
- def hash256hex( input ) Crypto.hash256hex( input ); end
294
-
295
-
296
- def base58( input ) Crypto.base58( input ); end
297
- def base58hex( input ) Crypto.base58hex( input ); end
298
-
299
-
300
- def base58check( input ) Crypto.base58check( input ); end
301
-
137
+ require 'crypto-lite/helper'
138
+ include CryptoHelper # add convenience "top-level" / global helpers
302
139
 
303
140
 
141
+ require 'crypto-lite/sign_rsa'
304
142
  RSA = Crypto::RSA
305
143
 
306
144
 
307
145
 
308
146
 
309
-
310
-
311
147
  puts CryptoLite.banner ## say hello
@@ -0,0 +1,25 @@
1
+
2
+ module CryptoHelper
3
+ ### note: use include CryptoHelper
4
+ ## to get "top-level" / global helpers
5
+
6
+ ## add convenience "top-level" helpers
7
+ def sha256( *args, **kwargs ) Crypto.sha256( *args, **kwargs ); end
8
+ def sha3_256( *args, **kwargs ) Crypto.sha3_256( *args, **kwargs ); end
9
+
10
+ def keccak256( *args, **kwargs ) Crypto.keccak256( *args, **kwargs ); end
11
+
12
+ def rmd160( *args, **kwargs ) Crypto.rmd160( *args, **kwargs ); end
13
+ ## def ripemd160( input ) Crypto.rmd160( input ); end
14
+ alias_method :ripemd160, :rmd160
15
+
16
+ def hash160( *args, **kwargs ) Crypto.hash160( *args, **kwargs ); end
17
+
18
+ def hash256( *args, **kwargs ) Crypto.hash256( *args, **kwargs ); end
19
+
20
+
21
+ def base58( *args, **kwargs ) Crypto.base58( *args, **kwargs ); end
22
+ def base58check( *args, **kwargs ) Crypto.base58check( *args, **kwargs ); end
23
+ end
24
+
25
+
@@ -0,0 +1,128 @@
1
+ module Crypto
2
+ module Metal
3
+
4
+ def self.debug?() Crypto.debug?; end
5
+
6
+ ########################
7
+ ### to the "metal" crypto primitives
8
+ ## work with binary strings (aka byte arrays) / data
9
+
10
+ ##
11
+ ## todo/check: use/keep bin-suffix in name - why? why not?
12
+
13
+
14
+ def self.base58bin( input )
15
+ ## todo/check: input must be a (binary) string - why? why not?
16
+ Base58::Bitcoin.encode_bin( input )
17
+ end
18
+
19
+ def self.base58bin_check( input )
20
+ ## todo/check: input must be a (binary) string - why? why not?
21
+ hash256 = hash256bin( input )
22
+ base58bin( input + hash256[0,4] )
23
+ end
24
+
25
+
26
+ ########################
27
+ # (secure) hash functions
28
+
29
+ def self.keccak256bin( input )
30
+ message = message( input ) ## "normalize" / convert to (binary) string
31
+ Digest::SHA3.digest( message, 256 )
32
+ end
33
+
34
+ def self.rmd160bin( input )
35
+ message = message( input ) ## "normalize" / convert to (binary) string
36
+ Digest::RMD160.digest( message )
37
+ end
38
+
39
+ ## add alias RIPEMD160 - why? why not?
40
+ class << self
41
+ alias_method :ripemd160bin, :rmd160bin
42
+ end
43
+
44
+
45
+ def self.sha256bin( input, engine=nil ) ## todo/check: add alias sha256b or such to - why? why not?
46
+ message = message( input ) ## "normalize" / convert to (binary) string
47
+
48
+ if engine && ['openssl'].include?( engine.to_s.downcase )
49
+ puts " engine: #{engine}" if debug?
50
+ digest = OpenSSL::Digest::SHA256.new
51
+ ## or use OpenSSL::Digest.new( 'SHA256' )
52
+ digest.update( message )
53
+ digest.digest
54
+ else ## use "built-in" hash function from digest module
55
+ Digest::SHA256.digest( message )
56
+ end
57
+ end
58
+
59
+ def self.sha3_256bin( input )
60
+ message = message( input ) ## "normalize" / convert to (binary) string
61
+
62
+ digest = OpenSSL::Digest.new( 'SHA3-256' )
63
+ digest.update( message )
64
+ digest.digest
65
+ end
66
+
67
+ ####
68
+ ## helper
69
+ # def hash160( pubkey )
70
+ # binary = [pubkey].pack( "H*" ) # Convert to binary first before hashing
71
+ # sha256 = Digest::SHA256.digest( binary )
72
+ # ripemd160 = Digest::RMD160.digest( sha256 )
73
+ # ripemd160.unpack( "H*" )[0] # Convert back to hex
74
+ # end
75
+
76
+ def self.hash160bin( input )
77
+ message = message( input ) ## "normalize" / convert to (binary) string
78
+
79
+ rmd160bin(sha256bin( message ))
80
+ end
81
+
82
+
83
+ def self.hash256bin( input )
84
+ message = message( input ) ## "normalize" / convert to (binary) string
85
+
86
+ sha256bin(sha256bin( message ))
87
+ end
88
+
89
+
90
+ ##############################
91
+ ## helpers
92
+ def self.message( input ) ## convert input to (binary) string
93
+ if debug?
94
+ input_type = if input.is_a?( String )
95
+ "#{input.class.name}/#{input.encoding}"
96
+ else
97
+ input.class.name
98
+ end
99
+ puts " input: #{input} (#{input_type})"
100
+ end
101
+
102
+ message = if input.is_a?( Integer ) ## assume byte if single (unsigned) integer
103
+ raise ArgumentError, "expected unsigned byte (0-255) - got #{input} (0x#{input.to_s(16)}) - can't pack negative number; sorry" if input < 0
104
+ ## note: pack - H (String) => hex string (high nibble first)
105
+ ## todo/check: is there a better way to convert integer number to (binary) string!!!
106
+ [input.to_s(16)].pack('H*')
107
+ else ## assume (binary) string
108
+ input
109
+ end
110
+
111
+ if debug?
112
+ bytes = message.bytes
113
+ bin = bytes.map {|byte| byte.to_s(2).rjust(8, "0")}.join( ' ' )
114
+ hex = bytes.map {|byte| byte.to_s(16).rjust(2, "0")}.join( ' ' )
115
+ puts " #{pluralize( bytes.size, 'byte')}: #{bytes.inspect}"
116
+ puts " binary: #{bin}"
117
+ puts " hex: #{hex}"
118
+ end
119
+
120
+ message
121
+ end
122
+
123
+ def self.pluralize( count, noun )
124
+ count == 1 ? "#{count} #{noun}" : "#{count} #{noun}s"
125
+ end
126
+
127
+ end # module Metal
128
+ end # module Crypto
@@ -0,0 +1,29 @@
1
+ module Crypto
2
+
3
+
4
+ module RSA
5
+ def self.generate_keys ## todo/check: add a generate alias - why? why not?
6
+ key_pair = OpenSSL::PKey::RSA.new( 2048 )
7
+ private_key = key_pair.export
8
+ public_key = key_pair.public_key.export
9
+
10
+ [private_key, public_key]
11
+ end
12
+
13
+
14
+ def self.sign( plaintext, private_key )
15
+ private_key = OpenSSL::PKey::RSA.new( private_key ) ## note: convert/wrap into to obj from exported text format
16
+ Base64.encode64( private_key.private_encrypt( plaintext ))
17
+ end
18
+
19
+ def self.decrypt( ciphertext, public_key )
20
+ public_key = OpenSSL::PKey::RSA.new( public_key ) ## note: convert/wrap into to obj from exported text format
21
+ public_key.public_decrypt( Base64.decode64( ciphertext ))
22
+ end
23
+
24
+
25
+ def self.valid_signature?( plaintext, ciphertext, public_key )
26
+ plaintext == decrypt( ciphertext, public_key )
27
+ end
28
+ end # module RSA
29
+ end # module Crypto
@@ -3,7 +3,7 @@ module CryptoLite
3
3
 
4
4
  MAJOR = 0
5
5
  MINOR = 2
6
- PATCH = 2
6
+ PATCH = 3
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
@@ -15,7 +15,7 @@ HEX_TESTS = [
15
15
 
16
16
  def test_hex
17
17
  HEX_TESTS.each do |item|
18
- assert_equal item[1], base58hex( item[0] )
18
+ assert_equal item[1], base58( hex: item[0] )
19
19
  assert_equal item[1], base58( item[0] )
20
20
  end
21
21
  end
@@ -27,9 +27,10 @@ def test_bitcoin_addr
27
27
  pkh = 'f54a5851e9372b87810a8e60cdd2e7cfd80b6e31'
28
28
 
29
29
  ## all-in-one
30
+ assert_equal addr_exp, base58check( hex: '00' + pkh )
30
31
  assert_equal addr_exp, base58check( '00' + pkh )
31
- assert_equal addr_exp, Crypto.base58hex_check( '00' + pkh )
32
- assert_equal addr_exp, Crypto.base58bin_check( "\x00" + [pkh].pack('H*') )
32
+
33
+ assert_equal addr_exp, Crypto::Metal.base58bin_check( "\x00" + [pkh].pack('H*') )
33
34
  end
34
35
 
35
36
  end # class TestBase58
@@ -0,0 +1,47 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_hash.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+
9
+ class TestHash < MiniTest::Test
10
+
11
+ KECCAK256_TESTS = [
12
+ ['', 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'],
13
+ ['testing', '5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02'],
14
+ ['Hello, Cryptos!', '2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5'],
15
+ ]
16
+
17
+ SHA3_256_TESTS = [
18
+ ['', 'a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a'],
19
+ ['Hello, Cryptos!', '7dddf4bc9b86352b67e8823e5010ddbd2a90a854469e2517992ca7ca89e5bd58'],
20
+ ]
21
+
22
+ RIPEMD160_TESTS = [
23
+ ['Hello, Cryptos!', '4d65f7b740bbade4097e1348e15d2a7d52ac5f53'],
24
+ ]
25
+
26
+
27
+
28
+ def test_keccak256
29
+ KECCAK256_TESTS.each do |item|
30
+ assert_equal item[1], keccak256( item[0].b )
31
+ end
32
+ end
33
+
34
+ def test_sha3_256
35
+ SHA3_256_TESTS.each do |item|
36
+ assert_equal item[1], sha3_256( item[0].b )
37
+ end
38
+ end
39
+
40
+ def test_ripemd160
41
+ RIPEMD160_TESTS.each do |item|
42
+ assert_equal item[1], ripemd160( item[0].b )
43
+ end
44
+ end
45
+
46
+
47
+ end # class TestHash
@@ -6,21 +6,35 @@
6
6
  require 'helper'
7
7
 
8
8
 
9
- class TestHash < MiniTest::Test
9
+ class TestHashSha < MiniTest::Test
10
10
 
11
- SHA256_EMPTY = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
12
11
  SHA256_ABC = 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
13
12
  SHA256_A = 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb'
14
13
  SHA256_B = '3e23e8160039594a33894f6564e1b1348bbd7a0088d42c4acb73eeaed59c009d'
15
14
  SHA256_C = '2e7d2c03a9507ae265ecf5b5356885a53393a2029d241394997265a1a25aefc6'
16
- SHA256_HELLO_CRYPTOS = '33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5'
17
15
 
18
16
 
19
- def test_empty
20
- assert_equal SHA256_EMPTY, sha256( '' )
21
- assert_equal SHA256_EMPTY, sha256( '', :openssl )
17
+ BIN_TESTS = [
18
+ ['', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'],
19
+ ['Hello, Cryptos!', '33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5'],
20
+
21
+ ['Blockchain 1', '223aae3830e87aff41db07714983671429a74fb7064646e27ab62adbdc892cd1'],
22
+ ['Blockchain 2', '8f4b5a896e78f680de2c141d25533e8c9207c9ee0d9b09c22a5a01d7992e7d1b'],
23
+ ['Blockchain 3', 'f9f5e7d64f3a93f071900a73d34b2b722867adcb09345a21a25b5cd7f8b41254'],
24
+ ['Blockchain 4', '69580cfb9a134395106ac27de53595cc41fb9940dcc298082c87144932a983a9'],
25
+ ['Blockchain 12', 'f94455d34e7b32dc7dac780fb94a5e958f0d7e2da4cc6500505d5daed719c227'],
26
+ ['Blockchain 13', '0cedb5e229c9582a35ec291ccb172b3f7c76a20c7f645e08d24ece8d5692e153'],
27
+ ]
28
+
29
+
30
+ def test_bin
31
+ BIN_TESTS.each do |item|
32
+ assert_equal item[1], sha256( item[0].b )
33
+ assert_equal item[1], sha256( item[0].b, engine: 'openssl' )
34
+ end
22
35
  end
23
36
 
37
+
24
38
  def test_abc
25
39
  ['abc',
26
40
  'abc'.b,
@@ -28,14 +42,14 @@ def test_abc
28
42
  0x616263
29
43
  ].each do |input|
30
44
  assert_equal SHA256_ABC, sha256( input )
31
- assert_equal SHA256_ABC, sha256( input, :openssl )
45
+ assert_equal SHA256_ABC, sha256( input, engine: 'openssl' )
32
46
  end
33
47
 
34
48
  ['616263',
35
49
  '0x616263',
36
50
  '0X616263'
37
51
  ].each do |input|
38
- assert_equal SHA256_ABC, sha256hex( input )
52
+ assert_equal SHA256_ABC, sha256( hex: input )
39
53
  end
40
54
  ## pp sha256hex( 'hello' ) -- fails - uses non-hex chars
41
55
 
@@ -47,14 +61,14 @@ def test_abc
47
61
  0x61
48
62
  ].each do |input|
49
63
  assert_equal SHA256_A, sha256( input )
50
- assert_equal SHA256_A, sha256( input, :openssl )
64
+ assert_equal SHA256_A, sha256( input, engine: 'openssl' )
51
65
  end
52
66
 
53
67
  ['61',
54
68
  '0x61',
55
69
  '0X61'
56
70
  ].each do |input|
57
- assert_equal SHA256_A, sha256hex( input )
71
+ assert_equal SHA256_A, sha256( hex: input )
58
72
  end
59
73
 
60
74
  [ 'b',
@@ -70,9 +84,4 @@ def test_abc
70
84
  end
71
85
  end
72
86
 
73
-
74
- def test_misc
75
- assert_equal SHA256_HELLO_CRYPTOS, sha256( 'Hello, Cryptos!' )
76
- end
77
-
78
- end # class TestHash
87
+ end # class TestHashSha
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crypto-lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-18 00:00:00.000000000 Z
11
+ date: 2021-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: digest-sha3-patched
@@ -102,13 +102,16 @@ files:
102
102
  - Rakefile
103
103
  - lib/crypto-lite.rb
104
104
  - lib/crypto-lite/config.rb
105
+ - lib/crypto-lite/helper.rb
106
+ - lib/crypto-lite/metal.rb
107
+ - lib/crypto-lite/sign_rsa.rb
105
108
  - lib/crypto-lite/version.rb
106
109
  - lib/crypto.rb
107
110
  - lib/crypto/lite.rb
108
111
  - test/helper.rb
109
112
  - test/test_base58.rb
110
113
  - test/test_bitcoin_addr.rb
111
- - test/test_hash_keccak.rb
114
+ - test/test_hash.rb
112
115
  - test/test_hash_sha.rb
113
116
  - test/test_version.rb
114
117
  homepage: https://github.com/rubycoco/blockchain
@@ -1,25 +0,0 @@
1
- ###
2
- # to run use
3
- # ruby -I ./lib -I ./test test/test_hash_keccak.rb
4
-
5
-
6
- require 'helper'
7
-
8
-
9
- class TestHashKeccak < MiniTest::Test
10
-
11
- KECCAK256_EMPTY = 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
12
- KECCAK256_TESTING = '5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02'
13
- KECCAK256_HELLO_CRYPTOS = '2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5'
14
-
15
-
16
- def test_empty
17
- assert_equal KECCAK256_EMPTY, keccak256( '' )
18
- end
19
-
20
- def test_misc
21
- assert_equal KECCAK256_TESTING, keccak256( 'testing' )
22
- assert_equal KECCAK256_HELLO_CRYPTOS, keccak256( 'Hello, Cryptos!' )
23
- end
24
-
25
- end # class TestHashKeccak