Module: Crypto

Defined in:
lib/crypto-lite.rb,
lib/crypto-lite/config.rb

Defined Under Namespace

Modules: RSA Classes: Configuration

Constant Summary collapse

HEX_RE =

check if it is a hex (string)

- allow optiona 0x or 0X  and allow abcdef and ABCDEF
/\A(?:0x)?[0-9a-f]+\z/i

Class Method Summary collapse

Class Method Details

.base58(input) ⇒ Object



37
38
39
40
# File 'lib/crypto-lite.rb', line 37

def self.base58( input )
  input = hex_to_bin_automagic( input )  ## add automagic hex (string) to bin (string) check - why? why not?

  base58bin( input )
end

.base58bin(input) ⇒ Object



32
33
34
35
# File 'lib/crypto-lite.rb', line 32

def self.base58bin( input )
  ## todo/check: input must be a (binary) string - why? why not?

  Base58::Bitcoin.encode_bin( input )
end

.base58bin_check(input) ⇒ Object



50
51
52
53
54
# File 'lib/crypto-lite.rb', line 50

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

.base58check(input) ⇒ Object



56
57
58
59
# File 'lib/crypto-lite.rb', line 56

def self.base58check( input )
  input = hex_to_bin_automagic( input )  ## add automagic hex (string) to bin (string) check - why? why not?

  base58bin_check( input )
end

.base58hex(input) ⇒ Object

Raises:

  • (ArgumentError)


42
43
44
45
46
47
# File 'lib/crypto-lite.rb', line 42

def self.base58hex( input )
  raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry"   unless input =~ HEX_RE

  input = strip0x( input )  ##  check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!

  base58bin( [input].pack( 'H*' ) )
end

.base58hex_check(input) ⇒ Object

Raises:

  • (ArgumentError)


61
62
63
64
65
66
# File 'lib/crypto-lite.rb', line 61

def self.base58hex_check( input )
  raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry"   unless input =~ HEX_RE

  input = strip0x( input )  ##  check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!

  base58bin_check( [input].pack( 'H*' ) )
end

.configurationObject

lets you use

Crypto.configure do |config|
   config.debug  =  true
end


18
19
20
# File 'lib/crypto-lite/config.rb', line 18

def self.configuration
  @configuration ||= Configuration.new
end

.configure {|configuration| ... } ⇒ Object

Yields:



22
23
24
# File 'lib/crypto-lite/config.rb', line 22

def self.configure
  yield( configuration )
end

.debug=(value) ⇒ Object



28
# File 'lib/crypto-lite/config.rb', line 28

def self.debug=(value) self.configuration.debug = value; end

.debug?Boolean

add convenience helper for format

Returns:

  • (Boolean)


27
# File 'lib/crypto-lite/config.rb', line 27

def self.debug?() configuration.debug?; end

.hash160(input) ⇒ Object



178
179
180
181
# File 'lib/crypto-lite.rb', line 178

def self.hash160( input )
  input = hex_to_bin_automagic( input )  ## add automagic hex (string) to bin (string) check - why? why not?

  hash160bin( input ).unpack( 'H*' )[0]
end

.hash160bin(input) ⇒ Object

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



172
173
174
175
176
# File 'lib/crypto-lite.rb', line 172

def self.hash160bin( input )
  message = message( input )   ## "normalize" / convert to (binary) string


  rmd160bin(sha256bin( message ))
end

.hash160hex(input) ⇒ Object

convenience helper - lets you pass in hex string

Raises:

  • (ArgumentError)


183
184
185
186
187
188
# File 'lib/crypto-lite.rb', line 183

def self.hash160hex( input )  ## convenience helper - lets you pass in hex string

  raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry"   unless input =~ HEX_RE

  input = strip0x( input )  ##  check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!

  hash160bin( [input].pack( 'H*' ) ).unpack( 'H*' )[0]
end

.hash256(input) ⇒ Object



198
199
200
201
# File 'lib/crypto-lite.rb', line 198

