elliptic 0.2.0 → 1.0.0
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.
- checksums.yaml +4 -4
- data/README.md +109 -1
- data/lib/elliptic.rb +3 -145
- data/lib/elliptic/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b669851bc198139a145ad4e0fcec669c63e5510836322db51787ceb8d09362c5
|
|
4
|
+
data.tar.gz: 1a125a73561286cf5670085f910e8c37c0ed48c9564400219885a24526dbe0de
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f1ed708148cf5c8dd47ab00c22dfeee9ce43f3967c1626b7f1ed90947d0fb01512e2dbbd6ce0e43ef49a913a59abec48c80c86ba95854d89d62f9061c0daaa8
|
|
7
|
+
data.tar.gz: bb86040e5624540f3f66368b0f1c1759fe2d0e1eaf0bc2c882f0c14d0e72b4cb685de6baebd84008262fb5f07cfe9775fa40394bf79fcef0142642113bab26ad
|
data/README.md
CHANGED
|
@@ -194,7 +194,9 @@ That's all the magic.
|
|
|
194
194
|
|
|
195
195
|
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
### Private / Public Key Formats
|
|
198
|
+
|
|
199
|
+
#### Intro
|
|
198
200
|
|
|
199
201
|
To get the all-in-one-string
|
|
200
202
|
public key from a point with the coordinates x and y
|
|
@@ -237,6 +239,112 @@ point.to_s( :compressed )
|
|
|
237
239
|
#=> "02e37648435c60dcd181b3d41d50857ba5b5abebe279429aa76558f6653f1658f2"
|
|
238
240
|
```
|
|
239
241
|
|
|
242
|
+
#### PEM, DER, BASE64(DER)
|
|
243
|
+
|
|
244
|
+
**Export**
|
|
245
|
+
|
|
246
|
+
To export a private or public key to
|
|
247
|
+
the Privacy Enhanced Mail (PEM) format use `to_pem`:
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
``` ruby
|
|
251
|
+
private_key = EC::PrivateKey.generate
|
|
252
|
+
private_key.to_pem
|
|
253
|
+
#=> "-----BEGIN EC PRIVATE KEY-----
|
|
254
|
+
# MHQCAQEEIDIWkCIC58Yo1E5noSiXbHdR/8zUqB+vvTK4nSk8tZ1RoAcGBSuBBAAK
|
|
255
|
+
# oUQDQgAEoll8rYerfDH4q6nT1miTZZ315a8BFsKA13Z8Zif5Mh+qavIr/6HpI/Kq
|
|
256
|
+
# Q0bnuOZiCD9gpEIWo7VGN8wJgcu6ZA==
|
|
257
|
+
# -----END EC PRIVATE KEY-----"
|
|
258
|
+
|
|
259
|
+
public_key = private_key.public_key
|
|
260
|
+
public_key.to_pem
|
|
261
|
+
#=> "-----BEGIN PUBLIC KEY-----
|
|
262
|
+
# MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEoll8rYerfDH4q6nT1miTZZ315a8BFsKA
|
|
263
|
+
# 13Z8Zif5Mh+qavIr/6HpI/KqQ0bnuOZiCD9gpEIWo7VGN8wJgcu6ZA==
|
|
264
|
+
# -----END PUBLIC KEY-----"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
To export a private or public key to
|
|
268
|
+
the (binary) Distinguished Encoding Rules (DER)
|
|
269
|
+
in ASN.1 format use `to_der`:
|
|
270
|
+
|
|
271
|
+
``` ruby
|
|
272
|
+
private_key.to_der
|
|
273
|
+
#=> "\xA1D\x03B\x00\x04\xA2Y|\xAD\x87\xAB|1
|
|
274
|
+
# \xF8\xAB\xA9\xD3\xD6h\x93e\x9D\xF5\xE5\xAF\x01\x16\xC2\x80
|
|
275
|
+
# \xD7v|f'\xF92\x1F\xAAj\xF2+\xFF\xA1\xE9#\xF2\xAACF\xE7\xB8
|
|
276
|
+
# \xE6b\b?`\xA4B\x16\xA3\xB5F7\xCC\t\x81\xCB\xBAd"
|
|
277
|
+
|
|
278
|
+
public_key = private_key.public_key
|
|
279
|
+
public_key.to_der
|
|
280
|
+
#=> "0V0\x10\x06\a*\x86H\xCE=\x02\x01\x06\x05+\x81\x04\x00
|
|
281
|
+
# \x03B\x00\x04\xA2Y|\xAD\x87\xAB|1\xF8\xAB\xA9
|
|
282
|
+
# \xD3\xD6h\x93e\x9D\xF5\xE5\xAF\x01\x16\xC2\x80\xD7v|f'\xF92
|
|
283
|
+
# \x1F\xAAj\xF2+\xFF\xA1\xE9#\xF2\xAACF\xE7\xB8\xE6b
|
|
284
|
+
# \b?`\xA4B\x16\xA3\xB5F7\xCC\t\x81\xCB\xBAd"
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
To export a private or public key to
|
|
288
|
+
the Base64-encoded Distinguished Encoding Rules (DER)
|
|
289
|
+
in ASN.1 format use `to_base64`:
|
|
290
|
+
|
|
291
|
+
``` ruby
|
|
292
|
+
private_key.to_base64
|
|
293
|
+
#=> "MHQCAQEEIDIWkCIC58Yo1E5noSiXbHdR/8zUqB+vvTK4nSk8tZ1RoAcGBSuBBAAK
|
|
294
|
+
# oUQDQgAEoll8rYerfDH4q6nT1miTZZ315a8BFsKA13Z8Zif5Mh+qavIr/6HpI/Kq
|
|
295
|
+
# Q0bnuOZiCD9gpEIWo7VGN8wJgcu6ZA=="
|
|
296
|
+
|
|
297
|
+
public_key = private_key.public_key
|
|
298
|
+
public_key.to_base64
|
|
299
|
+
#=> "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEoll8rYerfDH4q6nT1miTZZ315a8BFsKA
|
|
300
|
+
# 13Z8Zif5Mh+qavIr/6HpI/KqQ0bnuOZiCD9gpEIWo7VGN8wJgcu6ZA=="
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Import**
|
|
304
|
+
|
|
305
|
+
To import a private or public key
|
|
306
|
+
in the PEM or DER format use the all-in-one convenience constructor:
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
``` ruby
|
|
310
|
+
private_key = EC::PrivateKey.new( "-----BEGIN EC PRIVATE KEY-----
|
|
311
|
+
MHQCAQEEIDIWkCIC58Yo1E5noSiXbHdR/8zUqB+vvTK4nSk8tZ1RoAcGBSuBBAAK
|
|
312
|
+
oUQDQgAEoll8rYerfDH4q6nT1miTZZ315a8BFsKA13Z8Zif5Mh+qavIr/6HpI/Kq
|
|
313
|
+
Q0bnuOZiCD9gpEIWo7VGN8wJgcu6ZA==
|
|
314
|
+
-----END EC PRIVATE KEY-----" )
|
|
315
|
+
|
|
316
|
+
public_key = EC::PublicKey.new( "-----BEGIN PUBLIC KEY-----
|
|
317
|
+
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEoll8rYerfDH4q6nT1miTZZ315a8BFsKA
|
|
318
|
+
13Z8Zif5Mh+qavIr/6HpI/KqQ0bnuOZiCD9gpEIWo7VGN8wJgcu6ZA==
|
|
319
|
+
-----END PUBLIC KEY-----" )
|
|
320
|
+
|
|
321
|
+
## or
|
|
322
|
+
|
|
323
|
+
private_key = EC::PrivateKey.new( "\xA1D\x03B\x00\x04\xA2Y|\xAD\x87\xAB|1
|
|
324
|
+
\xF8\xAB\xA9\xD3\xD6h\x93e\x9D\xF5\xE5\xAF\x01\x16\xC2\x80
|
|
325
|
+
\xD7v|f'\xF92\x1F\xAAj\xF2+\xFF\xA1\xE9#\xF2\xAACF\xE7\xB8
|
|
326
|
+
\xE6b\b?`\xA4B\x16\xA3\xB5F7\xCC\t\x81\xCB\xBAd".b )
|
|
327
|
+
|
|
328
|
+
public_key = EC::PublicKey.new( "0V0\x10\x06\a*\x86H\xCE=\x02\x01\x06\x05+\x81\x04\x00
|
|
329
|
+
\x03B\x00\x04\xA2Y|\xAD\x87\xAB|1\xF8\xAB\xA9
|
|
330
|
+
\xD3\xD6h\x93e\x9D\xF5\xE5\xAF\x01\x16\xC2\x80\xD7v|f'\xF92
|
|
331
|
+
\x1F\xAAj\xF2+\xFF\xA1\xE9#\xF2\xAACF\xE7\xB8\xE6b
|
|
332
|
+
\b?`\xA4B\x16\xA3\xB5F7\xCC\t\x81\xCB\xBAd".b )
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
or use the decode/from helper:
|
|
336
|
+
|
|
337
|
+
``` ruby
|
|
338
|
+
private_key = EC::PrivateKey.decode_pem( ... ) # or from_pem( ... )
|
|
339
|
+
EC::PrivateKey.decode_der( ... ) # or from_der( ... )
|
|
340
|
+
EC::PrivateKey.decode_base64( ... ) # or from_base64( ... )
|
|
341
|
+
|
|
342
|
+
public_key = EC::PublicKey.decode_pem( ... ) # or from_pem( ... )
|
|
343
|
+
EC::PublicKey.decode_der( ... ) # or from_der( ... )
|
|
344
|
+
EC::PublicKey.decode_base64( ... ) # or from_base64( ... )
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
|
|
240
348
|
|
|
241
349
|
That's it.
|
|
242
350
|
|
data/lib/elliptic.rb
CHANGED
|
@@ -5,39 +5,14 @@ require 'openssl'
|
|
|
5
5
|
|
|
6
6
|
## our own code
|
|
7
7
|
require 'elliptic/version' # note: let version always go first
|
|
8
|
+
require 'elliptic/private_key'
|
|
9
|
+
require 'elliptic/public_key'
|
|
10
|
+
require 'elliptic/signature'
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
module EC
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class Signature
|
|
16
|
-
|
|
17
|
-
def self.decode_der( der )
|
|
18
|
-
asn1 = OpenSSL::ASN1.decode(der )
|
|
19
|
-
r = asn1.value[0].value.to_i
|
|
20
|
-
s = asn1.value[1].value.to_i
|
|
21
|
-
new(r, s)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
attr_reader :r, :s
|
|
25
|
-
def initialize(r, s)
|
|
26
|
-
@r, @s = r, s
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def to_der
|
|
30
|
-
asn1 = OpenSSL::ASN1::Sequence.new [
|
|
31
|
-
OpenSSL::ASN1::Integer.new( @r ),
|
|
32
|
-
OpenSSL::ASN1::Integer.new( @s ),
|
|
33
|
-
]
|
|
34
|
-
asn1.to_der
|
|
35
|
-
end
|
|
36
|
-
end ## class Signature
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
16
|
## "cached" / available groups for now include:
|
|
42
17
|
GROUP = {
|
|
43
18
|
## todo/check: is there a more direct way to get a group object?
|
|
@@ -93,123 +68,6 @@ module EC
|
|
|
93
68
|
|
|
94
69
|
|
|
95
70
|
|
|
96
|
-
|
|
97
|
-
class PublicKey
|
|
98
|
-
def self.convert( *args, **kwargs )
|
|
99
|
-
if args.size==1 && args[0].is_a?( PublicKey )
|
|
100
|
-
args[0] ## pass through as is (already a public key)
|
|
101
|
-
else
|
|
102
|
-
new( *args, group: kwargs[:group] )
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def initialize( *args, group: nil )
|
|
109
|
-
point = if args.size == 2 ## assume (x,y) raw integer points
|
|
110
|
-
@pt = Point.new( *args, group: group )
|
|
111
|
-
@pt.to_ec_point ## convert point to openssl (native) class
|
|
112
|
-
else
|
|
113
|
-
## "restore" public key (only) from point for verify
|
|
114
|
-
## - OpenSSL::PKey::EC::Point ## assume public key only (restore pkey object for verify?)
|
|
115
|
-
## - Point
|
|
116
|
-
if args[0].is_a?( Point )
|
|
117
|
-
@pt = args[0]
|
|
118
|
-
@pt.to_ec_point
|
|
119
|
-
else
|
|
120
|
-
args[0] ## assume it is already OpenSSL::PKey::EC::Point
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
## note: (auto)get group from point
|
|
125
|
-
@pkey = OpenSSL::PKey::EC.new( point.group )
|
|
126
|
-
@pkey.public_key = point
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def group() @pkey.group; end
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def point
|
|
133
|
-
## cache returned point - why? why not?
|
|
134
|
-
@pt ||= Point.new( @pkey.public_key )
|
|
135
|
-
@pt
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def verify?( message, signature )
|
|
141
|
-
signature_der = signature.to_der
|
|
142
|
-
@pkey.dsa_verify_asn1( message, signature_der )
|
|
143
|
-
end
|
|
144
|
-
alias_method :valid_signature?, :verify?
|
|
145
|
-
|
|
146
|
-
## helpers for debugging
|
|
147
|
-
def to_text() @pkey.to_text; end
|
|
148
|
-
def public?() @pkey.public?; end ## todo/check: keep - needed? - why? why not?
|
|
149
|
-
end # class PublicKey
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class PrivateKey
|
|
155
|
-
def self.convert( *args, **kwargs )
|
|
156
|
-
if args.size==1 && args[0].is_a?( PrivateKey )
|
|
157
|
-
args[0] ## pass through as is (alread a private key)
|
|
158
|
-
else
|
|
159
|
-
new( args[0], group: kwargs[:group] )
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
def self.generate( group: nil ) new( group: group ); end
|
|
165
|
-
|
|
166
|
-
def initialize( input=nil, group: nil )
|
|
167
|
-
ec_group = GROUP[ group || 'secp256k1' ]
|
|
168
|
-
@pkey = OpenSSL::PKey::EC.new( ec_group )
|
|
169
|
-
|
|
170
|
-
if input.nil? ## auto-generate new key
|
|
171
|
-
@pkey.generate_key
|
|
172
|
-
else
|
|
173
|
-
num = if input.is_a?( String ) ## assume hex string
|
|
174
|
-
input.to_i( 16 )
|
|
175
|
-
else ## assume integer
|
|
176
|
-
input
|
|
177
|
-
end
|
|
178
|
-
@pkey.private_key = OpenSSL::BN.new( num )
|
|
179
|
-
## auto-calculate public key too
|
|
180
|
-
@pkey.public_key = @pkey.group.generator.mul( @pkey.private_key )
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def to_i() @pkey.private_key.to_i; end
|
|
185
|
-
## todo/check/fix: make it always a 32 byte (64 hex chars) string
|
|
186
|
-
## even with leading zeros !!! - why? why not?
|
|
187
|
-
def to_s() @pkey.private_key.to_i.to_s(16); end
|
|
188
|
-
|
|
189
|
-
def group() @pkey.group; end
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
def public_key
|
|
193
|
-
## cache returned public key - why? why not?
|
|
194
|
-
@pub ||= PublicKey.new( @pkey.public_key )
|
|
195
|
-
@pub
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
def sign( message )
|
|
200
|
-
signature_der = @pkey.dsa_sign_asn1( message )
|
|
201
|
-
Signature.decode_der( signature_der )
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
## helpers for debugging
|
|
205
|
-
def to_text() @pkey.to_text; end
|
|
206
|
-
def private?() @pkey.private?; end ## todo/check: keep - needed? - why? why not?
|
|
207
|
-
end # class PrivateKey
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
71
|
def self.sign( message, priv_key )
|
|
214
72
|
signer = PrivateKey.convert( priv_key )
|
|
215
73
|
signer.sign( message )
|
data/lib/elliptic/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: elliptic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gerald Bauer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-01-
|
|
11
|
+
date: 2021-01-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rdoc
|