Class: CertificateAuthority::Certificate
- Inherits:
-
Object
- Object
- CertificateAuthority::Certificate
- Includes:
- Revocable, Validations
- Defined in:
- lib/certificate_authority/certificate.rb
Instance Attribute Summary collapse
-
#distinguished_name ⇒ Object
(also: #subject)
Returns the value of attribute distinguished_name.
-
#extensions ⇒ Object
Returns the value of attribute extensions.
-
#key_material ⇒ Object
Returns the value of attribute key_material.
-
#not_after ⇒ Object
Returns the value of attribute not_after.
-
#not_before ⇒ Object
Returns the value of attribute not_before.
-
#openssl_body ⇒ Object
Returns the value of attribute openssl_body.
-
#parent ⇒ Object
Returns the value of attribute parent.
-
#serial_number ⇒ Object
Returns the value of attribute serial_number.
Attributes included from Revocable
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize ⇒ Certificate
constructor
A new instance of Certificate.
- #is_intermediate_entity? ⇒ Boolean
- #is_root_entity? ⇒ Boolean
- #is_signing_entity? ⇒ Boolean
- #revoked? ⇒ Boolean
-
#sign!(signing_profile = {}) ⇒ Object
def self.from_openssl openssl_cert unless openssl_cert.is_a? OpenSSL::X509::Certificate raise “Can only construct from an OpenSSL::X509::Certificate” end.
- #signing_entity=(signing) ⇒ Object
- #to_csr ⇒ Object
- #to_pem ⇒ Object
- #validate ⇒ Object
Methods included from Revocable
Methods included from Validations
Constructor Details
#initialize ⇒ Certificate
Returns a new instance of Certificate.
31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/certificate_authority/certificate.rb', line 31 def initialize self.distinguished_name = DistinguishedName.new self.serial_number = SerialNumber.new self.key_material = MemoryKeyMaterial.new self.not_before = Date.today.utc self.not_after = Date.today.advance(:years => 1).utc self.parent = self self.extensions = load_extensions() self.signing_entity = false end |
Instance Attribute Details
#distinguished_name ⇒ Object Also known as: subject
Returns the value of attribute distinguished_name.
6 7 8 |
# File 'lib/certificate_authority/certificate.rb', line 6 def distinguished_name @distinguished_name end |
#extensions ⇒ Object
Returns the value of attribute extensions.
11 12 13 |
# File 'lib/certificate_authority/certificate.rb', line 11 def extensions @extensions end |
#key_material ⇒ Object
Returns the value of attribute key_material.
8 9 10 |
# File 'lib/certificate_authority/certificate.rb', line 8 def key_material @key_material end |
#not_after ⇒ Object
Returns the value of attribute not_after.
10 11 12 |
# File 'lib/certificate_authority/certificate.rb', line 10 def not_after @not_after end |
#not_before ⇒ Object
Returns the value of attribute not_before.
9 10 11 |
# File 'lib/certificate_authority/certificate.rb', line 9 def not_before @not_before end |
#openssl_body ⇒ Object
Returns the value of attribute openssl_body.
12 13 14 |
# File 'lib/certificate_authority/certificate.rb', line 12 def openssl_body @openssl_body end |
#parent ⇒ Object
Returns the value of attribute parent.
16 17 18 |
# File 'lib/certificate_authority/certificate.rb', line 16 def parent @parent end |
#serial_number ⇒ Object
Returns the value of attribute serial_number.
7 8 9 |
# File 'lib/certificate_authority/certificate.rb', line 7 def serial_number @serial_number end |
Class Method Details
.from_x509_cert(raw_cert) ⇒ Object
147 148 149 150 |
# File 'lib/certificate_authority/certificate.rb', line 147 def self.from_x509_cert(raw_cert) openssl_cert = OpenSSL::X509::Certificate.new(raw_cert) Certificate.from_openssl(openssl_cert) end |
Instance Method Details
#is_intermediate_entity? ⇒ Boolean
156 157 158 |
# File 'lib/certificate_authority/certificate.rb', line 156 def is_intermediate_entity? (self.parent != self) && is_signing_entity? end |
#is_root_entity? ⇒ Boolean
152 153 154 |
# File 'lib/certificate_authority/certificate.rb', line 152 def is_root_entity? self.parent == self && is_signing_entity? end |
#is_signing_entity? ⇒ Boolean
107 108 109 |
# File 'lib/certificate_authority/certificate.rb', line 107 def is_signing_entity? self.extensions["basicConstraints"].ca end |
#revoked? ⇒ Boolean
115 116 117 |
# File 'lib/certificate_authority/certificate.rb', line 115 def revoked? !self.revoked_at.nil? end |
#sign!(signing_profile = {}) ⇒ Object
def self.from_openssl openssl_cert
unless openssl_cert.is_a? OpenSSL::X509::Certificate
raise "Can only construct from an OpenSSL::X509::Certificate"
end
certificate = Certificate.new
# Only subject, key_material, and body are used for signing
certificate.distinguished_name = DistinguishedName.from_openssl openssl_cert.subject
certificate.key_material.public_key = openssl_cert.public_key
certificate.openssl_body = openssl_cert
certificate.serial_number.number = openssl_cert.serial.to_i
certificate.not_before = openssl_cert.not_before
certificate.not_after = openssl_cert.not_after
# TODO extensions
certificate
end
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/certificate_authority/certificate.rb', line 63 def sign!(signing_profile={}) raise "Invalid certificate #{self.errors.}" unless valid? merge_profile_with_extensions(signing_profile) openssl_cert = OpenSSL::X509::Certificate.new openssl_cert.version = 2 openssl_cert.not_before = self.not_before openssl_cert.not_after = self.not_after openssl_cert.public_key = self.key_material.public_key openssl_cert.serial = self.serial_number.number openssl_cert.subject = self.distinguished_name.to_x509_name openssl_cert.issuer = parent.distinguished_name.to_x509_name factory = OpenSSL::X509::ExtensionFactory.new factory.subject_certificate = openssl_cert #NB: If the parent doesn't have an SSL body we're making this a self-signed cert if parent.openssl_body.nil? factory.issuer_certificate = openssl_cert else factory.issuer_certificate = parent.openssl_body end factory.config = build_openssl_config # Order matters: e.g. for self-signed, subjectKeyIdentifier must come before authorityKeyIdentifier self.extensions.keys.sort{|a,b| b<=>a}.each do |k| e = extensions[k] next if e.to_s.nil? or e.to_s == "" ## If the extension returns an empty string we won't include it ext = factory.create_ext(e.openssl_identifier, e.to_s, e.critical) openssl_cert.add_extension(ext) end if signing_profile["digest"].nil? digest = OpenSSL::Digest.new("SHA512") else digest = OpenSSL::Digest.new(signing_profile["digest"]) end self.openssl_body = openssl_cert.sign(parent.key_material.private_key, digest) end |
#signing_entity=(signing) ⇒ Object
111 112 113 |
# File 'lib/certificate_authority/certificate.rb', line 111 def signing_entity=(signing) self.extensions["basicConstraints"].ca = signing end |
#to_csr ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/certificate_authority/certificate.rb', line 124 def to_csr csr = SigningRequest.new csr.distinguished_name = self.distinguished_name csr.key_material = self.key_material factory = OpenSSL::X509::ExtensionFactory.new exts = [] self.extensions.keys.each do |k| ## Don't copy over key identifiers for CSRs next if k == "subjectKeyIdentifier" || k == "authorityKeyIdentifier" e = extensions[k] ## If the extension returns an empty string we won't include it next if e.to_s.nil? or e.to_s == "" exts << factory.create_ext(e.openssl_identifier, e.to_s, e.critical) end attrval = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(exts)]) attrs = [ OpenSSL::X509::Attribute.new("extReq", attrval), OpenSSL::X509::Attribute.new("msExtReq", attrval) ] csr.attributes = attrs csr end |
#to_pem ⇒ Object
119 120 121 122 |
# File 'lib/certificate_authority/certificate.rb', line 119 def to_pem raise "Certificate has no signed body" if self.openssl_body.nil? self.openssl_body.to_pem end |
#validate ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/certificate_authority/certificate.rb', line 18 def validate errors.add :base, "Distinguished name must be valid" unless distinguished_name.valid? errors.add :base, "Key material must be valid" unless key_material.valid? errors.add :base, "Serial number must be valid" unless serial_number.valid? errors.add :base, "Extensions must be valid" unless extensions.each do |item| unless item.respond_to?(:valid?) true else item.valid? end end end |