def self.hash256( input )
  input = hex_to_bin_automagic( input )  ## add automagic hex (string) to bin (string) check - why? why not?

  hash256bin( input ).unpack( 'H*' )[0]
end

.hash256bin(input) ⇒ Object



192
193
194
195
196
# File 'lib/crypto-lite.rb', line 192

def self.hash256bin( input )
  message = message( input )   ## "normalize" / convert to (binary) string


  sha256bin(sha256bin( message ))
end

.hash256hex(input) ⇒ Object

convenience helper - lets you pass in hex string

Raises:

  • (ArgumentError)


203
204
205
206
207
208
# File 'lib/crypto-lite.rb', line 203

def self.hash256hex( input )  ## convenience helper - lets you pass in hex string

  raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry"   unless input =~ HEX_RE

  input = strip0x( input )  ##  check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!

  hash256bin( [input].pack( 'H*' ) ).unpack( "H*" )[0]
end

.hex_to_bin(str) ⇒ Object



237
238
239
240
# File 'lib/crypto-lite.rb', line 237

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

.hex_to_bin_automagic(input) ⇒ Object

more helpers



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/crypto-lite.rb', line 213

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

.keccak256(input) ⇒ Object



110
111
112
113
# File 'lib/crypto-lite.rb', line 110

def self.keccak256( input )
  input = hex_to_bin_automagic( input )  ## add automagic hex (string) to bin (string) check - why? why not?

  keccak256bin( input ).unpack( 'H*' )[0]
end

.keccak256bin(input) ⇒ Object



105
106
107
108
# File 'lib/crypto-lite.rb', line 105

def self.keccak256bin( input )
  message = message( input )   ## "normalize" / convert to (binary) string

  Digest::SHA3.digest( message, 256 )
end

.message(input) ⇒ Object

(secure) hash functions



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/crypto-lite.rb', line 72

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

.pluralize(count, noun) ⇒ Object



242
243
244
# File 'lib/crypto-lite.rb', line 242

def self.pluralize( count, noun )
   count == 1 ? "#{count} #{noun}" : "#{count} #{noun}s"
end

.rmd160(input) ⇒ Object Also known as: ripemd160



122
123
124
125
# File 'lib/crypto-lite.rb', line 122

def self.rmd160( input )
  input = hex_to_bin_automagic( input )  ## add automagic hex (string) to bin (string) check - why? why not?

  rmd160bin( input ).unpack( 'H*' )[0]
end

.rmd160bin(input) ⇒ Object Also known as: ripemd160bin



117
118
119
120
# File 'lib/crypto-lite.rb', line 117

def self.rmd160bin( input )
  message = message( input )   ## "normalize" / convert to (binary) string

  Digest::RMD160.digest( message )
end

.sha256(input, engine = nil) ⇒ Object



148
149
150
151
# File 'lib/crypto-lite.rb', line 148

def self.sha256( input, engine=nil )
  input = hex_to_bin_automagic( input )  ## add automagic hex (string) to bin (string) check - why? why not?

  sha256bin( input, engine ).unpack( 'H*' )[0]
end

.sha256bin(input, engine = nil) ⇒ Object

todo/check: add alias sha256b or such to - why? why not?



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/crypto-lite.rb', line 135

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
       digest.update( message )
       digest.digest
     else  ## use "built-in" hash function from digest module

       Digest::SHA256.digest( message )
     end
end

.sha256hex(input, engine = nil) ⇒ Object

convenience helper - lets you pass in hex string

Raises:

  • (ArgumentError)


154
155
156
157
158
159
# File 'lib/crypto-lite.rb', line 154

def self.sha256hex( input, engine=nil )  ## convenience helper - lets you pass in hex string

  raise ArgumentError, "expected hex string (0-9a-f) - got >#{input}< - can't pack string; sorry"   unless input =~ HEX_RE

  input = strip0x( input )  ##  check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!

  sha256bin( [input].pack( 'H*' ), engine ).unpack( 'H*' )[0]
end

.strip0x(str) ⇒ Object

todo/check: add alias e.g. strip_hex_prefix or such - why? why not?



233
234
235
# File 'lib/crypto-lite.rb', line 233

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