bip_mnemonic 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +5 -5
  2. data/lib/bip_mnemonic.rb +44 -29
  3. metadata +7 -8
  4. data/lib/pbkdf2.rb +0 -118
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bbf1e975d44bbde5154bcd0e878bebd99543b010
4
- data.tar.gz: 12bffd32fff7bd73af2bf6acddaf79a2caea0a72
2
+ SHA256:
3
+ metadata.gz: 866130921b342eab2a72f02b33e659e1a644b6a832d13e31af08bcbcd209f9ea
4
+ data.tar.gz: 8d2581038cc68b6ac8588b7274f425966bcb3d7078ee63638a1bc7a29893c3f1
5
5
  SHA512:
6
- metadata.gz: 2e11c8dd13d1092926a1af73d2904b87581cceb68eeae4060374d65e09fc429f07a0919a34d8ea8d183c9929771af17d7100797427260787b496dd95dce0a18e
7
- data.tar.gz: f63d15d3809ecec185c146cb155bf7368012b2cbc72fbe7bf357e3e63cfbb459116e32d54a32c5fbf8751f988c83fcaa05b8e931269fcd3d651bc7b1adbb6947
6
+ metadata.gz: 9e3416ed270b6c5679bf406cbaae6c67f29e30991a15adcd129e6d07ca9e0234b8d0f5c776d26d5e5114d7e3a76a9abfe70d934cf6ee7176c570e3ef0168e2b7
7
+ data.tar.gz: c8ea91e39855b9604d49ecbbb285c6916f2db3bd8135bd1ac4860010e1cdd84c619ea5b7e88c9454fe87da83275176a5e06613e4ac5dba298436bb19228bd985
@@ -1,51 +1,66 @@
1
- require 'pbkdf2'
2
-
1
+ require 'openssl'
3
2
  class BipMnemonic
4
- VERSION = "0.0.2"
3
+ VERSION = '0.0.3'.freeze
4
+
5
5
  def self.to_mnemonic(options)
6
6
  options ||= {}
7
7
  bits = options[:bits] || 128
8
- unless options[:entropy].nil?
9
- raise ArgumentError, "Entropy is empty" if options[:entropy] == ""
10
- entropy_bytes = [options[:entropy]].pack("H*")
8
+ if options[:entropy].nil?
9
+ entropy_bytes = OpenSSL::Random.random_bytes(bits / 8)
11
10
  else
12
- entropy_bytes = OpenSSL::Random.pseudo_bytes(bits/8)
11
+ raise ArgumentError, 'Entropy is empty' if options[:entropy].empty?
12
+ entropy_bytes = [options[:entropy]].pack('H*')
13
13
  end
14
- entropy_binary = entropy_bytes.unpack("B*").first
14
+ entropy_binary = entropy_bytes.unpack('B*').first
15
15
  seed_binary = entropy_binary + checksum(entropy_binary)
16
- words_array = File.readlines(File.join(File.dirname(File.expand_path(__FILE__)), '../words/english.txt')).map(&:strip)
17
- seed_binary.chars.each_slice(11).map(&:join).map{|item| item.to_i(2)}.map {|i| words_array[i]}.join(" ")
16
+ words_array = File.readlines(
17
+ File.join(
18
+ File.dirname(File.expand_path(__FILE__)), '../words/english.txt'
19
+ )
20
+ ).map(&:strip)
21
+ seed_binary.chars
22
+ .each_slice(11)
23
+ .map(&:join)
24
+ .map { |item| item.to_i(2) }
25
+ .map { |i| words_array[i] }
26
+ .join(' ')
18
27
  end
19
28
 
20
29
  def self.to_entropy(options)
21
30
  options ||= {}
22
- raise ArgumentError, "Mnemonic not set" if options[:mnemonic].nil?
23
- raise ArgumentError, "Mnemonic is empty" if options[:mnemonic] == ""
24
- words_array = File.readlines(File.join(File.dirname(File.expand_path(__FILE__)), '../words/english.txt')).map(&:strip)
25
- mnemonic_array = options[:mnemonic].split(" ").map do |word|
31
+ raise ArgumentError, 'Mnemonic not set' if options[:mnemonic].nil?
32
+ raise ArgumentError, 'Mnemonic is empty' if options[:mnemonic].empty?
33
+ words_array = File.readlines(
34
+ File.join(
35
+ File.dirname(File.expand_path(__FILE__)), '../words/english.txt'
36
+ )
37
+ ).map(&:strip)
38
+ mnemonic_array = options[:mnemonic].split(' ').map do |word|
26
39
  word_index = words_array.index(word)
