letscert 0.4.5 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9713b8f8c57715a49c9a47ee496be861b140605e
4
- data.tar.gz: b066af17d583c2a87e246729fe4ec52478b529b2
3
+ metadata.gz: 52add53a57fa00b0778f2a493f17f60c52c66420
4
+ data.tar.gz: 918a0428e5ec2c2c7f05c29eb41fcd60cd43a5f6
5
5
  SHA512:
6
- metadata.gz: cf1ee72bfb5f7e348ab4dbe35a674e2c723e8004f241a28a705787d9947ab1d1abe1fd0b8788d84f3b7c8734ccd34f6cc6b44b1513f1f5c239b788506a757410
7
- data.tar.gz: b2bf80554770b4545bf343b12676412b6074979dc92d6e9966ac7bdc9922bef503afa201dd538d20f187f7146f4388ff9ecadab073aec0019dcd824e4f6963bd
6
+ metadata.gz: 7a5017b39b842d751148c95666fc2372c4af7158c2dada7ad5b5d4dd6e53fe1d38582090827271611fc7ddb94c1e8c8473f0ed6837f855e3c66eedca38b544b4
7
+ data.tar.gz: 9c9462d83f3b2fecba4c0d3ef73760257d4814df0aeb8aafeb177f096e34fec2ed896f8cea923b37ed358592c1b345ca8de1cd03c93b6f43df0dc44647502987
checksums.yaml.gz.sig CHANGED
Binary file
data/.travis.yml CHANGED
@@ -2,7 +2,8 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1
4
4
  - 2.2
5
- - 2.3.1
5
+ - 2.3.3
6
+ - 2.4.0
6
7
 
7
8
  install:
8
9
  - gem install bundler
data/letscert.gemspec CHANGED
@@ -23,10 +23,10 @@ EOF
23
23
 
24
24
  s.required_ruby_version = '>= 2.1.0'
25
25
 
26
- s.add_dependency 'acme-client', '~>0.5.0'
26
+ s.add_dependency 'acme-client', '~>0.5.5'
27
27
 
28
28
  s.add_development_dependency 'bundler', '~> 1.12'
29
- s.add_development_dependency 'rake', '~> 10.0'
29
+ s.add_development_dependency 'rake', '~> 11.0'
30
30
  s.add_development_dependency 'rspec', '~>3.4'
31
31
  s.add_development_dependency 'vcr', '~>3.0'
32
32
  s.add_development_dependency 'yard', '~>0.8'
@@ -21,6 +21,7 @@
21
21
  # SOFTWARE.
22
22
  require 'acme-client'
23
23
  require_relative 'loggable'
24
+ require_relative 'patched_ec_pkey'
24
25
 
25
26
  # rubocop:disable Metrics/ClassLength, Style/MultilineBlockLayout
26
27
  # rubocop:disable Style/BlockEndNewline, Style/BlockDelimiters
@@ -82,7 +83,7 @@ module LetsCert
82
83
  else
83
84
  logger.info { 'Generate new private key' }
84
85
  generate_certificate options[:roots].keys,
85
- options[:cert_key_size]
86
+ options
86
87
  end
87
88
 
88
89
  options[:files] ||= []
@@ -299,6 +300,52 @@ module LetsCert
299
300
  end
300
301
  end
301
302
 
