elliptic 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|