Class: MoneyTree::PrivateKey
- Inherits:
-
Key
- Object
- Key
- MoneyTree::PrivateKey
show all
- Defined in:
- lib/money-tree/key.rb
Constant Summary
Constants inherited
from Key
Key::GROUP_NAME, Key::ORDER
Constants included
from Support
Support::BASE58_CHARS, Support::INT32_MAX, Support::INT64_MAX
Instance Attribute Summary
Attributes inherited from Key
#ec_key, #key, #options, #raw_key
Instance Method Summary
collapse
Methods inherited from Key
#to_bytes, #to_i, #valid?
Methods included from Support
#base58_to_int, #bytes_to_hex, #bytes_to_int, #convert_p2wpkh_p2sh, #custom_hash_160, #decode_base58, #decode_base64, #digestify, #encode_base58, #encode_base64, #encode_p2wpkh_p2sh, #from_serialized_base58, #hex_to_bytes, #hex_to_int, #hmac_sha512, #hmac_sha512_hex, #int_to_base58, #int_to_bytes, #int_to_hex, #ripemd160, #sha256, #to_serialized_base58, #to_serialized_bech32
Constructor Details
#initialize(opts = {}) ⇒ PrivateKey
Returns a new instance of PrivateKey.
40
41
42
43
44
45
46
47
48
49
50
|
# File 'lib/money-tree/key.rb', line 40
def initialize(opts = {})
@options = opts
generate
if @options[:key]
@raw_key = @options[:key]
@key = parse_raw_key
import
else
@key = to_hex
end
end
|
Instance Method Details
123
124
125
|
# File 'lib/money-tree/key.rb', line 123
def base64_format?(base64_key = raw_key)
base64_key.length == 44 && base64_key =~ /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/
end
|
#calculate_public_key(opts = {}) ⇒ Object
69
70
71
72
73
74
|
# File 'lib/money-tree/key.rb', line 69
def calculate_public_key(opts = {})
opts[:compressed] = true unless opts[:compressed] == false
group = ec_key.group
group.point_conversion_form = opts[:compressed] ? :compressed : :uncompressed
point = group.generator.mul OpenSSL::BN.new(key, 16)
end
|
109
110
111
|
# File 'lib/money-tree/key.rb', line 109
def compressed_wif_format?
wif_format?(:compressed)
end
|
#data_sequence ⇒ Object
60
61
62
63
64
65
66
67
|
# File 'lib/money-tree/key.rb', line 60
def data_sequence
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(1),
OpenSSL::ASN1::OctetString(OpenSSL::BN.new(key, 16).to_s(2)),
OpenSSL::ASN1::ObjectId(GROUP_NAME, 0, :EXPLICIT),
OpenSSL::ASN1::BitString(calculate_public_key.to_octet_string(:uncompressed), 1, :EXPLICIT),
])
end
|
#from_base64(base64_key = raw_key) ⇒ Object
104
105
106
107
|
# File 'lib/money-tree/key.rb', line 104
def from_base64(base64_key = raw_key)
raise InvalidBase64Format unless base64_format?(base64_key)
decode_base64(base64_key)
end
|
#from_hex(hex = raw_key) ⇒ Object
92
93
94
|
# File 'lib/money-tree/key.rb', line 92
def from_hex(hex = raw_key)
hex
end
|
#from_integer(bignum = raw_key) ⇒ Object
87
88
89
90
|
# File 'lib/money-tree/key.rb', line 87
def from_integer(bignum = raw_key)
int_to_hex(bignum)
end
|
#from_wif(wif = raw_key) ⇒ Object
96
97
98
99
100
101
102
|
# File 'lib/money-tree/key.rb', line 96
def from_wif(wif = raw_key)
compressed = wif.length == 52
validate_wif(wif)
hex = decode_base58(wif)
last_char = compressed ? -11 : -9
hex.slice(2..last_char)
end
|
#generate ⇒ Object
52
53
54
|
# File 'lib/money-tree/key.rb', line 52
def generate
@ec_key = PKey::EC.generate GROUP_NAME
end
|
127
128
129
|
# File 'lib/money-tree/key.rb', line 127
def hex_format?
raw_key.length == 64 && !raw_key[/\H/]
end
|
#import ⇒ Object
56
57
58
|
# File 'lib/money-tree/key.rb', line 56
def import
@ec_key = OpenSSL::PKey::EC.new(data_sequence.to_der)
end
|
#parse_raw_key ⇒ Object
80
81
82
83
84
85
|
# File 'lib/money-tree/key.rb', line 80
def parse_raw_key
result = if raw_key.is_a?(Integer) then from_integer elsif hex_format? then from_hex elsif base64_format? then from_base64 elsif compressed_wif_format? then from_wif elsif uncompressed_wif_format? then from_wif else
raise KeyFormatNotFound
end
result.downcase
end
|
#set_public_key(opts = {}) ⇒ Object
76
77
78
|
# File 'lib/money-tree/key.rb', line 76
def set_public_key(opts = {})
ec_key.public_key = calculate_public_key(opts)
end
|
#to_base64 ⇒ Object
159
160
161
|
# File 'lib/money-tree/key.rb', line 159
def to_base64
encode_base64(to_hex)
end
|
#to_hex ⇒ Object
131
132
133
|
# File 'lib/money-tree/key.rb', line 131
def to_hex
int_to_hex @ec_key.private_key, 64
end
|
#to_s(network: :bitcoin) ⇒ Object
163
164
165
|
# File 'lib/money-tree/key.rb', line 163
def to_s(network: :bitcoin)
to_wif(network: network)
end
|
#to_wif(compressed: true, network: :bitcoin) ⇒ Object
135
136
137
138
139
140
141
142
143
|
# File 'lib/money-tree/key.rb', line 135
def to_wif(compressed: true, network: :bitcoin)
source = NETWORKS[network][:privkey_version] + to_hex
source += NETWORKS[network][:privkey_compression_flag] if compressed
hash = sha256(source)
hash = sha256(hash)
checksum = hash.slice(0..7)
source_with_checksum = source + checksum
encode_base58(source_with_checksum)
end
|
113
114
115
|
# File 'lib/money-tree/key.rb', line 113
def uncompressed_wif_format?
wif_format?(:uncompressed)
end
|
#validate_wif(wif) ⇒ Object
155
156
157
|
# File 'lib/money-tree/key.rb', line 155
def validate_wif(wif)
raise InvalidWIFFormat unless wif_valid?(wif)
end
|
117
118
119
120
121
|
# File 'lib/money-tree/key.rb', line 117
def wif_format?(compression)
length = compression == :compressed ? 52 : 51
wif_prefixes = MoneyTree::NETWORKS.map { |k, v| v["#{compression}_wif_chars".to_sym] }.flatten
raw_key.length == length && wif_prefixes.include?(raw_key.slice(0))
end
|
#wif_valid?(wif) ⇒ Boolean
145
146
147
148
149
150
151
152
153
|
# File 'lib/money-tree/key.rb', line 145
def wif_valid?(wif)
hex = decode_base58(wif)
checksum = hex.chars.to_a.pop(8).join
source = hex.slice(0..-9)
hash = sha256(source)
hash = sha256(hash)
hash_checksum = hash.slice(0..7)
checksum == hash_checksum
end
|