certificate_authority 0.1.6 → 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 -31
- data/README.rdoc +91 -2
- data/Rakefile +6 -41
- data/certificate_authority.gemspec +22 -66
- data/lib/certificate_authority.rb +6 -5
- data/lib/certificate_authority/certificate.rb +91 -36
- data/lib/certificate_authority/certificate_revocation_list.rb +34 -14
- data/lib/certificate_authority/core_extensions.rb +46 -0
- data/lib/certificate_authority/distinguished_name.rb +64 -16
- data/lib/certificate_authority/extensions.rb +417 -45
- data/lib/certificate_authority/key_material.rb +30 -9
- data/lib/certificate_authority/ocsp_handler.rb +75 -5
- data/lib/certificate_authority/pkcs11_key_material.rb +0 -2
- data/lib/certificate_authority/revocable.rb +14 -0
- data/lib/certificate_authority/serial_number.rb +15 -2
- 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 +76 -48
- 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 -428
- data/spec/units/distinguished_name_spec.rb +0 -59
- data/spec/units/extensions_spec.rb +0 -115
- data/spec/units/key_material_spec.rb +0 -100
- data/spec/units/ocsp_handler_spec.rb +0 -104
- data/spec/units/pkcs11_key_material_spec.rb +0 -41
- 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
@@ -15,11 +15,30 @@ module CertificateAuthority
|
|
15
15
|
def is_in_memory?
|
16
16
|
raise "Required implementation"
|
17
17
|
end
|
18
|
+
|
19
|
+
def self.from_x509_key_pair(pair,password=nil)
|
20
|
+
if password.nil?
|
21
|
+
key = OpenSSL::PKey::RSA.new(pair)
|
22
|
+
else
|
23
|
+
key = OpenSSL::PKey::RSA.new(pair,password)
|
24
|
+
end
|
25
|
+
mem_key = MemoryKeyMaterial.new
|
26
|
+
mem_key.public_key = key.public_key
|
27
|
+
mem_key.private_key = key
|
28
|
+
mem_key
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.from_x509_public_key(public_key_pem)
|
32
|
+
key = OpenSSL::PKey::RSA.new(public_key_pem)
|
33
|
+
signing_request_key = SigningRequestKeyMaterial.new
|
34
|
+
signing_request_key.public_key = key.public_key
|
35
|
+
signing_request_key
|
36
|
+
end
|
18
37
|
end
|
19
38
|
|
20
39
|
class MemoryKeyMaterial
|
21
40
|
include KeyMaterial
|
22
|
-
include
|
41
|
+
include Validations
|
23
42
|
|
24
43
|
attr_accessor :keypair
|
25
44
|
attr_accessor :private_key
|
@@ -28,11 +47,13 @@ module CertificateAuthority
|
|
28
47
|
def initialize
|
29
48
|
end
|
30
49
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
50
|
+
def validate
|
51
|
+
if private_key.nil?
|
52
|
+
errors.add :private_key, "cannot be blank"
|
53
|
+
end
|
54
|
+
if public_key.nil?
|
55
|
+
errors.add :public_key, "cannot be blank"
|
56
|
+
end
|
36
57
|
end
|
37
58
|
|
38
59
|
def is_in_hardware?
|
@@ -61,10 +82,10 @@ module CertificateAuthority
|
|
61
82
|
|
62
83
|
class SigningRequestKeyMaterial
|
63
84
|
include KeyMaterial
|
64
|
-
include
|
85
|
+
include Validations
|
65
86
|
|
66
|
-
|
67
|
-
|
87
|
+
def validate
|
88
|
+
errors.add :public_key, "cannot be blank" if public_key.nil?
|
68
89
|
end
|
69
90
|
|
70
91
|
attr_accessor :public_key
|
@@ -1,6 +1,74 @@
|
|
1
1
|
module CertificateAuthority
|
2
|
+
class OCSPResponseBuilder
|
3
|
+
attr_accessor :ocsp_response
|
4
|
+
attr_accessor :verification_mechanism
|
5
|
+
attr_accessor :ocsp_request_reader
|
6
|
+
attr_accessor :parent
|
7
|
+
attr_accessor :next_update
|
8
|
+
|
9
|
+
GOOD = OpenSSL::OCSP::V_CERTSTATUS_GOOD
|
10
|
+
REVOKED = OpenSSL::OCSP::V_CERTSTATUS_REVOKED
|
11
|
+
|
12
|
+
NO_REASON=0
|
13
|
+
KEY_COMPROMISED=OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE
|
14
|
+
UNSPECIFIED=OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED
|
15
|
+
|
16
|
+
def build_response()
|
17
|
+
raise "Requires a parent for signing" if @parent.nil?
|
18
|
+
if @verification_mechanism.nil?
|
19
|
+
## If no verification callback is provided we're marking it GOOD
|
20
|
+
@verification_mechanism = lambda {|cert_id| [GOOD,NO_REASON] }
|
21
|
+
end
|
22
|
+
|
23
|
+
@ocsp_request_reader.ocsp_request.certid.each do |cert_id|
|
24
|
+
result,reason = verification_mechanism.call(cert_id.serial)
|
25
|
+
|
26
|
+
## cert_id, status, reason, rev_time, this update, next update, ext
|
27
|
+
## - unit of time is seconds
|
28
|
+
## - rev_time is currently set to "now"
|
29
|
+
@ocsp_response.add_status(cert_id,
|
30
|
+
result, reason,
|
31
|
+
0, 0, @next_update, nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
@ocsp_response.sign(OpenSSL::X509::Certificate.new(@parent.to_pem), @parent.key_material.private_key, nil, nil)
|
35
|
+
OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, @ocsp_response)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.from_request_reader(request_reader,verification_mechanism=nil)
|
39
|
+
response_builder = OCSPResponseBuilder.new
|
40
|
+
response_builder.ocsp_request_reader = request_reader
|
41
|
+
|
42
|
+
ocsp_response = OpenSSL::OCSP::BasicResponse.new
|
43
|
+
ocsp_response.copy_nonce(request_reader.ocsp_request)
|
44
|
+
response_builder.ocsp_response = ocsp_response
|
45
|
+
response_builder.next_update = 60*15 #Default of 15 minutes
|
46
|
+
response_builder
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class OCSPRequestReader
|
51
|
+
attr_accessor :raw_ocsp_request
|
52
|
+
attr_accessor :ocsp_request
|
53
|
+
|
54
|
+
def serial_numbers
|
55
|
+
@ocsp_request.certid.collect do |cert_id|
|
56
|
+
cert_id.serial
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.from_der(request_body)
|
61
|
+
reader = OCSPRequestReader.new
|
62
|
+
reader.raw_ocsp_request = request_body
|
63
|
+
reader.ocsp_request = OpenSSL::OCSP::Request.new(request_body)
|
64
|
+
|
65
|
+
reader
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
## DEPRECATED
|
2
70
|
class OCSPHandler
|
3
|
-
include
|
71
|
+
include Validations
|
4
72
|
|
5
73
|
attr_accessor :ocsp_request
|
6
74
|
attr_accessor :certificate_ids
|
@@ -10,10 +78,10 @@ module CertificateAuthority
|
|
10
78
|
|
11
79
|
attr_accessor :ocsp_response_body
|
12
80
|
|
13
|
-
validate
|
81
|
+
def validate
|
14
82
|
errors.add :parent, "A parent entity must be set" if parent.nil?
|
83
|
+
all_certificates_available
|
15
84
|
end
|
16
|
-
validate :all_certificates_available
|
17
85
|
|
18
86
|
def initialize
|
19
87
|
self.certificates = {}
|
@@ -24,9 +92,11 @@ module CertificateAuthority
|
|
24
92
|
end
|
25
93
|
|
26
94
|
def extract_certificate_serials
|
27
|
-
|
28
|
-
openssl_request = OpenSSL::OCSP::Request.new(self.ocsp_request)
|
95
|
+
openssl_request = OpenSSL::OCSP::Request.new(@ocsp_request)
|
29
96
|
|
97
|
+
if openssl_request.certid.nil?
|
98
|
+
raise "Invalid openssl request"
|
99
|
+
end
|
30
100
|
self.certificate_ids = openssl_request.certid.collect do |cert_id|
|
31
101
|
cert_id.serial
|
32
102
|
end
|
@@ -1,9 +1,22 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
module CertificateAuthority
|
2
4
|
class SerialNumber
|
3
|
-
include
|
5
|
+
include Validations
|
6
|
+
include Revocable
|
4
7
|
|
5
8
|
attr_accessor :number
|
6
9
|
|
7
|
-
|
10
|
+
def validate
|
11
|
+
if self.number.nil?
|
12
|
+
errors.add :number, "must not be empty"
|
13
|
+
elsif self.number.to_i <= 0
|
14
|
+
errors.add :number, "must be greater than zero"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
self.number = SecureRandom.random_number(2**128-1)
|
20
|
+
end
|
8
21
|
end
|
9
22
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module CertificateAuthority
|
2
|
+
class SigningRequest
|
3
|
+
attr_accessor :distinguished_name
|
4
|
+
attr_accessor :key_material
|
5
|
+
attr_accessor :raw_body
|
6
|
+
attr_accessor :openssl_csr
|
7
|
+
attr_accessor :digest
|
8
|
+
attr_accessor :attributes
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
@attributes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
# Fake attribute for convenience because adding
|
15
|
+
# alternative names on a CSR is remarkably non-trivial.
|
16
|
+
def subject_alternative_names=(alt_names)
|
17
|
+
raise "alt_names must be an Array" unless alt_names.is_a?(Array)
|
18
|
+
|
19
|
+
factory = OpenSSL::X509::ExtensionFactory.new
|
20
|
+
name_list = alt_names.map{|m| "DNS:#{m}"}.join(",")
|
21
|
+
ext = factory.create_ext("subjectAltName",name_list,false)
|
22
|
+
ext_set = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence([ext])])
|
23
|
+
attr = OpenSSL::X509::Attribute.new("extReq", ext_set)
|
24
|
+
@attributes << attr
|
25
|
+
end
|
26
|
+
|
27
|
+
def read_attributes_by_oid(*oids)
|
28
|
+
attributes.detect { |a| oids.include?(a.oid) }
|
29
|
+
end
|
30
|
+
protected :read_attributes_by_oid
|
31
|
+
|
32
|
+
def to_cert
|
33
|
+
cert = Certificate.new
|
34
|
+
if !@distinguished_name.nil?
|
35
|
+
cert.distinguished_name = @distinguished_name
|
36
|
+
end
|
37
|
+
cert.key_material = @key_material
|
38
|
+
if attribute = read_attributes_by_oid('extReq', 'msExtReq')
|
39
|
+
set = OpenSSL::ASN1.decode(attribute.value)
|
40
|
+
seq = set.value.first
|
41
|
+
seq.value.collect { |asn1ext| OpenSSL::X509::Extension.new(asn1ext).to_a }.each do |o, v, c|
|
42
|
+
Certificate::EXTENSIONS.each do |klass|
|
43
|
+
cert.extensions[klass::OPENSSL_IDENTIFIER] = klass.parse(v, c) if v && klass::OPENSSL_IDENTIFIER == o
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
cert
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_pem
|
51
|
+
to_x509_csr.to_pem
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_x509_csr
|
55
|
+
raise "Must specify a DN/subject on csr" if @distinguished_name.nil?
|
56
|
+
raise "Invalid DN in request" unless @distinguished_name.valid?
|
57
|
+
raise "CSR must have key material" if @key_material.nil?
|
58
|
+
raise "CSR must include a public key on key material" if @key_material.public_key.nil?
|
59
|
+
raise "Need a private key on key material for CSR generation" if @key_material.private_key.nil?
|
60
|
+
|
61
|
+
opensslcsr = OpenSSL::X509::Request.new
|
62
|
+
opensslcsr.subject = @distinguished_name.to_x509_name
|
63
|
+
opensslcsr.public_key = @key_material.public_key
|
64
|
+
opensslcsr.attributes = @attributes unless @attributes.nil?
|
65
|
+
opensslcsr.sign @key_material.private_key, OpenSSL::Digest.new(@digest || "SHA512")
|
66
|
+
opensslcsr
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.from_x509_csr(raw_csr)
|
70
|
+
csr = SigningRequest.new
|
71
|
+
openssl_csr = OpenSSL::X509::Request.new(raw_csr)
|
72
|
+
csr.distinguished_name = DistinguishedName.from_openssl openssl_csr.subject
|
73
|
+
csr.raw_body = raw_csr
|
74
|
+
csr.openssl_csr = openssl_csr
|
75
|
+
csr.attributes = openssl_csr.attributes
|
76
|
+
key_material = SigningRequestKeyMaterial.new
|
77
|
+
key_material.public_key = openssl_csr.public_key
|
78
|
+
csr.key_material = key_material
|
79
|
+
csr
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.from_netscape_spkac(raw_spkac)
|
83
|
+
openssl_spkac = OpenSSL::Netscape::SPKI.new raw_spkac
|
84
|
+
csr = SigningRequest.new
|
85
|
+
csr.raw_body = raw_spkac
|
86
|
+
key_material = SigningRequestKeyMaterial.new
|
87
|
+
key_material.public_key = openssl_spkac.public_key
|
88
|
+
csr
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# This is a super simple replacement for ActiveSupport::Validations
|
3
|
+
#
|
4
|
+
|
5
|
+
module CertificateAuthority
|
6
|
+
class Errors < Array
|
7
|
+
def add(symbol, msg)
|
8
|
+
self.push([symbol, msg])
|
9
|
+
end
|
10
|
+
def full_messages
|
11
|
+
self.map {|i| i[0].to_s + ": " + i[1]}.join("\n")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Validations
|
16
|
+
def valid?
|
17
|
+
@errors = Errors.new
|
18
|
+
validate
|
19
|
+
errors.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
# must be overridden
|
23
|
+
def validate
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
@errors ||= Errors.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,111 +1,139 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: certificate_authority
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Chris Chandler
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2020-05-28 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement:
|
17
|
-
none: false
|
14
|
+
name: coveralls
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
22
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
23
49
|
prerelease: false
|
24
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
25
55
|
- !ruby/object:Gem::Dependency
|
26
56
|
name: rspec
|
27
|
-
requirement:
|
28
|
-
none: false
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
29
58
|
requirements:
|
30
|
-
- -
|
59
|
+
- - ">="
|
31
60
|
- !ruby/object:Gem::Version
|
32
61
|
version: '0'
|
33
62
|
type: :development
|
34
63
|
prerelease: false
|
35
|
-
version_requirements:
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
36
69
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement:
|
39
|
-
none: false
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
40
72
|
requirements:
|
41
|
-
- -
|
73
|
+
- - ">="
|
42
74
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
75
|
+
version: '0'
|
44
76
|
type: :development
|
45
77
|
prerelease: false
|
46
|
-
version_requirements:
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
47
83
|
description:
|
48
|
-
email:
|
84
|
+
email:
|
85
|
+
- squanderingtime@gmail.com
|
49
86
|
executables: []
|
50
87
|
extensions: []
|
51
|
-
extra_rdoc_files:
|
52
|
-
- README.rdoc
|
88
|
+
extra_rdoc_files: []
|
53
89
|
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
54
93
|
- Gemfile
|
55
94
|
- Gemfile.lock
|
56
95
|
- README.rdoc
|
57
96
|
- Rakefile
|
58
|
-
- VERSION.yml
|
59
97
|
- certificate_authority.gemspec
|
60
98
|
- lib/certificate_authority.rb
|
61
99
|
- lib/certificate_authority/certificate.rb
|
62
100
|
- lib/certificate_authority/certificate_revocation_list.rb
|
101
|
+
- lib/certificate_authority/core_extensions.rb
|
63
102
|
- lib/certificate_authority/distinguished_name.rb
|
64
103
|
- lib/certificate_authority/extensions.rb
|
65
104
|
- lib/certificate_authority/key_material.rb
|
66
105
|
- lib/certificate_authority/ocsp_handler.rb
|
67
106
|
- lib/certificate_authority/pkcs11_key_material.rb
|
107
|
+
- lib/certificate_authority/revocable.rb
|
68
108
|
- lib/certificate_authority/serial_number.rb
|
69
109
|
- lib/certificate_authority/signing_entity.rb
|
110
|
+
- lib/certificate_authority/signing_request.rb
|
111
|
+
- lib/certificate_authority/validations.rb
|
112
|
+
- lib/certificate_authority/version.rb
|
70
113
|
- lib/tasks/certificate_authority.rake
|
71
|
-
|
72
|
-
- spec/units/certificate_authority_spec.rb
|
73
|
-
- spec/units/certificate_revocation_list_spec.rb
|
74
|
-
- spec/units/certificate_spec.rb
|
75
|
-
- spec/units/distinguished_name_spec.rb
|
76
|
-
- spec/units/extensions_spec.rb
|
77
|
-
- spec/units/key_material_spec.rb
|
78
|
-
- spec/units/ocsp_handler_spec.rb
|
79
|
-
- spec/units/pkcs11_key_material_spec.rb
|
80
|
-
- spec/units/serial_number_spec.rb
|
81
|
-
- spec/units/signing_entity_spec.rb
|
82
|
-
- spec/units/units_helper.rb
|
83
|
-
homepage: http://github.com/cchandler/certificate_authority
|
114
|
+
homepage: https://github.com/cchandler/certificate_authority
|
84
115
|
licenses:
|
85
116
|
- MIT
|
117
|
+
metadata:
|
118
|
+
homepage_uri: https://github.com/cchandler/certificate_authority
|
119
|
+
source_code_uri: https://github.com/cchandler/certificate_authority
|
86
120
|
post_install_message:
|
87
121
|
rdoc_options: []
|
88
122
|
require_paths:
|
89
123
|
- lib
|
90
124
|
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
-
none: false
|
92
125
|
requirements:
|
93
|
-
- -
|
126
|
+
- - ">="
|
94
127
|
- !ruby/object:Gem::Version
|
95
|
-
version: '
|
96
|
-
segments:
|
97
|
-
- 0
|
98
|
-
hash: -2366790866817530073
|
128
|
+
version: '2.4'
|
99
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
-
none: false
|
101
130
|
requirements:
|
102
|
-
- -
|
131
|
+
- - ">="
|
103
132
|
- !ruby/object:Gem::Version
|
104
133
|
version: '0'
|
105
134
|
requirements: []
|
106
|
-
|
107
|
-
rubygems_version: 1.8.15
|
135
|
+
rubygems_version: 3.1.2
|
108
136
|
signing_key:
|
109
|
-
specification_version:
|
137
|
+
specification_version: 4
|
110
138
|
summary: Ruby gem for managing the core functions outlined in RFC-3280 for PKI
|
111
139
|
test_files: []
|