303
+ # Generate a key from options
304
+ # @param [Hash] options +:cert_ecdsa+ and +:cert_rsa+ are mutually
305
+ # exclusive.
306
+ # @option options [Integer] :cert_ecdsa curve for which generate a cert
307
+ # @option options [Integer] :cert_rsa key size to generate a RSA key
308
+ # @return [OpenSSL::Pkey::PKey]
309
+ # @raise [Error]
310
+ def generate_key(options)
311
+ if options[:cert_ecdsa] and options[:cert_rsa]
312
+ raise Error, 'cannot generate a ECDSA key and a RSA key in one shot'
313
+ end
314
+
315
+ if options[:cert_ecdsa]
316
+ generate_ecdsa_key options[:cert_ecdsa]
317
+ else
318
+ OpenSSL::PKey::RSA.generate options[:cert_rsa]
319
+ end
320
+ end
321
+
322
+ # Generate a ECDSA key
323
+ # @param [String] curve curve name
324
+ # @return [OpenSSL::PKey::EC]
325
+ def generate_ecdsa_key(curve)
326
+ key = (PatchedECPkey.needed? ? PatchedECPkey : OpenSSL::PKey::EC).new
327
+ key.group = OpenSSL::PKey::EC::Group.new(curve)
328
+ key.generate_key
329
+ rescue OpenSSL::PKey::EC::Group::Error => ex
330
+ raise unless ex.message =~ /^unknown curve/
331
+ msg = "unknown curve. Supported curves are:\n"
332
+ msg << secure_curves.join("\n")
333
+ raise Error, msg
334
+ end
335
+
336
+ # Return array of secure curve names
337
+ # @return [Array<String>]
338
+ def secure_curves
339
+ curves = OpenSSL::PKey::EC.builtin_curves.map { |ary| '%-20s%s' % ary }
340
+ # Remove all binary curves, and prime curves which field is less than
341
+ # 256 bits
342
+ curves.reject! do |el|
343
+ el =~ /binary/ or (el =~ /(\d+) bit/ and $1.to_i < 256)
344
+ end
345
+
346
+ curves
347
+ end
348
+
302
349
  # Generate new certificate for given domains with existing private key
303
350
  # @param [Array<String>] domains
304
351
  # @param [OpenSSL::PKey::PKey] pkey private key to use
@@ -315,10 +362,11 @@ module LetsCert
315
362
 
316
363
  # Generate new certificate for given domains
317
364
  # @param [Array<String>] domains
318
- # @param [Integer] pkey_size size in bits for private key to generate
365
+ # @param [Hash] options option hash containing +:cert_ecdsa+, +:cert_rsa+
366
+ # or +:cert_key_size+ key.
319
367
  # @return [OpenSSL::PKey::PKey] generated private key
320
- def generate_certificate(domains, pkey_size)
321
- pkey = OpenSSL::PKey::RSA.generate(pkey_size)
368
+ def generate_certificate(domains, options)
369
+ pkey = generate_key(options)
322
370
  generate_certificate_from_pkey domains, pkey
323
371
  end
324
372
 
@@ -0,0 +1,16 @@
1
+ require 'openssl'
2
+
3
+ module LetsCert
4
+ # Ruby < 2.4 has bugs in OpenSSL. This class patches these bugs.
5
+ # @author Sylvain Daubert
6
+ class PatchedECPkey < OpenSSL::PKey::EC
7
+ alias :private? :private_key?
8
+ alias :public? :public_key?
9
+
10
+ # Say if {PatchedECPkey} is needed
11
+ # @return [Boolean]
12
+ def self.needed?
13
+ RbConfig::CONFIG['MAJOR'] == '2' && RbConfig::CONFIG['MINOR'].to_i < 4
14
+ end
15
+ end
16
+ end
@@ -42,6 +42,9 @@ module LetsCert
42
42
  # Exit value for error(s)
43
43
  RETURN_ERROR = 2
44
44
 
45
+ # Default key size for RSA certificates
46
+ RSA_DEFAULT_KEY_SIZE = 2048
47
+
45
48
  # Get options
46
49
  # @return [Hash]
47
50
  attr_reader :options
@@ -62,7 +65,6 @@ module LetsCert
62
65
  verbose: 0,
63
66
  domains: [],
64
67
  files: [],
65
- cert_key_size: 2048,
66
68
  valid_min: ValidTime.new('30d'),
67
69
  account_key_size: 4096,
68
70
  tos_sha256: '33d233c8ab558ba6c8ebc370a509acdded8b80e5d587aa5d192193f3' \
@@ -150,10 +152,21 @@ module LetsCert
150
152
  @options[:files] << file
151
153
  end
152
154
 
