bip_mnemonic 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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