diff --git a/crypto-lite/README.md b/crypto-lite/README.md index 549dd24..d57e578 100644 --- a/crypto-lite/README.md +++ b/crypto-lite/README.md @@ -15,23 +15,36 @@ **SHA256 - Secure Hash Algorithm (SHA) 256-Bit (32 Bytes)** +Note: By default all hash functions return binary strings. +Use `String#hexdigest` (or `String#bin_to_hex` +or `String#btoh`) +to convert binary strings to hex(adecimal) +strings (via `Bytes.bin_to_hex`). + + + + ``` ruby require 'crypto' ## or use require 'crypto-lite' ## try abc -sha256( "abc" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -sha256( "abc".b ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -sha256( "\x61\x62\x63" ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -sha256( 0x616263 ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( "abc" ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( "abc".b ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( "\x61\x62\x63" ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" + +sha256( hex: '616263' ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( hex: '0x616263' ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( hex: '0X616263' ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +``` -sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" + Bonus Back Stage Tip: How does SHA256 work? @@ -45,27 +58,32 @@ Onwards with more sha256 examples: ``` ruby ## try a -sha256( "a" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" -sha256( "\x61" ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" +sha256( "a" ).hexdigest #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" +sha256( "\x61" ).hexdigest #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" + +sha256( hex: '61' ).hexdigest #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" +sha256( hex: '0x61' ).hexdigest #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" + + +## try some more +sha256( "Hello, Cryptos!" ).hexdigest #=> "33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5" +``` + + -## try some more -sha256( "Hello, Cryptos!" ) #=> "33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5" -``` **SHA3-256 - Secure Hashing Algorthim (SHA) 3, 256-Bit (32 Bytes)** ``` ruby -sha3_256( "Hello, Cryptos!" ) #=> "7dddf4bc9b86352b67e8823e5010ddbd2a90a854469e2517992ca7ca89e5bd58" +sha3_256( "Hello, Cryptos!" ).hexdigest #=> "7dddf4bc9b86352b67e8823e5010ddbd2a90a854469e2517992ca7ca89e5bd58" ``` Note: Yes, SHA256 vs SHA3-256 / SHA-2 vs SHA-3 the hashing functions are @@ -79,7 +97,7 @@ The sha3_256 is part of the (newer) Secure Hash Algorithm (SHA) 3 family / stand **Keccak 256-Bit** ``` ruby -keccak256( "Hello, Cryptos!" ) #=> "2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5" +keccak256( "Hello, Cryptos!" ).hexdigest #=> "2cf14baa817e931f5cc2dcb63c889619d6b7ae0794fc2223ebadf8e672c776f5" ``` @@ -101,13 +119,13 @@ original or official? - check your hash: For keccak 256-bit: ``` ruby -keccak256( '' ) #=> "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" +keccak256( '' ).hexdigest #=> "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" ``` For sha3 256-bit: ``` ruby -sha3_256( '' ) #=> "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" +sha3_256( '' ).hexdigest #=> "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" ``` @@ -118,9 +136,9 @@ sha3_256( '' ) #=> "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80 ``` ruby -rmd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53" +rmd160( "Hello, Cryptos!" ).hexdigest #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53" # or use the alias / alternate name -ripemd160( "Hello, Cryptos!" ) #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53" +ripemd160( "Hello, Cryptos!" ).hexdigest #=>"4d65f7b740bbade4097e1348e15d2a7d52ac5f53" ``` @@ -162,14 +180,16 @@ to the hash function and that will "automagically" handle the hex-to-bin conversion for you. Example: ``` ruby -sha256( hex: '61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" -sha256( hex: '0x61' ) #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" +sha256( hex: '61' ).hexdigest #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" +sha256( hex: '0x61' ).hexdigest #=> "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" -sha256( hex: '616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -sha256( hex: '0x616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -sha256( hex: '0X616263' ) #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( hex: '616263' ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( hex: '0x616263' ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +sha256( hex: '0X616263' ).hexdigest #=> "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" ``` + + + + #### Hash Function Helpers @@ -204,10 +227,10 @@ All-in-one "best-of-both-worlds" helper - first hash with sha256 and than hash w ``` ruby -hash160( '02b9d1cc0b793b03b9f64d022e9c67d5f32670b03f636abf0b3147b34123d13990' ) +hash160( '02b9d1cc0b793b03b9f64d022e9c67d5f32670b03f636abf0b3147b34123d13990' ).hexdigest #=> "e6b145a3908a4d6616b13c1109717add8672c900" -hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' ) +hash160( '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' ).hexdigest #=> "93ce48570b55c42c2af816aeaba06cfee1224fae" ``` @@ -222,7 +245,7 @@ All-in-one double sha256 hash helper, that is, first hash with sha256 and than h ``` ruby -hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' ) +hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' ).hexdigest #=> "02335f08b8fe4ddad263a50b7a33c5d38ea1cbd8fd2056a1320a3ddece541711" ``` @@ -233,29 +256,34 @@ hash256( '6fe6b145a3908a4d6616b13c1109717add8672c900' ) Base58 encoding / decoding with leading zero bytes (in hex or binary strings) getting encoded from `00` to `1` and back: ``` ruby -base58( "516b6fcd0f" ) #=> "ABnLTmg" -base58( "00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ" +base58( hex: "516b6fcd0f" ) #=> "ABnLTmg" +base58( hex: "00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ" # or with optional 0x or 0X prefix -base58( "0x516b6fcd0f" ) #=> "ABnLTmg" -base58( "0x00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ" +base58( hex: "0x516b6fcd0f" ) #=> "ABnLTmg" +base58( hex: "0x00000000000000000000123456789abcdef0" ) #=> "111111111143c9JGph3DZ" -unbase58( "ABnLTmg" ) #=> "516b6fcd0f" +unbase58( "ABnLTmg" ) #=> "516b6fcd0f" unbase58( "111111111143c9JGph3DZ" ) #=> "00000000000000000000123456789abcdef0" ``` + + **BASE58CHECK - BASE58(X || SHA256(SHA256(X))[:4])** Base58 encoding with an extra 4-byte secure hash checksum. ``` ruby -base58check( "516b6fcd0f" ) #=> "237LSrY9NUUas" -base58check( "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ) #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" +base58check( hex: "516b6fcd0f" ) #=> "237LSrY9NUUas" +base58check( hex: "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ) #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" unbase58check( "237LSrY9NUUas" ) #=> "516b6fcd0f" unbase58check( "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" ) #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ``` + ### Public Key Signature Algorithms @@ -313,7 +341,7 @@ Sign a transaction with an (elliptic curve) private key: ``` ruby # Step 1 - Calculate the Transaction (tx) Hash tx = 'from: Alice to: Bob cryptos: 43_000_000_000' -txhash = sha256( tx ) +txhash = sha256( tx ).hexdigest # Step 2 - Get the Signer's Private key private_key = EC::PrivateKey.new( 1234 ) # This private key is just an example. It should be much more secure! @@ -340,7 +368,7 @@ Verify a signed transaction with an (elliptic curve) public key: ``` ruby # Step 1 - Calculate the Transaction (tx) Hash tx = 'from: Alice to: Bob cryptos: 43_000_000_000' -txhash = sha256( tx ) +txhash = sha256( tx ).hexdigest # Step 2 - Get the Signer's Public Key public_key = EC::PublicKey.new( @@ -582,11 +610,11 @@ Let's follow the steps from [How to create Bitcoin Address](https://en.bitcoin.i pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" # 1. Perform SHA-256 hashing on the public key -step1 = sha256( pk ) +step1 = sha256( hex: pk ).hexdigest #=> "0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98" # 2. Perform RIPEMD-160 hashing on the result of SHA-256 -step2 = ripemd160( step1 ) +step2 = ripemd160( hex: step1 ).hexdigest #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" # 3. Add version byte in front of RIPEMD-160 hash (0x00 for Bitcoin Main Network) @@ -594,11 +622,11 @@ step3 = "00" + step2 #=> "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" # 4. Perform SHA-256 hash on the extended RIPEMD-160 result -step4 = sha256( step3 ) +step4 = sha256( hex: step3 ).hexdigest #=> "ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c" # 5. Perform SHA-256 hash on the result of the previous SHA-256 hash -step5 = sha256( step4 ) +step5 = sha256( hex: step4 ).hexdigest #=> "c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd" # 6. Take the first 4 bytes of the second SHA-256 hash. This is the address checksum @@ -613,7 +641,7 @@ step7 = step3 + step6 # 8. Convert the result from a byte string into a base58 string using Base58 encoding. # This is the most commonly used Bitcoin Address format. -addr = base58( step7 ) +addr = base58( hex: step7 ) #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" ``` @@ -629,7 +657,7 @@ pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" # 1. Perform HASH-160 hashing on the public key # a) Perform SHA-256 hashing on the public key # b) Perform RIPEMD-160 hashing on the result of SHA-256 -step1 = hash160( pk ) +step1 = hash160( hex: pk ).hexdigest #=> "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" # 2. Add version byte in front of RIPEMD-160 hash (0x00 for Bitoin Main Network) @@ -646,7 +674,7 @@ step2 = "00" + step1 # e) Convert the result from a byte string into a base58 string # using Base58 encoding. # This is the most commonly used Bitcoin Address format. -addr = base58check( step2 ) +addr = base58check( hex: step2 ) #=> "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" ``` @@ -676,11 +704,11 @@ This is all then converted to Base58, which shortens the string and makes it eas privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" extended = "80" + privatekey + "01" #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db201" -checksum = hash256( extended )[0..7] +checksum = hash256( hex: extended ).hexdigest[0..7] #=> "66557e53" extendedchecksum = extended + checksum #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db20166557e53" -wif = base58( extendedchecksum ) +wif = base58( hex: extendedchecksum ) #=> "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" ``` @@ -690,7 +718,7 @@ Or let's try again with the base58check (`BASE58(X || SHA256(SHA256(X))[:4])`) s privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" extended = "80" + privatekey + "01" #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db201" -wif = base58check( extended ) +wif = base58check( hex: extended ) #=> "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" ``` @@ -832,7 +860,7 @@ pk = "022744c02580b4905349bc481a60c308c2d98d823d44888835047f6bc5c38c4e8f" # 1. Perform HASH-160 hashing on the public key # a) Perform SHA-256 hashing on the public key # b) Perform RIPEMD-160 hashing on the result of SHA-256 -step1 = hash160( pk ) +step1 = hash160( hex: pk ).hexdigest #=> "a1f37969bcb547cd9c3a28fa07c2269ef813340a" # 2. Add version byte in front of RIPEMD-160 hash (0x1e for Dodge Main Network) @@ -849,7 +877,7 @@ step2 = "1e" + step1 # e) Convert the result from a byte string into a base58 string # using Base58 encoding. # This is the most commonly used Dodge Address format. -addr = base58check( step2 ) +addr = base58check( hex: step2 ) #=> "DKuR12onkdp5GxC5c8DgXhGe4Z2AqCK3Xh" ``` @@ -980,7 +1008,7 @@ to calculate the hash of the public key ``` ruby pub = "6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0" -hash = keccak256( pub ) +hash = keccak256( hex: pub ).hexdigest #=> "2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9" ``` diff --git a/crypto-lite/Rakefile b/crypto-lite/Rakefile index 5a283ef..c38f44e 100644 --- a/crypto-lite/Rakefile +++ b/crypto-lite/Rakefile @@ -19,6 +19,7 @@ Hoe.spec 'crypto-lite' do self.history_file = 'CHANGELOG.md' self.extra_deps = [ + ['bytes'], ['digest-lite'], ['base32-alphabets'], ['base58-alphabets'], diff --git a/crypto-lite/attic/crypto_lite.rb b/crypto-lite/attic/crypto_lite.rb new file mode 100644 index 0000000..15b1db8 --- /dev/null +++ b/crypto-lite/attic/crypto_lite.rb @@ -0,0 +1,52 @@ + + ######## + # more helpers + ## check if it is a hex (string) + ## - allow optiona 0x or 0X and allow abcdef and ABCDEF + HEX_RE = /\A(?:0x)?[0-9a-f]+\z/i + + def self.args_to_input( args, kwargs ) + if kwargs[:hex] + hex = kwargs[:hex] + raise ArgumentError, "expected hex string (0-9a-f) - got >#{hex}< - can't pack string; sorry" unless hex =~ HEX_RE + + hex = strip0x( hex ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!! + [hex].pack( 'H*' ) + else ## assume single input arg for now + input = args[0] + input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not? + input + end + end + + def self.hex_to_bin_automagic( input ) + ## todo/check/fix: add configure setting to turn off automagic - why? why not? + if input.is_a?( String ) && input =~ HEX_RE + if input[0,2] == '0x' || input[0,2] == '0X' + ## starting with 0x or 0X always assume hex string for now - why? why not? + input = input[2..-1] + [input].pack( 'H*' ) + elsif input.size >= 10 + ## note: hex heuristic!! + ## for now assumes string MUST have more than 10 digits to qualify!!! + [input].pack( 'H*' ) + else + input ## pass through as is!!! (e.g. a, abc, etc.) + end + else + input ## pass through as is + end + end + + + + def self.strip0x( str ) ## todo/check: add alias e.g. strip_hex_prefix or such - why? why not? + (str[0,2] == '0x' || str[0,2] == '0X') ? str[2..-1] : str + end + +# def self.hex_to_bin( str ) +# str = strip0x( str ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!! +# [str].pack( 'H*' ) +# end + + diff --git a/crypto-lite/attic/metal.rb b/crypto-lite/attic/metal.rb new file mode 100644 index 0000000..8631277 --- /dev/null +++ b/crypto-lite/attic/metal.rb @@ -0,0 +1,135 @@ +module Crypto +module Metal + + def self.debug?() Crypto.debug?; end + + ######################## + ### to the "metal" crypto primitives + ## work with binary strings (aka byte arrays) / data + + ## + ## todo/check: use/keep bin-suffix in name - why? why not? + + + def self.base58bin( input ) + ## todo/check: input must be a (binary) string - why? why not? + Base58::Bitcoin.encode_bin( input ) + end + + def self.base58bin_check( input ) + ## todo/check: input must be a (binary) string - why? why not? + hash256 = hash256bin( input ) + base58bin( input + hash256[0,4] ) + end + + + ######################## + # (secure) hash functions + + def self.keccak256bin( input ) + message = message( input ) ## "normalize" / convert to (binary) string + Digest::KeccakLite.digest( message, 256 ) + end + + def self.rmd160bin( input ) + message = message( input ) ## "normalize" / convert to (binary) string + Digest::RMD160.digest( message ) + end + + ## add alias RIPEMD160 - why? why not? + class << self + alias_method :ripemd160bin, :rmd160bin + end + + + def self.sha256bin( input, engine=nil ) ## todo/check: add alias sha256b or such to - why? why not? + message = message( input ) ## "normalize" / convert to (binary) string + + if engine && ['openssl'].include?( engine.to_s.downcase ) + puts " engine: #{engine}" if debug? + digest = OpenSSL::Digest::SHA256.new + ## or use OpenSSL::Digest.new( 'SHA256' ) + digest.update( message ) + digest.digest + else ## use "built-in" hash function from digest module + Digest::SHA256.digest( message ) + end + end + + + def self.sha3_256bin( input, engine=nil ) + message = message( input ) ## "normalize" / convert to (binary) string + + if engine && ['openssl'].include?( engine.to_s.downcase ) + puts " engine: #{engine}" if debug? + digest = OpenSSL::Digest.new( 'SHA3-256' ) + digest.update( message ) + digest.digest + else ## use "built-in" hash function from digest module + Digest::SHA3Lite.digest( message, 256 ) + end + end + + + #### + ## helper + # def hash160( pubkey ) + # binary = [pubkey].pack( "H*" ) # Convert to binary first before hashing + # sha256 = Digest::SHA256.digest( binary ) + # ripemd160 = Digest::RMD160.digest( sha256 ) + # ripemd160.unpack( "H*" )[0] # Convert back to hex + # end + + def self.hash160bin( input ) + message = message( input ) ## "normalize" / convert to (binary) string + + rmd160bin(sha256bin( message )) + end + + + def self.hash256bin( input ) + message = message( input ) ## "normalize" / convert to (binary) string + + sha256bin(sha256bin( message )) + end + + + ############################## + ## helpers + def self.message( input ) ## convert input to (binary) string + if debug? + input_type = if input.is_a?( String ) + "#{input.class.name}/#{input.encoding}" + else + input.class.name + end + puts " input: #{input} (#{input_type})" + end + + message = if input.is_a?( Integer ) ## assume byte if single (unsigned) integer + raise ArgumentError, "expected unsigned byte (0-255) - got #{input} (0x#{input.to_s(16)}) - can't pack negative number; sorry" if input < 0 + ## note: pack - H (String) => hex string (high nibble first) + ## todo/check: is there a better way to convert integer number to (binary) string!!! + [input.to_s(16)].pack('H*') + else ## assume (binary) string + input + end + + if debug? + bytes = message.bytes + bin = bytes.map {|byte| byte.to_s(2).rjust(8, "0")}.join( ' ' ) + hex = bytes.map {|byte| byte.to_s(16).rjust(2, "0")}.join( ' ' ) + puts " #{pluralize( bytes.size, 'byte')}: #{bytes.inspect}" + puts " binary: #{bin}" + puts " hex: #{hex}" + end + + message + end + + def self.pluralize( count, noun ) + count == 1 ? "#{count} #{noun}" : "#{count} #{noun}s" + end + +end # module Metal +end # module Crypto diff --git a/crypto-lite/lib/crypto-lite.rb b/crypto-lite/lib/crypto-lite.rb index 06e6a66..f2ee744 100644 --- a/crypto-lite/lib/crypto-lite.rb +++ b/crypto-lite/lib/crypto-lite.rb @@ -5,141 +5,35 @@ ## our own 3rd party (2nd party?) +require 'bytes' + +## extend String +class String + alias_method :hexdigest, :bin_to_hex ## note: bin_to_hex added via Bytes!!! +end + + require 'digest-lite' # e.g. keccak (original submission/proposal NOT official sha3) require 'base32-alphabets' require 'base58-alphabets' require 'elliptic' - ## our own code require_relative 'crypto-lite/version' # note: let version always go first require_relative 'crypto-lite/config' require_relative 'crypto-lite/metal' - - - - -module Crypto - - def self.base58( *args, **kwargs ) - input = args_to_input( args, kwargs ) - Metal.base58bin( input ) - end - - def self.base58check( *args, **kwargs ) - input = args_to_input( args, kwargs ) - Metal.base58bin_check( input ) - end - - - ######################## - # (secure) hash functions - - def self.keccak256( *args, **kwargs ) - input = args_to_input( args, kwargs ) - Metal.keccak256bin( input ).unpack( 'H*' )[0] - end - - - def self.rmd160( *args, **kwargs ) - input = args_to_input( args, kwargs ) - Metal.rmd160bin( input ).unpack( 'H*' )[0] - end - - ## add alias RIPEMD160 - why? why not? - class << self - alias_method :ripemd160, :rmd160 - end - - - def self.sha256( *args, **kwargs ) - input = args_to_input( args, kwargs ) - engine = kwargs[:engine] - Metal.sha256bin( input, engine ).unpack( 'H*' )[0] - end - - def self.sha3_256( *args, **kwargs ) - input = args_to_input( args, kwargs ) - Metal.sha3_256bin( input ).unpack( 'H*' )[0] - end - - - - def self.hash160( *args, **kwargs ) - input = args_to_input( args, kwargs ) - Metal.hash160bin( input ).unpack( 'H*' )[0] - end - - def self.hash256( *args, **kwargs ) - input = args_to_input( args, kwargs ) - Metal.hash256bin( input ).unpack( 'H*' )[0] - end - - - - ######## - # more helpers - ## check if it is a hex (string) - ## - allow optiona 0x or 0X and allow abcdef and ABCDEF - HEX_RE = /\A(?:0x)?[0-9a-f]+\z/i - - def self.args_to_input( args, kwargs ) - if kwargs[:hex] - hex = kwargs[:hex] - raise ArgumentError, "expected hex string (0-9a-f) - got >#{hex}< - can't pack string; sorry" unless hex =~ HEX_RE - - hex = strip0x( hex ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!! - [hex].pack( 'H*' ) - else ## assume single input arg for now - input = args[0] - input = hex_to_bin_automagic( input ) ## add automagic hex (string) to bin (string) check - why? why not? - input - end - end - - def self.hex_to_bin_automagic( input ) - ## todo/check/fix: add configure setting to turn off automagic - why? why not? - if input.is_a?( String ) && input =~ HEX_RE - if input[0,2] == '0x' || input[0,2] == '0X' - ## starting with 0x or 0X always assume hex string for now - why? why not? - input = input[2..-1] - [input].pack( 'H*' ) - elsif input.size >= 10 - ## note: hex heuristic!! - ## for now assumes string MUST have more than 10 digits to qualify!!! - [input].pack( 'H*' ) - else - input ## pass through as is!!! (e.g. a, abc, etc.) - end - else - input ## pass through as is - end - end - - - def self.strip0x( str ) ## todo/check: add alias e.g. strip_hex_prefix or such - why? why not? - (str[0,2] == '0x' || str[0,2] == '0X') ? str[2..-1] : str - end - -# def self.hex_to_bin( str ) -# str = strip0x( str ) ## check if input starts with 0x or 0X if yes - (auto-)cut off!!!!! -# [str].pack( 'H*' ) -# end - -end # module Crypto - - - - require_relative 'crypto-lite/helper' -include CryptoHelper # add convenience "top-level" / global helpers require_relative 'crypto-lite/sign_rsa' RSA = Crypto::RSA +## auto-add top-level helpers - why? why not? +include CryptoHelper + + puts CryptoLite.banner ## say hello diff --git a/crypto-lite/lib/crypto-lite/helper.rb b/crypto-lite/lib/crypto-lite/helper.rb index 3e9c8de..7e1e6c6 100644 --- a/crypto-lite/lib/crypto-lite/helper.rb +++ b/crypto-lite/lib/crypto-lite/helper.rb @@ -1,25 +1,64 @@ - module CryptoHelper - ### note: use include CryptoHelper - ## to get "top-level" / global helpers - ## add convenience "top-level" helpers - def sha256( *args, **kwargs ) Crypto.sha256( *args, **kwargs ); end - def sha3_256( *args, **kwargs ) Crypto.sha3_256( *args, **kwargs ); end - def keccak256( *args, **kwargs ) Crypto.keccak256( *args, **kwargs ); end +### +# todo: change ''.b to BYTE_ZERO constant or such - why? why not? + + + ###### + # add convenience helpers + def base58( bin=''.b, hex: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.base58( bin ) + end - def rmd160( *args, **kwargs ) Crypto.rmd160( *args, **kwargs ); end - ## def ripemd160( input ) Crypto.rmd160( input ); end + def base58check( bin=''.b, hex: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.base58check( bin ) + end + + def keccak256( bin=''.b, hex: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.keccak256( bin ) + end + + def rmd160( bin=''.b, hex: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.rmd160( bin ) + end + ## add alias RIPEMD160 - why? why not? alias_method :ripemd160, :rmd160 - def hash160( *args, **kwargs ) Crypto.hash160( *args, **kwargs ); end + def sha256( bin=''.b, hex: nil, + engine: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.sha256( bin, engine ) + end + + def sha3_256( bin=''.b, hex: nil, + engine: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.sha3_256( bin, engine ) + end - def hash256( *args, **kwargs ) Crypto.hash256( *args, **kwargs ); end + def hash160( bin=''.b, hex: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.hash160( bin ) + end + def hash256( bin=''.b, hex: nil ) + bin = hex.hex_to_bin if hex # uses Bytes.hex_to_bin + Crypto::Metal.hash256( bin ) + end +end # module CryptoHelper - def base58( *args, **kwargs ) Crypto.base58( *args, **kwargs ); end - def base58check( *args, **kwargs ) Crypto.base58check( *args, **kwargs ); end -end +module Crypto + extend CryptoHelper + ## + ## lets you use + ## Crypto.sha256( bin, hex: ) -> bin + ## Crytpo.base58( bin, hex: ) -> bin + ## etc. +end # module Crypto diff --git a/crypto-lite/lib/crypto-lite/metal.rb b/crypto-lite/lib/crypto-lite/metal.rb index 8631277..09e9748 100644 --- a/crypto-lite/lib/crypto-lite/metal.rb +++ b/crypto-lite/lib/crypto-lite/metal.rb @@ -1,72 +1,56 @@ -module Crypto -module Metal - - def self.debug?() Crypto.debug?; end - ######################## - ### to the "metal" crypto primitives - ## work with binary strings (aka byte arrays) / data - - ## - ## todo/check: use/keep bin-suffix in name - why? why not? +module Crypto +module MetalHelper + #### + # note: all (digest) hash functions + # take in a binary string and return a binary string!!!! - def self.base58bin( input ) - ## todo/check: input must be a (binary) string - why? why not? - Base58::Bitcoin.encode_bin( input ) + def base58( bin ) + Base58::Bitcoin.encode_bin( bin ) end - def self.base58bin_check( input ) - ## todo/check: input must be a (binary) string - why? why not? - hash256 = hash256bin( input ) - base58bin( input + hash256[0,4] ) + def base58check( bin ) + hash256 = hash256( bin ) + base58( bin + hash256[0,4] ) end ######################## # (secure) hash functions - def self.keccak256bin( input ) - message = message( input ) ## "normalize" / convert to (binary) string - Digest::KeccakLite.digest( message, 256 ) + def keccak256( bin ) + Digest::KeccakLite.digest( bin, 256 ) end - def self.rmd160bin( input ) - message = message( input ) ## "normalize" / convert to (binary) string - Digest::RMD160.digest( message ) + def rmd160( bin ) + Digest::RMD160.digest( bin ) end - ## add alias RIPEMD160 - why? why not? - class << self - alias_method :ripemd160bin, :rmd160bin - end + alias_method :ripemd160, :rmd160 - def self.sha256bin( input, engine=nil ) ## todo/check: add alias sha256b or such to - why? why not? - message = message( input ) ## "normalize" / convert to (binary) string - + def sha256( bin, engine=nil ) ## todo/check: add alias sha256b or such to - why? why not? if engine && ['openssl'].include?( engine.to_s.downcase ) - puts " engine: #{engine}" if debug? + ## puts " engine: #{engine}" if debug? digest = OpenSSL::Digest::SHA256.new ## or use OpenSSL::Digest.new( 'SHA256' ) - digest.update( message ) + digest.update( bin ) digest.digest else ## use "built-in" hash function from digest module - Digest::SHA256.digest( message ) + Digest::SHA256.digest( bin ) end end - def self.sha3_256bin( input, engine=nil ) - message = message( input ) ## "normalize" / convert to (binary) string - + def sha3_256( bin, engine=nil ) if engine && ['openssl'].include?( engine.to_s.downcase ) - puts " engine: #{engine}" if debug? + ## puts " engine: #{engine}" if debug? digest = OpenSSL::Digest.new( 'SHA3-256' ) - digest.update( message ) + digest.update( bin ) digest.digest else ## use "built-in" hash function from digest module - Digest::SHA3Lite.digest( message, 256 ) + Digest::SHA3Lite.digest( bin, 256 ) end end @@ -80,56 +64,23 @@ def self.sha3_256bin( input, engine=nil ) # ripemd160.unpack( "H*" )[0] # Convert back to hex # end - def self.hash160bin( input ) - message = message( input ) ## "normalize" / convert to (binary) string - - rmd160bin(sha256bin( message )) + def hash160( bin ) + rmd160(sha256( bin )) end - - def self.hash256bin( input ) - message = message( input ) ## "normalize" / convert to (binary) string - - sha256bin(sha256bin( message )) + def hash256( bin ) + sha256(sha256( bin )) end +end # module MetalHelper - ############################## - ## helpers - def self.message( input ) ## convert input to (binary) string - if debug? - input_type = if input.is_a?( String ) - "#{input.class.name}/#{input.encoding}" - else - input.class.name - end - puts " input: #{input} (#{input_type})" - end - - message = if input.is_a?( Integer ) ## assume byte if single (unsigned) integer - raise ArgumentError, "expected unsigned byte (0-255) - got #{input} (0x#{input.to_s(16)}) - can't pack negative number; sorry" if input < 0 - ## note: pack - H (String) => hex string (high nibble first) - ## todo/check: is there a better way to convert integer number to (binary) string!!! - [input.to_s(16)].pack('H*') - else ## assume (binary) string - input - end - - if debug? - bytes = message.bytes - bin = bytes.map {|byte| byte.to_s(2).rjust(8, "0")}.join( ' ' ) - hex = bytes.map {|byte| byte.to_s(16).rjust(2, "0")}.join( ' ' ) - puts " #{pluralize( bytes.size, 'byte')}: #{bytes.inspect}" - puts " binary: #{bin}" - puts " hex: #{hex}" - end - - message - end +module Metal + extend MetalHelper + ## lets you use + ## Crypto::Metal.sha256( bin ) -> bin + ## Crytpo::Metal.base58( bin ) -> bin + ## etc. +end # module Metal +end # module Crypto - def self.pluralize( count, noun ) - count == 1 ? "#{count} #{noun}" : "#{count} #{noun}s" - end -end # module Metal -end # module Crypto diff --git a/crypto-lite/lib/crypto-lite/version.rb b/crypto-lite/lib/crypto-lite/version.rb index 81054da..6e36fbe 100644 --- a/crypto-lite/lib/crypto-lite/version.rb +++ b/crypto-lite/lib/crypto-lite/version.rb @@ -2,8 +2,8 @@ module CryptoLite MAJOR = 0 - MINOR = 3 - PATCH = 1 + MINOR = 4 + PATCH = 0 VERSION = [MAJOR,MINOR,PATCH].join('.') def self.version diff --git a/crypto-lite/sandbox/test_bitcoin.rb b/crypto-lite/sandbox/test_bitcoin.rb index 2c66a68..36227de 100644 --- a/crypto-lite/sandbox/test_bitcoin.rb +++ b/crypto-lite/sandbox/test_bitcoin.rb @@ -6,6 +6,8 @@ require 'crypto-lite' + + puts EC::SECP256K1.order puts EC::SECP256K1.order.to_s(16).downcase @@ -65,10 +67,10 @@ def roll_dice() SecureRandom.random_number(6); end puts "checksum:" # puts checksum('00662ad25db00e7bb38bc04831ae48b4b446d12698') #=> 17d515b6 -pp hash256( '00662ad25db00e7bb38bc04831ae48b4b446d12698' )[0..7] +pp hash256( hex: '00662ad25db00e7bb38bc04831ae48b4b446d12698' ).hexdigest[0..7] puts "base58:" -pp base58('00662ad25db00e7bb38bc04831ae48b4b446d1269817d515b6') +pp base58( hex: '00662ad25db00e7bb38bc04831ae48b4b446d1269817d515b6') puts @@ -76,17 +78,17 @@ def roll_dice() SecureRandom.random_number(6); end privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" pp extended = "80" + privatekey + "01" #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db201" -pp checksum = hash256( extended )[0..7] +pp checksum = hash256( hex: extended ).hexdigest[0..7] #=> "66557e53" pp extendedchecksum = extended + checksum #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db20166557e53" -pp wif = base58( extendedchecksum ) +pp wif = base58( hex: extendedchecksum ) #=> "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" puts privatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" pp extended = "80" + privatekey + "01" #=> "80ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db201" -pp wif = base58check( extended ) +pp wif = base58check( hex: extended ) #=> "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" diff --git a/crypto-lite/sandbox/test_dodge.rb b/crypto-lite/sandbox/test_dodge.rb index 8203fa2..1bff53d 100644 --- a/crypto-lite/sandbox/test_dodge.rb +++ b/crypto-lite/sandbox/test_dodge.rb @@ -35,7 +35,7 @@ pk = "022744c02580b4905349bc481a60c308c2d98d823d44888835047f6bc5c38c4e8f" -pp step1 = hash160( pk ) +pp step1 = hash160( hex: pk ).hexdigest #=> "a1f37969bcb547cd9c3a28fa07c2269ef813340a" # 2. Add version byte in front of RIPEMD-160 hash (0x1e for Dodge Main Network) @@ -52,7 +52,7 @@ # e) Convert the result from a byte string into a base58 string # using Base58 encoding. # This is the most commonly used Dodge Address format. -pp addr = base58check( step2 ) +pp addr = base58check( hex: step2 ) #=> "DKuR12onkdp5GxC5c8DgXhGe4Z2AqCK3Xh" diff --git a/crypto-lite/sandbox/test_ethereum.rb b/crypto-lite/sandbox/test_ethereum.rb index 7ebcee7..ee5cb02 100644 --- a/crypto-lite/sandbox/test_ethereum.rb +++ b/crypto-lite/sandbox/test_ethereum.rb @@ -94,7 +94,7 @@ #=> "6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0" -pp hash = keccak256(pub) +pp hash = keccak256( hex: pub ).hexdigest #=> "2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9" ## expected result from ethereum book: diff --git a/crypto-lite/sandbox/test_hash.rb b/crypto-lite/sandbox/test_hash.rb index 7a604db..8bbdc3a 100644 --- a/crypto-lite/sandbox/test_hash.rb +++ b/crypto-lite/sandbox/test_hash.rb @@ -7,64 +7,64 @@ puts ":" -pp sha256( '' ) #=> 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', +pp sha256( '' ).hexdigest #=> 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', puts "abc:" -pp sha256( "abc" ) #=> -pp sha256( "abc".b ) #=> -pp sha256( "\x61\x62\x63" ) -pp sha256( 0x616263 ) - -pp sha256( hex: '616263' ) -pp sha256( hex: '0x616263' ) -pp sha256( hex: '0X616263' ) +pp sha256( "abc" ).hexdigest #=> +pp sha256( "abc".b ).hexdigest #=> +pp sha256( "\x61\x62\x63" ).hexdigest +## pp sha256( 0x616263 ) + +pp sha256( hex: '616263' ).hexdigest +pp sha256( hex: '0x616263' ).hexdigest +pp sha256( hex: '0X616263' ).hexdigest ## pp sha256( hex: 'hello' ) -- fails - uses non-hex chars -pp sha256( "abc", engine: 'openssl' ) +pp sha256( "abc", engine: 'openssl' ).hexdigest # a = dec (97), hex (61), bin (01100001) puts "---" puts "a:" -pp sha256( "a" ) #=> -pp sha256( "\x61" ) #=> -pp sha256( 0b01100001 ) #=> -pp sha256( 0x61 ) -pp sha256( "a", engine: 'openssl' ) +pp sha256( "a" ).hexdigest #=> +pp sha256( "\x61" ).hexdigest #=> +## pp sha256( 0b01100001 ) #=> +## pp sha256( 0x61 ) +pp sha256( "a", engine: 'openssl' ).hexdigest -pp sha256( hex: '61' ) -pp sha256( hex: '0x61' ) +pp sha256( hex: '61' ).hexdigest +pp sha256( hex: '0x61' ).hexdigest puts "b:" -pp sha256( "b" ) #=> -pp sha256( 0b01100010 ) #=> -pp sha256( "b", :openssl ) +pp sha256( "b" ).hexdigest #=> +## pp sha256( 0b01100010 ) #=> +pp sha256( "b", engine: 'openssl' ).hexdigest puts "c:" -pp sha256( "c" ) #=> -pp sha256( 0b01100011 ) #=> -pp sha256( "c", :openssl ) +pp sha256( "c" ).hexdigest #=> +## pp sha256( 0b01100011 ) #=> +pp sha256( "c", engine: 'openssl' ).hexdigest puts "Hello, Cryptos!:" -pp sha256( "Hello, Cryptos!" ) +pp sha256( "Hello, Cryptos!" ).hexdigest -pp keccak256( "Hello, Cryptos!" ) -pp rmd160( "Hello, Cryptos!" ) +pp keccak256( "Hello, Cryptos!" ).hexdigest +pp rmd160( "Hello, Cryptos!" ).hexdigest -pp hash160( hex: '02b9d1cc0b793b03b9f64d022e9c67d5f32670b03f636abf0b3147b34123d13990' ) -pp hash160( hex: '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' ) +pp hash160( hex: '02b9d1cc0b793b03b9f64d022e9c67d5f32670b03f636abf0b3147b34123d13990' ).hexdigest +pp hash160( hex: '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' ).hexdigest -pp hash256( hex: '6fe6b145a3908a4d6616b13c1109717add8672c900' ) +pp hash256( hex: '6fe6b145a3908a4d6616b13c1109717add8672c900' ).hexdigest -pp sha256( "Satoshi Nakamoto" ) -pp sha256( "Satoshi Nakamot0" ) +pp sha256( "Satoshi Nakamoto" ).hexdigest +pp sha256( "Satoshi Nakamot0" ).hexdigest diff --git a/crypto-lite/sandbox/test_sign.rb b/crypto-lite/sandbox/test_sign.rb index 5acf8d6..19c6c55 100644 --- a/crypto-lite/sandbox/test_sign.rb +++ b/crypto-lite/sandbox/test_sign.rb @@ -97,7 +97,7 @@ tx = "from: alice, to: bob, $21" -pp tx_hash = sha256( tx ) +pp tx_hash = sha256( tx ).hexdigest #=> "426a472a6c69bf68354391b7822393bea3952cde9df8949ad7a0f5f405b2fcb5" puts "---" @@ -113,7 +113,7 @@ #=> true tx = "from: alice, to: bob, $22" -pp tx_hash = sha256( tx ) +pp tx_hash = sha256( tx ).hexdigest #=> "e899604bb4c95d2f1a7cfe561ad65941769e2064bdbbcaa79eb64ce0a2832380" pp RSA.valid_signature?( tx_hash, tx_signature, alice_pub ) diff --git a/crypto-lite/test/test_base58.rb b/crypto-lite/test/test_base58.rb index b7c6889..380d827 100644 --- a/crypto-lite/test/test_base58.rb +++ b/crypto-lite/test/test_base58.rb @@ -9,14 +9,16 @@ class TestBase58 < MiniTest::Test HEX_TESTS = [ - ["00000000000000000000", "1111111111"], + ["00000000000000000000", "1111111111"], ["00000000000000000000123456789abcdef0", "111111111143c9JGph3DZ"], ] + def test_hex HEX_TESTS.each do |item| - assert_equal item[1], base58( hex: item[0] ) - assert_equal item[1], base58( item[0] ) + assert_equal item[1], Crypto.base58( hex: item[0] ) + bin = Bytes.hex_to_bin( item[0] ) + assert_equal item[1], Crypto.base58( bin ) end end @@ -27,10 +29,11 @@ def test_bitcoin_addr pkh = 'f54a5851e9372b87810a8e60cdd2e7cfd80b6e31' ## all-in-one - assert_equal addr_exp, base58check( hex: '00' + pkh ) - assert_equal addr_exp, base58check( '00' + pkh ) + assert_equal addr_exp, Crypto.base58check( hex: '00' + pkh ) + bin = Bytes.hex_to_bin('00' + pkh) + assert_equal addr_exp, Crypto.base58check( bin ) - assert_equal addr_exp, Crypto::Metal.base58bin_check( "\x00" + [pkh].pack('H*') ) + assert_equal addr_exp, Crypto::Metal.base58check( "\x00" + [pkh].pack('H*') ) end end # class TestBase58 diff --git a/crypto-lite/test/test_bitcoin_addr.rb b/crypto-lite/test/test_bitcoin_addr.rb index 2413e2a..bb26ea4 100644 --- a/crypto-lite/test/test_bitcoin_addr.rb +++ b/crypto-lite/test/test_bitcoin_addr.rb @@ -11,11 +11,11 @@ class TestBitcoinAddr < MiniTest::Test def test_bitcoin_addr_v1 pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" - step1 = sha256( pk ) + step1 = Crypto.sha256( hex: pk ).hexdigest assert_equal "0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98", step1 - step2 = ripemd160( step1 ) + step2 = Crypto.ripemd160( hex: step1 ).hexdigest assert_equal "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31", step2 @@ -23,11 +23,11 @@ def test_bitcoin_addr_v1 assert_equal "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31", step3 - step4 = sha256( step3 ) + step4 = Crypto.sha256( hex: step3 ).hexdigest assert_equal "ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c", step4 - step5 = sha256( step4 ) + step5 = Crypto.sha256( hex: step4 ).hexdigest assert_equal "c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd", step5 @@ -37,7 +37,7 @@ def test_bitcoin_addr_v1 step7 = step3 + step6 assert_equal "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8", step7 - addr = base58( step7 ) + addr = Crypto.base58( hex: step7 ) assert_equal "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs", addr end @@ -45,13 +45,13 @@ def test_bitcoin_addr_v1 def test_bitcoin_addr_v2 pk = "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" - step1 = hash160( pk ) + step1 = Crypto.hash160( hex: pk ).hexdigest assert_equal "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31", step1 step2 = "00" + step1 assert_equal "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31", step2 - addr = base58check( step2 ) + addr = Crypto.base58check( hex: step2 ) assert_equal "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs", addr end diff --git a/crypto-lite/test/test_hash.rb b/crypto-lite/test/test_hash.rb index 3d07822..afa3d60 100644 --- a/crypto-lite/test/test_hash.rb +++ b/crypto-lite/test/test_hash.rb @@ -24,22 +24,28 @@ class TestHash < MiniTest::Test ] +def assert_hexdigest( exp, bin ) + assert_equal exp, bin.hexdigest +end + + def test_keccak256 KECCAK256_TESTS.each do |item| - assert_equal item[1], keccak256( item[0].b ) + assert_hexdigest item[1], Crypto.keccak256( item[0].b ) end end def test_sha3_256 SHA3_256_TESTS.each do |item| - assert_equal item[1], sha3_256( item[0].b ) + assert_hexdigest item[1], Crypto.sha3_256( item[0].b ) end end def test_ripemd160 RIPEMD160_TESTS.each do |item| - assert_equal item[1], ripemd160( item[0].b ) + assert_hexdigest item[1], Crypto.ripemd160( item[0].b ) + assert_hexdigest item[1], Crypto.rmd160( item[0].b ) end end diff --git a/crypto-lite/test/test_hash_sha.rb b/crypto-lite/test/test_hash_sha.rb index 754c96f..6e0f6fa 100644 --- a/crypto-lite/test/test_hash_sha.rb +++ b/crypto-lite/test/test_hash_sha.rb @@ -30,10 +30,17 @@ class TestHashSha < MiniTest::Test ] + +def assert_hexdigest( exp, bin ) + assert_equal exp, bin.hexdigest +end + + + def test_bin BIN_TESTS.each do |item| - assert_equal item[1], sha256( item[0].b ) - assert_equal item[1], sha256( item[0].b, engine: 'openssl' ) + assert_hexdigest item[1], Crypto.sha256( item[0].b ) + assert_hexdigest item[1], Crypto.sha256( item[0].b, engine: 'openssl' ) end end @@ -42,17 +49,17 @@ def test_abc ['abc', 'abc'.b, "\x61\x62\x63", - 0x616263 + # 0x616263 ].each do |input| - assert_equal SHA256_ABC, sha256( input ) - assert_equal SHA256_ABC, sha256( input, engine: 'openssl' ) + assert_hexdigest SHA256_ABC, Crypto.sha256( input ) + assert_hexdigest SHA256_ABC, Crypto.sha256( input, engine: 'openssl' ) end ['616263', '0x616263', '0X616263' ].each do |input| - assert_equal SHA256_ABC, sha256( hex: input ) + assert_hexdigest SHA256_ABC, Crypto.sha256( hex: input ) end ## pp sha256hex( 'hello' ) -- fails - uses non-hex chars @@ -60,30 +67,30 @@ def test_abc [ 'a', "\x61", - 0b01100001, - 0x61 + # 0b01100001, + # 0x61 ].each do |input| - assert_equal SHA256_A, sha256( input ) - assert_equal SHA256_A, sha256( input, engine: 'openssl' ) + assert_hexdigest SHA256_A, Crypto.sha256( input ) + assert_hexdigest SHA256_A, Crypto.sha256( input, engine: 'openssl' ) end ['61', '0x61', '0X61' ].each do |input| - assert_equal SHA256_A, sha256( hex: input ) + assert_hexdigest SHA256_A, Crypto.sha256( hex: input ) end [ 'b', - 0b01100010 + # 0b01100010 ].each do |input| - assert_equal SHA256_B, sha256( input ) + assert_hexdigest SHA256_B, Crypto.sha256( input ) end [ 'c', - 0b01100011 + # 0b01100011 ].each do |input| - assert_equal SHA256_C, sha256( input ) + assert_hexdigest SHA256_C, Crypto.sha256( input ) end end