crypto-lite 0.2.2 → 0.2.3

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: 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