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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50c1f0afa4d55fd9b936ddc1ef0c38ede63054432aae99aa2b717ba21bc819c7
4
- data.tar.gz: e9d57e5bfece39941288e66fd9b087d99660dfa25a42e723b69f96f85c690fd0
3
+ metadata.gz: b669851bc198139a145ad4e0fcec669c63e5510836322db51787ceb8d09362c5
4
+ data.tar.gz: 1a125a73561286cf5670085f910e8c37c0ed48c9564400219885a24526dbe0de
5
5
  SHA512:
6
- metadata.gz: 56cc6e7d72f921b61701d6ca2d1d25383b91377607752db4f96a7d12c56881fdfda1bcccfe2177ff8695114de81822ea9fbc8b0ccecfa1546f4c678393b2b933
7
- data.tar.gz: c8ec4acab2b3495b8937bee4e7488d6d3922b31a6ec13473a877ea30249319e0c8eacc4c89062cd76d3e1a4c078c95d36579b2b420b2a55e931ace6be9b69692
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
- ## Public Key Formats
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
 
@@ -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 )
@@ -3,8 +3,8 @@
3
3
 
4
4
  module EC
5
5
 
6
- MAJOR = 0
7
- MINOR = 2
6
+ MAJOR = 1
7
+ MINOR = 0
8
8
  PATCH = 0
9
9
  VERSION = [MAJOR,MINOR,PATCH].join('.')
10
10
 
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.2.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-23 00:00:00.000000000 Z
11
+ date: 2021-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc