Class: MiniCa::Certificate
- Inherits:
-
Object
- Object
- MiniCa::Certificate
- Defined in:
- lib/mini_ca/certificate.rb
Constant Summary collapse
- DIGEST =
OpenSSL::Digest::SHA256
Instance Attribute Summary collapse
-
#ca ⇒ Object
readonly
Returns the value of attribute ca.
-
#issuer ⇒ Object
readonly
Returns the value of attribute issuer.
-
#private_key ⇒ Object
readonly
Returns the value of attribute private_key.
-
#x509 ⇒ Object
readonly
Returns the value of attribute x509.
Instance Method Summary collapse
- #bundle ⇒ Object
- #bundle_pem ⇒ Object
- #chain ⇒ Object
- #chain_pem ⇒ Object
-
#initialize(cn, sans: nil, issuer: nil, ca: false, serial: nil, not_before: nil, not_after: nil, country: nil, state: nil, location: nil, organization: nil, private_key: nil) ⇒ Certificate
constructor
rubocop:disable ParameterLists.
-
#issue(cn, **opts) ⇒ Object
rubocop:enable ParameterLists.
- #private_key_pem ⇒ Object
- #public_key ⇒ Object
- #store ⇒ Object
- #x509_pem ⇒ Object
Constructor Details
#initialize(cn, sans: nil, issuer: nil, ca: false, serial: nil, not_before: nil, not_after: nil, country: nil, state: nil, location: nil, organization: nil, private_key: nil) ⇒ Certificate
rubocop:disable ParameterLists
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 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 |
# File 'lib/mini_ca/certificate.rb', line 8 def initialize( cn, sans: nil, issuer: nil, ca: false, serial: nil, not_before: nil, not_after: nil, country: nil, state: nil, location: nil, organization: nil, private_key: nil ) @private_key = private_key || OpenSSL::PKey::RSA.new(2048) @x509 = OpenSSL::X509::Certificate.new @issuer = issuer @ca = ca @counter = 0 x509.version = 0x2 x509.serial = serial || 0 x509.public_key = public_key x509.subject = OpenSSL::X509::Name.new [ ['CN', cn], ['C', country], ['ST', state], ['L', location], ['O', organization] ].each do |prop, value| next if value.nil? x509.subject = x509.subject.add_entry(prop, value) end x509.issuer = issuer ? issuer.x509.subject : x509.subject if issuer not_before ||= issuer.x509.not_before not_after ||= issuer.x509.not_after if issuer.x509.not_before > not_before raise Error, 'Certificate cannot become valid before issuer' end if issuer.x509.not_after < not_after raise Error, 'Certificate cannot expire after issuer' end else not_before ||= Time.now - 3600 * 24 not_after ||= Time.now + 3600 + 24 end x509.not_before = not_before x509.not_after = not_after ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = x509 sans = (sans || []) + ["DNS:#{cn}"] exts = if ca [ ef.create_extension('basicConstraints', 'CA:TRUE', true) ] else [ ef.create_extension('basicConstraints', 'CA:FALSE', true), ef.create_extension('subjectAltName', sans.join(','), false) ] end exts.each { |e| x509.add_extension(e) } signing_key = issuer ? issuer.private_key : send(:private_key) x509.sign signing_key, DIGEST.new end |
Instance Attribute Details
#ca ⇒ Object (readonly)
Returns the value of attribute ca.
5 6 7 |
# File 'lib/mini_ca/certificate.rb', line 5 def ca @ca end |
#issuer ⇒ Object (readonly)
Returns the value of attribute issuer.
5 6 7 |
# File 'lib/mini_ca/certificate.rb', line 5 def issuer @issuer end |
#private_key ⇒ Object (readonly)
Returns the value of attribute private_key.
5 6 7 |
# File 'lib/mini_ca/certificate.rb', line 5 def private_key @private_key end |
#x509 ⇒ Object (readonly)
Returns the value of attribute x509.
5 6 7 |
# File 'lib/mini_ca/certificate.rb', line 5 def x509 @x509 end |
Instance Method Details
#bundle ⇒ Object
110 111 112 |
# File 'lib/mini_ca/certificate.rb', line 110 def bundle [self] + chain end |
#bundle_pem ⇒ Object
122 123 124 |
# File 'lib/mini_ca/certificate.rb', line 122 def bundle_pem bundle.map(&:x509).map(&:to_pem).join('') end |
#chain ⇒ Object
101 102 103 104 105 106 107 108 |
# File 'lib/mini_ca/certificate.rb', line 101 def chain bits = [] this_cert = self until (this_cert = this_cert.issuer).nil? bits << this_cert end bits[0...-1] end |
#chain_pem ⇒ Object
118 119 120 |
# File 'lib/mini_ca/certificate.rb', line 118 def chain_pem chain.map(&:x509).map(&:to_pem).join('') end |
#issue(cn, **opts) ⇒ Object
rubocop:enable ParameterLists
90 91 92 93 94 |
# File 'lib/mini_ca/certificate.rb', line 90 def issue(cn, **opts) raise 'CA must be set to use #issue' unless ca @counter += 1 Certificate.new(cn, issuer: self, serial: @counter, **opts) end |
#private_key_pem ⇒ Object
126 127 128 |
# File 'lib/mini_ca/certificate.rb', line 126 def private_key_pem private_key.to_pem end |
#public_key ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/mini_ca/certificate.rb', line 130 def public_key case private_key when OpenSSL::PKey::RSA private_key.public_key when OpenSSL::PKey::EC # See: https://github.com/ruby/openssl/issues/29#issuecomment-230664793 # See: https://alexpeattie.com/blog/signing-a-csr-with-ecdsa-in-ruby pub = OpenSSL::PKey::EC.new(private_key.group) pub.public_key = private_key.public_key pub else raise Error, "Unsupported private_key: #{private_key.class}" end end |
#store ⇒ Object
96 97 98 99 |
# File 'lib/mini_ca/certificate.rb', line 96 def store raise 'CA must be set to use #store' unless ca OpenSSL::X509::Store.new.tap { |store| store.add_cert(x509) } end |
#x509_pem ⇒ Object
114 115 116 |
# File 'lib/mini_ca/certificate.rb', line 114 def x509_pem x509.to_pem end |