27
- raise IndexError, "Word not found in words list" if word_index.nil?
28
- word_index.to_s(2).rjust(11,"0")
40
+ raise IndexError, 'Word not found in words list' if word_index.nil?
41
+ word_index.to_s(2).rjust(11, '0')
29
42
  end
30
43
  mnemonic_binary_with_checksum = mnemonic_array.join.to_s
31
- entropy_binary = mnemonic_binary_with_checksum.slice(0,mnemonic_binary_with_checksum.length*32/33)
32
- checksum_bits = mnemonic_binary_with_checksum.slice(-(entropy_binary.length/32),(entropy_binary.length/32))
33
- if checksum(entropy_binary) == checksum_bits
34
- return [entropy_binary].pack("B*").unpack("H*").first
35
- else
36
- raise SecurityError, "Checksum mismatch, invalid mnemonic"
37
- end
44
+ entropy_binary =mnemonic_binary_with_checksum.slice(0, mnemonic_binary_with_checksum.length * 32 / 33)
45
+ checksum_bits = mnemonic_binary_with_checksum.slice(-(entropy_binary.length / 32), (entropy_binary.length / 32))
46
+ raise SecurityError, 'Checksum mismatch, invalid mnemonic' unless checksum(entropy_binary) == checksum_bits
47
+ [entropy_binary].pack('B*').unpack('H*').first
38
48
  end
39
49
 
40
50
  def self.checksum(entropy_binary)
41
- sha256hash = OpenSSL::Digest::SHA256.hexdigest([entropy_binary].pack("B*"))
42
- sha256hash_binary = [sha256hash].pack("H*").unpack("B*").first
43
- binary_checksum = sha256hash_binary.slice(0,(entropy_binary.length/32))
51
+ sha256hash = OpenSSL::Digest::SHA256.hexdigest([entropy_binary].pack('B*'))
52
+ sha256hash_binary = [sha256hash].pack('H*').unpack('B*').first
53
+ sha256hash_binary.slice(0, (entropy_binary.length / 32))
44
54
  end
45
55
 
46
56
  def self.to_seed(options)
47
- raise ArgumentError, "Mnemonic not set" if options[:mnemonic].nil?
48
- PBKDF2.hex_string(password: options[:mnemonic], salt: "mnemonic#{options[:password]}", iterations: 2048, hash_function: OpenSSL::Digest::SHA512, key_length: 512)
57
+ raise ArgumentError, 'Mnemonic not set' if options[:mnemonic].nil?
58
+ OpenSSL::PKCS5.pbkdf2_hmac(
59
+ options[:mnemonic],
60
+ "mnemonic#{options[:password]}",
61
+ 2048,
62
+ 64,
63
+ OpenSSL::Digest::SHA512.new
64
+ ).unpack('H*')[0]
49
65
  end
50
-
51
66
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bip_mnemonic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sreekanth GS
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-11 00:00:00.000000000 Z
11
+ date: 2019-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rspec
14
+ name: rdoc
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rdoc
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -47,10 +47,10 @@ extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
49
  - lib/bip_mnemonic.rb
50
- - lib/pbkdf2.rb
51
50
  - words/english.txt
52
51
  homepage: http://github.com/sreekanthgs/mnemonic
53
- licenses: []
52
+ licenses:
53
+ - MIT
54
54
  metadata: {}
55
55
  post_install_message:
56
56
  rdoc_options: []
@@ -67,8 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  requirements: []
70
- rubyforge_project:
71
- rubygems_version: 2.4.6
70
+ rubygems_version: 3.0.3
72
71
  signing_key:
73
72
  specification_version: 4
74
73
  summary: BipMnemonic words and seed generator based on BIP-39
