derivator 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +21 -0
- data/README.md +115 -0
- data/Rakefile +6 -0
- data/bin/console +12 -0
- data/derivator.gemspec +27 -0
- data/exe/derivator_key_from_parent +17 -0
- data/exe/derivator_key_from_seed +15 -0
- data/exe/derivator_mnemonic +12 -0
- data/exe/derivator_public_from_private +15 -0
- data/exe/derivator_seed_from_mnemonic +14 -0
- data/lib/derivator/key.rb +300 -0
- data/lib/derivator/mnemonic.rb +51 -0
- data/lib/derivator/refinements.rb +37 -0
- data/lib/derivator/word_lists/english.txt +2048 -0
- data/lib/derivator.rb +10 -0
- metadata +98 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
module Derivator
|
2
|
+
# {https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki BIP39} mnemonic generation.
|
3
|
+
class Mnemonic
|
4
|
+
# Word list (ordered). Only English is supported.
|
5
|
+
WORDS = File.readlines(__dir__ + '/word_lists/english.txt', chomp: true)
|
6
|
+
|
7
|
+
SEED_ITERATIONS = 2048
|
8
|
+
SEED_KEY_LENGTH = 64
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# Generates 128 bits of random
|
12
|
+
#
|
13
|
+
# @return [String] 16 random bytes
|
14
|
+
def random_bytes
|
15
|
+
SecureRandom.random_bytes(128 / 8) # 128 bits
|
16
|
+
end
|
17
|
+
|
18
|
+
# Generates mnemonic.
|
19
|
+
#
|
20
|
+
# @param bytes [String] bytes to generate mnemonic from
|
21
|
+
# @return [String] mnemonic (12 words)
|
22
|
+
def generate(bytes = random_bytes)
|
23
|
+
checksum = OpenSSL::Digest::SHA256.new(bytes).digest[0..0]
|
24
|
+
checksum_bits = checksum[0..0].unpack('B4').first # first 4 bits
|
25
|
+
bits = bytes.unpack('B*').first + checksum_bits
|
26
|
+
mnemonic = bits.chars.
|
27
|
+
each_slice(11).
|
28
|
+
map(&:join).
|
29
|
+
map { |x| x.to_i(2) }.
|
30
|
+
map { |x| WORDS[x] }.
|
31
|
+
join(' ')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Generates master seed.
|
35
|
+
#
|
36
|
+
# @param mnemonic [String] mnemonic (12 words) to generate seed from
|
37
|
+
# @param password [String] password
|
38
|
+
def seed(mnemonic, password = '')
|
39
|
+
salt = "mnemonic#{password}"
|
40
|
+
result_bytes = OpenSSL::KDF.pbkdf2_hmac(
|
41
|
+
mnemonic,
|
42
|
+
salt: salt,
|
43
|
+
iterations: SEED_ITERATIONS,
|
44
|
+
length: SEED_KEY_LENGTH,
|
45
|
+
hash: 'SHA512'
|
46
|
+
)
|
47
|
+
result_bytes.unpack('H*').first
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Derivator
|
2
|
+
# Internally used refinements
|
3
|
+
module Refinements
|
4
|
+
refine String do
|
5
|
+
def to_hex
|
6
|
+
unpack('H*').first
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_hex
|
10
|
+
[self].pack('H*')
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_base64
|
14
|
+
Base64.encode64(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def from_base64
|
18
|
+
Base64.decode64(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_der
|
22
|
+
OpenSSL::ASN1.decode(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_der_octet_string
|
26
|
+
OpenSSL::ASN1::OctetString.new(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns BIP-0032 key identifier, interpreting string as binary key
|
30
|
+
def hash160
|
31
|
+
# https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#key-identifiers
|
32
|
+
r = OpenSSL::Digest::SHA256.new(self).digest
|
33
|
+
OpenSSL::Digest::RIPEMD160.new(r).digest
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|