certificate_authority 0.1.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +3 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -8
- data/Gemfile.lock +71 -27
- data/README.rdoc +184 -89
- data/Rakefile +6 -41
- data/certificate_authority.gemspec +22 -81
- data/lib/certificate_authority.rb +7 -6
- data/lib/certificate_authority/certificate.rb +151 -71
- data/lib/certificate_authority/certificate_revocation_list.rb +46 -26
- data/lib/certificate_authority/core_extensions.rb +46 -0
- data/lib/certificate_authority/distinguished_name.rb +84 -17
- data/lib/certificate_authority/extensions.rb +483 -96
- data/lib/certificate_authority/key_material.rb +75 -21
- data/lib/certificate_authority/ocsp_handler.rb +99 -29
- data/lib/certificate_authority/pkcs11_key_material.rb +13 -15
- data/lib/certificate_authority/revocable.rb +14 -0
- data/lib/certificate_authority/serial_number.rb +18 -5
- data/lib/certificate_authority/signing_entity.rb +5 -7
- data/lib/certificate_authority/signing_request.rb +91 -0
- data/lib/certificate_authority/validations.rb +31 -0
- data/lib/certificate_authority/version.rb +3 -0
- metadata +96 -94
- data/VERSION.yml +0 -5
- data/spec/spec_helper.rb +0 -4
- data/spec/units/certificate_authority_spec.rb +0 -4
- data/spec/units/certificate_revocation_list_spec.rb +0 -68
- data/spec/units/certificate_spec.rb +0 -351
- data/spec/units/distinguished_name_spec.rb +0 -38
- data/spec/units/extensions_spec.rb +0 -53
- data/spec/units/key_material_spec.rb +0 -96
- data/spec/units/ocsp_handler_spec.rb +0 -104
- data/spec/units/serial_number_spec.rb +0 -20
- data/spec/units/signing_entity_spec.rb +0 -4
- data/spec/units/units_helper.rb +0 -1
data/Rakefile
CHANGED
@@ -1,35 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'rspec/core/rake_task'
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "rubocop/rake_task"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
rescue Bundler::BundlerError => e
|
9
|
-
$stderr.puts e.message
|
10
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
-
exit e.status_code
|
12
|
-
end
|
13
|
-
|
14
|
-
require 'rake'
|
15
|
-
|
16
|
-
desc 'Default: run specs.'
|
17
|
-
task :default => :spec
|
18
|
-
|
19
|
-
require 'jeweler'
|
20
|
-
Jeweler::Tasks.new do |gem|
|
21
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
22
|
-
gem.name = "certificate_authority"
|
23
|
-
gem.homepage = "http://github.com/cchandler/certificate_authority"
|
24
|
-
gem.license = "MIT"
|
25
|
-
gem.summary = 'Ruby gem for managing the core functions outlined in RFC-3280 for PKI'
|
26
|
-
# gem.description = ''
|
27
|
-
gem.email = "chris@flatterline.com"
|
28
|
-
gem.authors = ["Chris Chandler"]
|
29
|
-
|
30
|
-
# gem.add_dependency('activemodel', '3.0.6')
|
31
|
-
end
|
32
|
-
Jeweler::RubygemsDotOrgTasks.new
|
5
|
+
desc "Default: run specs."
|
6
|
+
task default: %i[spec]
|
33
7
|
|
34
8
|
task :spec do
|
35
9
|
Rake::Task["spec:units"].invoke
|
@@ -38,15 +12,6 @@ end
|
|
38
12
|
namespace :spec do
|
39
13
|
desc "Run unit specs."
|
40
14
|
RSpec::Core::RakeTask.new(:units) do |t|
|
41
|
-
t.rspec_opts = [
|
15
|
+
t.rspec_opts = ["--colour --format progress --tag ~pkcs11"]
|
42
16
|
end
|
43
|
-
|
44
|
-
desc "Run integration specs."
|
45
|
-
RSpec::Core::RakeTask.new(:integrations) do |t|
|
46
|
-
t.rspec_opts = ['--colour --format progress']
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
RSpec::Core::RakeTask.new(:doc) do |t|
|
51
|
-
t.rspec_opts = ['--format specdoc ']
|
52
17
|
end
|
@@ -1,87 +1,28 @@
|
|
1
|
-
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
1
|
+
require File.expand_path("lib/certificate_authority/version", __dir__)
|
5
2
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "certificate_authority"
|
5
|
+
spec.version = CertificateAuthority::VERSION
|
6
|
+
spec.authors = ["Chris Chandler"]
|
7
|
+
spec.email = ["squanderingtime@gmail.com"]
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
s.email = %q{chris@flatterline.com}
|
14
|
-
s.extra_rdoc_files = [
|
15
|
-
"README.rdoc"
|
16
|
-
]
|
17
|
-
s.files = [
|
18
|
-
"Gemfile",
|
19
|
-
"Gemfile.lock",
|
20
|
-
"README.rdoc",
|
21
|
-
"Rakefile",
|
22
|
-
"VERSION.yml",
|
23
|
-
"certificate_authority.gemspec",
|
24
|
-
"lib/certificate_authority.rb",
|
25
|
-
"lib/certificate_authority/certificate.rb",
|
26
|
-
"lib/certificate_authority/certificate_revocation_list.rb",
|
27
|
-
"lib/certificate_authority/distinguished_name.rb",
|
28
|
-
"lib/certificate_authority/extensions.rb",
|
29
|
-
"lib/certificate_authority/key_material.rb",
|
30
|
-
"lib/certificate_authority/ocsp_handler.rb",
|
31
|
-
"lib/certificate_authority/pkcs11_key_material.rb",
|
32
|
-
"lib/certificate_authority/serial_number.rb",
|
33
|
-
"lib/certificate_authority/signing_entity.rb",
|
34
|
-
"lib/tasks/certificate_authority.rake",
|
35
|
-
"spec/spec_helper.rb",
|
36
|
-
"spec/units/certificate_authority_spec.rb",
|
37
|
-
"spec/units/certificate_revocation_list_spec.rb",
|
38
|
-
"spec/units/certificate_spec.rb",
|
39
|
-
"spec/units/distinguished_name_spec.rb",
|
40
|
-
"spec/units/extensions_spec.rb",
|
41
|
-
"spec/units/key_material_spec.rb",
|
42
|
-
"spec/units/ocsp_handler_spec.rb",
|
43
|
-
"spec/units/serial_number_spec.rb",
|
44
|
-
"spec/units/signing_entity_spec.rb",
|
45
|
-
"spec/units/units_helper.rb"
|
46
|
-
]
|
47
|
-
s.homepage = %q{http://github.com/cchandler/certificate_authority}
|
48
|
-
s.licenses = ["MIT"]
|
49
|
-
s.require_paths = ["lib"]
|
50
|
-
s.rubygems_version = %q{1.7.2}
|
51
|
-
s.summary = %q{Ruby gem for managing the core functions outlined in RFC-3280 for PKI}
|
52
|
-
s.test_files = [
|
53
|
-
"spec/spec_helper.rb",
|
54
|
-
"spec/units/certificate_authority_spec.rb",
|
55
|
-
"spec/units/certificate_revocation_list_spec.rb",
|
56
|
-
"spec/units/certificate_spec.rb",
|
57
|
-
"spec/units/distinguished_name_spec.rb",
|
58
|
-
"spec/units/extensions_spec.rb",
|
59
|
-
"spec/units/key_material_spec.rb",
|
60
|
-
"spec/units/ocsp_handler_spec.rb",
|
61
|
-
"spec/units/serial_number_spec.rb",
|
62
|
-
"spec/units/signing_entity_spec.rb",
|
63
|
-
"spec/units/units_helper.rb"
|
64
|
-
]
|
9
|
+
spec.summary = "Ruby gem for managing the core functions outlined in RFC-3280 for PKI"
|
10
|
+
spec.homepage = "https://github.com/cchandler/certificate_authority"
|
11
|
+
spec.license = "MIT"
|
65
12
|
|
66
|
-
|
67
|
-
|
13
|
+
spec.metadata["homepage_uri"] = "https://github.com/cchandler/certificate_authority"
|
14
|
+
spec.metadata["source_code_uri"] = "https://github.com/cchandler/certificate_authority"
|
68
15
|
|
69
|
-
|
70
|
-
|
71
|
-
s.add_development_dependency(%q<rspec>, [">= 0"])
|
72
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
73
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
74
|
-
else
|
75
|
-
s.add_dependency(%q<activemodel>, ["~> 3.0.6"])
|
76
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
77
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
78
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
79
|
-
end
|
80
|
-
else
|
81
|
-
s.add_dependency(%q<activemodel>, ["~> 3.0.6"])
|
82
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
83
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
84
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
16
|
+
spec.files = Dir.chdir(__dir__) do
|
17
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec/)}) }
|
85
18
|
end
|
86
|
-
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.required_ruby_version = ">= 2.4"
|
87
22
|
|
23
|
+
spec.add_development_dependency "coveralls"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "rubocop"
|
28
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#Exterior requirements
|
1
|
+
# Exterior requirements
|
4
2
|
require 'openssl'
|
5
|
-
require 'active_model'
|
6
3
|
|
7
|
-
#Internal modules
|
4
|
+
# Internal modules
|
5
|
+
require 'certificate_authority/core_extensions'
|
8
6
|
require 'certificate_authority/signing_entity'
|
7
|
+
require 'certificate_authority/revocable'
|
8
|
+
require 'certificate_authority/validations'
|
9
9
|
require 'certificate_authority/distinguished_name'
|
10
10
|
require 'certificate_authority/serial_number'
|
11
11
|
require 'certificate_authority/key_material'
|
@@ -14,6 +14,7 @@ require 'certificate_authority/extensions'
|
|
14
14
|
require 'certificate_authority/certificate'
|
15
15
|
require 'certificate_authority/certificate_revocation_list'
|
16
16
|
require 'certificate_authority/ocsp_handler'
|
17
|
+
require 'certificate_authority/signing_request'
|
17
18
|
|
18
19
|
module CertificateAuthority
|
19
|
-
end
|
20
|
+
end
|
@@ -1,68 +1,88 @@
|
|
1
1
|
module CertificateAuthority
|
2
2
|
class Certificate
|
3
|
-
|
4
|
-
include
|
5
|
-
|
3
|
+
include Validations
|
4
|
+
include Revocable
|
5
|
+
|
6
6
|
attr_accessor :distinguished_name
|
7
7
|
attr_accessor :serial_number
|
8
8
|
attr_accessor :key_material
|
9
9
|
attr_accessor :not_before
|
10
10
|
attr_accessor :not_after
|
11
|
-
attr_accessor :revoked_at
|
12
11
|
attr_accessor :extensions
|
13
12
|
attr_accessor :openssl_body
|
14
|
-
|
13
|
+
|
15
14
|
alias :subject :distinguished_name #Same thing as the DN
|
16
|
-
|
15
|
+
|
17
16
|
attr_accessor :parent
|
18
|
-
|
19
|
-
validate
|
17
|
+
|
18
|
+
def validate
|
20
19
|
errors.add :base, "Distinguished name must be valid" unless distinguished_name.valid?
|
21
|
-
errors.add :base, "Key material
|
20
|
+
errors.add :base, "Key material must be valid" unless key_material.valid?
|
22
21
|
errors.add :base, "Serial number must be valid" unless serial_number.valid?
|
23
22
|
errors.add :base, "Extensions must be valid" unless extensions.each do |item|
|
24
|
-
|
25
|
-
|
23
|
+
unless item.respond_to?(:valid?)
|
24
|
+
true
|
25
|
+
else
|
26
|
+
item.valid?
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
|
-
|
30
|
+
|
29
31
|
def initialize
|
30
32
|
self.distinguished_name = DistinguishedName.new
|
31
33
|
self.serial_number = SerialNumber.new
|
32
34
|
self.key_material = MemoryKeyMaterial.new
|
33
|
-
self.not_before =
|
34
|
-
self.not_after =
|
35
|
+
self.not_before = Date.today.utc
|
36
|
+
self.not_after = Date.today.advance(:years => 1).utc
|
35
37
|
self.parent = self
|
36
38
|
self.extensions = load_extensions()
|
37
|
-
|
39
|
+
|
38
40
|
self.signing_entity = false
|
39
|
-
|
41
|
+
|
40
42
|
end
|
41
|
-
|
43
|
+
|
44
|
+
=begin
|
45
|
+
def self.from_openssl openssl_cert
|
46
|
+
unless openssl_cert.is_a? OpenSSL::X509::Certificate
|
47
|
+
raise "Can only construct from an OpenSSL::X509::Certificate"
|
48
|
+
end
|
49
|
+
|
50
|
+
certificate = Certificate.new
|
51
|
+
# Only subject, key_material, and body are used for signing
|
52
|
+
certificate.distinguished_name = DistinguishedName.from_openssl openssl_cert.subject
|
53
|
+
certificate.key_material.public_key = openssl_cert.public_key
|
54
|
+
certificate.openssl_body = openssl_cert
|
55
|
+
certificate.serial_number.number = openssl_cert.serial.to_i
|
56
|
+
certificate.not_before = openssl_cert.not_before
|
57
|
+
certificate.not_after = openssl_cert.not_after
|
58
|
+
# TODO extensions
|
59
|
+
certificate
|
60
|
+
end
|
61
|
+
=end
|
62
|
+
|
42
63
|
def sign!(signing_profile={})
|
43
64
|
raise "Invalid certificate #{self.errors.full_messages}" unless valid?
|
44
65
|
merge_profile_with_extensions(signing_profile)
|
45
|
-
|
66
|
+
|
46
67
|
openssl_cert = OpenSSL::X509::Certificate.new
|
47
|
-
openssl_cert.version
|
68
|
+
openssl_cert.version = 2
|
48
69
|
openssl_cert.not_before = self.not_before
|
49
70
|
openssl_cert.not_after = self.not_after
|
50
71
|
openssl_cert.public_key = self.key_material.public_key
|
51
|
-
|
72
|
+
|
52
73
|
openssl_cert.serial = self.serial_number.number
|
53
|
-
|
74
|
+
|
54
75
|
openssl_cert.subject = self.distinguished_name.to_x509_name
|
55
76
|
openssl_cert.issuer = parent.distinguished_name.to_x509_name
|
56
|
-
|
77
|
+
|
57
78
|
require 'tempfile'
|
58
79
|
t = Tempfile.new("bullshit_conf")
|
59
|
-
# t = File.new("/tmp/openssl.cnf")
|
60
80
|
## The config requires a file even though we won't use it
|
61
81
|
openssl_config = OpenSSL::Config.new(t.path)
|
62
|
-
|
82
|
+
|
63
83
|
factory = OpenSSL::X509::ExtensionFactory.new
|
64
84
|
factory.subject_certificate = openssl_cert
|
65
|
-
|
85
|
+
|
66
86
|
#NB: If the parent doesn't have an SSL body we're making this a self-signed cert
|
67
87
|
if parent.openssl_body.nil?
|
68
88
|
factory.issuer_certificate = openssl_cert
|
@@ -74,51 +94,85 @@ module CertificateAuthority
|
|
74
94
|
config_extensions = extensions[k].config_extensions
|
75
95
|
openssl_config = merge_options(openssl_config,config_extensions)
|
76
96
|
end
|
77
|
-
|
97
|
+
|
78
98
|
# p openssl_config.sections
|
79
|
-
|
99
|
+
|
80
100
|
factory.config = openssl_config
|
81
|
-
|
82
|
-
|
101
|
+
|
102
|
+
# Order matters: e.g. for self-signed, subjectKeyIdentifier must come before authorityKeyIdentifier
|
103
|
+
self.extensions.keys.sort{|a,b| b<=>a}.each do |k|
|
83
104
|
e = extensions[k]
|
84
105
|
next if e.to_s.nil? or e.to_s == "" ## If the extension returns an empty string we won't include it
|
85
|
-
ext = factory.create_ext(e.openssl_identifier, e.to_s)
|
106
|
+
ext = factory.create_ext(e.openssl_identifier, e.to_s, e.critical)
|
86
107
|
openssl_cert.add_extension(ext)
|
87
108
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
109
|
+
|
110
|
+
if signing_profile["digest"].nil?
|
111
|
+
digest = OpenSSL::Digest.new("SHA512")
|
112
|
+
else
|
113
|
+
digest = OpenSSL::Digest.new(signing_profile["digest"])
|
114
|
+
end
|
115
|
+
|
116
|
+
self.openssl_body = openssl_cert.sign(parent.key_material.private_key, digest)
|
117
|
+
ensure
|
118
|
+
t.close! if t # We can get rid of the ridiculous temp file
|
93
119
|
end
|
94
|
-
|
120
|
+
|
95
121
|
def is_signing_entity?
|
96
122
|
self.extensions["basicConstraints"].ca
|
97
123
|
end
|
98
|
-
|
124
|
+
|
99
125
|
def signing_entity=(signing)
|
100
126
|
self.extensions["basicConstraints"].ca = signing
|
101
127
|
end
|
102
|
-
|
128
|
+
|
103
129
|
def revoked?
|
104
130
|
!self.revoked_at.nil?
|
105
131
|
end
|
106
|
-
|
132
|
+
|
107
133
|
def to_pem
|
108
134
|
raise "Certificate has no signed body" if self.openssl_body.nil?
|
109
135
|
self.openssl_body.to_pem
|
110
136
|
end
|
111
|
-
|
137
|
+
|
138
|
+
def to_csr
|
139
|
+
csr = SigningRequest.new
|
140
|
+
csr.distinguished_name = self.distinguished_name
|
141
|
+
csr.key_material = self.key_material
|
142
|
+
factory = OpenSSL::X509::ExtensionFactory.new
|
143
|
+
exts = []
|
144
|
+
self.extensions.keys.each do |k|
|
145
|
+
## Don't copy over key identifiers for CSRs
|
146
|
+
next if k == "subjectKeyIdentifier" || k == "authorityKeyIdentifier"
|
147
|
+
e = extensions[k]
|
148
|
+
## If the extension returns an empty string we won't include it
|
149
|
+
next if e.to_s.nil? or e.to_s == ""
|
150
|
+
exts << factory.create_ext(e.openssl_identifier, e.to_s, e.critical)
|
151
|
+
end
|
152
|
+
attrval = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(exts)])
|
153
|
+
attrs = [
|
154
|
+
OpenSSL::X509::Attribute.new("extReq", attrval),
|
155
|
+
OpenSSL::X509::Attribute.new("msExtReq", attrval)
|
156
|
+
]
|
157
|
+
csr.attributes = attrs
|
158
|
+
csr
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.from_x509_cert(raw_cert)
|
162
|
+
openssl_cert = OpenSSL::X509::Certificate.new(raw_cert)
|
163
|
+
Certificate.from_openssl(openssl_cert)
|
164
|
+
end
|
165
|
+
|
112
166
|
def is_root_entity?
|
113
167
|
self.parent == self && is_signing_entity?
|
114
168
|
end
|
115
|
-
|
169
|
+
|
116
170
|
def is_intermediate_entity?
|
117
171
|
(self.parent != self) && is_signing_entity?
|
118
172
|
end
|
119
|
-
|
173
|
+
|
120
174
|
private
|
121
|
-
|
175
|
+
|
122
176
|
def merge_profile_with_extensions(signing_profile={})
|
123
177
|
return self.extensions if signing_profile["extensions"].nil?
|
124
178
|
signing_config = signing_profile["extensions"]
|
@@ -127,50 +181,76 @@ module CertificateAuthority
|
|
127
181
|
items = signing_config[k]
|
128
182
|
items.keys.each do |profile_item_key|
|
129
183
|
if extension.respond_to?("#{profile_item_key}=".to_sym)
|
130
|
-
|
184
|
+
if k == 'subjectAltName' && profile_item_key == 'emails'
|
185
|
+
items[profile_item_key].map do |email|
|
186
|
+
if email == 'email:copy'
|
187
|
+
fail "no email address provided for subject: #{subject.to_x509_name}" unless subject.email_address
|
188
|
+
"email:#{subject.email_address}"
|
189
|
+
else
|
190
|
+
email
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
extension.send("#{profile_item_key}=".to_sym, items[profile_item_key] )
|
131
195
|
else
|
132
196
|
p "Tried applying '#{profile_item_key}' to #{extension.class} but it doesn't respond!"
|
133
197
|
end
|
134
198
|
end
|
135
199
|
end
|
136
200
|
end
|
137
|
-
|
201
|
+
|
202
|
+
# Enumeration of the extensions. Not the worst option since
|
203
|
+
# the likelihood of these needing to be updated is low at best.
|
204
|
+
EXTENSIONS = [
|
205
|
+
CertificateAuthority::Extensions::BasicConstraints,
|
206
|
+
CertificateAuthority::Extensions::CrlDistributionPoints,
|
207
|
+
CertificateAuthority::Extensions::SubjectKeyIdentifier,
|
208
|
+
CertificateAuthority::Extensions::AuthorityKeyIdentifier,
|
209
|
+
CertificateAuthority::Extensions::AuthorityInfoAccess,
|
210
|
+
CertificateAuthority::Extensions::KeyUsage,
|
211
|
+
CertificateAuthority::Extensions::ExtendedKeyUsage,
|
212
|
+
CertificateAuthority::Extensions::SubjectAlternativeName,
|
213
|
+
CertificateAuthority::Extensions::CertificatePolicies
|
214
|
+
]
|
215
|
+
|
138
216
|
def load_extensions
|
139
217
|
extension_hash = {}
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
temp_extensions << basic_constraints
|
144
|
-
crl_distribution_points = CertificateAuthority::Extensions::CrlDistributionPoints.new
|
145
|
-
temp_extensions << crl_distribution_points
|
146
|
-
subject_key_identifier = CertificateAuthority::Extensions::SubjectKeyIdentifier.new
|
147
|
-
temp_extensions << subject_key_identifier
|
148
|
-
authority_key_identifier = CertificateAuthority::Extensions::AuthorityKeyIdentifier.new
|
149
|
-
temp_extensions << authority_key_identifier
|
150
|
-
authority_info_access = CertificateAuthority::Extensions::AuthorityInfoAccess.new
|
151
|
-
temp_extensions << authority_info_access
|
152
|
-
key_usage = CertificateAuthority::Extensions::KeyUsage.new
|
153
|
-
temp_extensions << key_usage
|
154
|
-
extended_key_usage = CertificateAuthority::Extensions::ExtendedKeyUsage.new
|
155
|
-
temp_extensions << extended_key_usage
|
156
|
-
subject_alternative_name = CertificateAuthority::Extensions::SubjectAlternativeName.new
|
157
|
-
temp_extensions << subject_alternative_name
|
158
|
-
certificate_policies = CertificateAuthority::Extensions::CertificatePolicies.new
|
159
|
-
temp_extensions << certificate_policies
|
160
|
-
|
161
|
-
temp_extensions.each do |extension|
|
218
|
+
|
219
|
+
EXTENSIONS.each do |klass|
|
220
|
+
extension = klass.new
|
162
221
|
extension_hash[extension.openssl_identifier] = extension
|
163
222
|
end
|
164
|
-
|
223
|
+
|
165
224
|
extension_hash
|
166
225
|
end
|
167
|
-
|
226
|
+
|
168
227
|
def merge_options(config,hash)
|
169
228
|
hash.keys.each do |k|
|
170
229
|
config[k] = hash[k]
|
171
230
|
end
|
172
231
|
config
|
173
232
|
end
|
174
|
-
|
233
|
+
|
234
|
+
def self.from_openssl openssl_cert
|
235
|
+
unless openssl_cert.is_a? OpenSSL::X509::Certificate
|
236
|
+
raise "Can only construct from an OpenSSL::X509::Certificate"
|
237
|
+
end
|
238
|
+
|
239
|
+
certificate = Certificate.new
|
240
|
+
# Only subject, key_material, and body are used for signing
|
241
|
+
certificate.distinguished_name = DistinguishedName.from_openssl openssl_cert.subject
|
242
|
+
certificate.key_material.public_key = openssl_cert.public_key
|
243
|
+
certificate.openssl_body = openssl_cert
|
244
|
+
certificate.serial_number.number = openssl_cert.serial.to_i
|
245
|
+
certificate.not_before = openssl_cert.not_before
|
246
|
+
certificate.not_after = openssl_cert.not_after
|
247
|
+
EXTENSIONS.each do |klass|
|
248
|
+
_,v,c = (openssl_cert.extensions.detect { |e| e.to_a.first == klass::OPENSSL_IDENTIFIER } || []).to_a
|
249
|
+
certificate.extensions[klass::OPENSSL_IDENTIFIER] = klass.parse(v, c) if v
|
250
|
+
end
|
251
|
+
|
252
|
+
certificate
|
253
|
+
end
|
254
|
+
|
175
255
|
end
|
176
|
-
end
|
256
|
+
end
|