155
+ opts.on('--cert-ecdsa CURVE', String,
156
+ 'Generate ECDSA certificate on CURVE') do |curve|
157
+ @options[:cert_ecdsa] = curve
158
+ end
159
+
160
+ opts.on('--cert-rsa BITS', Integer,
161
+ 'Generate RSA certificate with a BITS-bit',
162
+ 'private key') do |bits|
163
+ @options[:cert_rsa] = bits
164
+ end
153
165
  opts.on('--cert-key-size BITS', Integer,
154
166
  'Certificate key size in bits',
155
- "(default: #{@options[:cert_key_size]})") do |bits|
156
- @options[:cert_key_size] = bits
167
+ '(equivalent to --cert-rsa)',
168
+ "(default: #{RSA_DEFAULT_KEY_SIZE})") do |bits|
169
+ @options[:cert_rsa] = bits
157
170
  end
158
171
 
159
172
  opts.accept(ValidTime) do |valid_time|
@@ -207,6 +220,7 @@ module LetsCert
207
220
 
208
221
  @opt_parser.parse!
209
222
  compute_roots
223
+ select_default_cert_type_if_none_specified
210
224
  end
211
225
 
212
226
  # Check all components are covered by plugins
@@ -354,6 +368,12 @@ module LetsCert
354
368
  @options[:roots] = roots
355
369
  end
356
370
 
371
+ def select_default_cert_type_if_none_specified
372
+ if @options[:cert_ecdsa].nil? and @options[:cert_rsa].nil?
373
+ @options[:cert_rsa] = RSA_DEFAULT_KEY_SIZE
374
+ end
375
+ end
376
+
357
377
  def persisted_data
358
378
  persisted = IOPlugin.empty_data
359
379
  @options[:files].each do |file|
@@ -1,6 +1,6 @@
1
1
  module LetsCert
2
2
 
3
3
  # Letscert version number
4
- VERSION = '0.4.5'.freeze
4
+ VERSION = '0.5.0'.freeze
5
5
 
6
6
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: letscert
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Daubert
@@ -31,7 +31,7 @@ cert_chain:
31
31
  dMi8WSKt03lfzyxIqZseBwVYYn+XMlzCcJLXCUgZXHcBRRRDH5wGDqOqXjL25b2O
32
32
  6m3JJngqkCFrOw==
33
33
  -----END CERTIFICATE-----
34
- date: 2016-11-21 00:00:00.000000000 Z
34
+ date: 2017-04-18 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: acme-client
@@ -39,14 +39,14 @@ dependencies:
39
39
  requirements:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: 0.5.0
42
+ version: 0.5.5
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: 0.5.0
49
+ version: 0.5.5
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: bundler
52
52
  requirement: !ruby/object:Gem::Requirement
@@ -67,14 +67,14 @@ dependencies:
67
67
  requirements:
68
68
  - - "~>"
69
69
  - !ruby/object:Gem::Version
70
- version: '10.0'
70
+ version: '11.0'
71
71
  type: :development
72
72
  prerelease: false
73
73
  version_requirements: !ruby/object:Gem::Requirement
74
74
  requirements:
75
75
  - - "~>"
76
76
  - !ruby/object:Gem::Version
77
- version: '10.0'
77
+ version: '11.0'
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: rspec
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -162,6 +162,7 @@ files:
162
162
  - lib/letscert/io_plugins/key_file.rb
163
163
  - lib/letscert/io_plugins/openssl_io_plugin.rb
164
164
  - lib/letscert/loggable.rb
165
+ - lib/letscert/patched_ec_pkey.rb
165
166
  - lib/letscert/runner.rb
166
167
  - lib/letscert/runner/logger_formatter.rb
167
168
  - lib/letscert/valid_time.rb
@@ -186,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
187
  version: '0'
187
188
  requirements: []
188
189
  rubyforge_project:
189
- rubygems_version: 2.5.1
190
+ rubygems_version: 2.5.2
190
191
  signing_key:
191
192
  specification_version: 4
192
193
  summary: letscert, a simple Let's Encrypt client
metadata.gz.sig CHANGED
Binary file