@@ -1,118 +0,0 @@
1
- # THIS IS A MINIMALLY MODIFIED IMPLEMENTATION OF PBKDF2, ORIGINALLY IMPLEMENTED BY
2
- # Sam Quigley. ORIGINAL IMPLEMENTATION AVAILABLE AT:
3
- # https://github.com/emerose/pbkdf2-ruby
4
- #
5
- # Copyright (c) 2008 Sam Quigley <quigley@emerose.com>
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy
8
- # of this software and associated documentation files (the "Software"), to deal
9
- # in the Software without restriction, including without limitation the rights
10
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- # copies of the Software, and to permit persons to whom the Software is
12
- # furnished to do so, subject to the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be included in
15
- # all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- # THE SOFTWARE.
24
- #
25
- # This license is sometimes referred to as "The MIT License"
26
-
27
- require 'openssl'
28
-
29
- class PBKDF2
30
- VERSION = "0.0.1"
31
- def self.hex_string(options = {})
32
-
33
- yield self if block_given?
34
-
35
- # Raise errors for unset options, all are mandatory
36
- raise ArgumentError, ":password is not set" if options[:password].nil?
37
- raise ArgumentError, ":salt is not set" if options[:salt].nil?
38
- raise ArgumentError, ":iterations is not set" if options[:iterations].nil?
39
- raise ArgumentError, ":key_length is not set" if options[:key_length].nil?
40
- raise ArgumentError, ":hash_function is not set" if options[:hash_function].nil?
41
-
42
- options[:hash_function] = options[:hash_function].new
43
- validate(options)
44
- options[:key_length] = options[:key_length]/8
45
-
46
- calculate!(options)
47
- end
48
-
49
- def self.validate(options)
50
- raise ArgumentError, "Key is too short (< 1)" if options[:key_length] < 1
51
- raise ArgumentError, "key is too long for hash function" if options[:key_length]/8 > ((2**32 - 1) * options[:hash_function].size)
52
- raise ArgumentError, "iterations can't be less than 1" if options[:iterations] < 1
53
- end
54
-
55
- def self.prf(options, data)
56
- OpenSSL::HMAC.digest(options[:hash_function], options[:password], data)
57
- end
58
-
59
- # this is a translation of the helper function "F" defined in the spec
60
- def self.calculate_block(options, block_num)
61
- # u_1:
62
- u = prf(options, options[:salt]+[block_num].pack("N"))
63
- ret = u
64
- # u_2 through u_c:
65
- 2.upto(options[:iterations]) do
66
- # calculate u_n
67
- u = prf(options, u)
68
- # xor it with the previous results
69
- ret = ret^u
70
- end
71
- ret
72
- end
73
-
74
- # the bit that actually does the calculating
75
- def self.calculate!(options)
76
- # how many blocks we'll need to calculate (the last may be truncated)
77
- blocks_needed = (options[:key_length].to_f / options[:hash_function].size).ceil
78
- # reset
79
- value = ""
80
- # main block-calculating loop:
81
- 1.upto(blocks_needed) do |block_num|
82
- value << calculate_block(options,block_num)
83
- end
84
- # truncate to desired length:
85
- value = value.slice(0,options[:key_length]).unpack("H*").first
86
- value
87
- end
88
-
89
- end
90
-
91
- class String
92
- if RUBY_VERSION >= "1.9"
93
- def xor_impl(other)
94
- result = "".encode("ASCII-8BIT")
95
- o_bytes = other.bytes.to_a
96
- bytes.each_with_index do |c, i|
97
- result << (c ^ o_bytes[i])
98
- end
99
- result
100
- end
101
- else
102
- def xor_impl(other)
103
- result = (0..length-1).collect { |i| self[i] ^ other[i] }
104
- result.pack("C*")
105
- end
106
- end
107
-
108
- private :xor_impl
109
-
110
- def ^(other)
111
- raise ArgumentError, "Can't bitwise-XOR a String with a non-String" \
112
- unless other.kind_of? String
113
- raise ArgumentError, "Can't bitwise-XOR strings of different length" \
114
- unless length == other.length
115
-
116
- xor_impl(other)
117
- end
118
- end