Class: CertificateAuthority::Certificate

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Validations
Defined in:
lib/certificate_authority/certificate.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCertificate

Returns a new instance of Certificate.



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/certificate_authority/certificate.rb', line 32

def initialize
  self.distinguished_name = DistinguishedName.new
  self.serial_number = SerialNumber.new
  self.key_material = MemoryKeyMaterial.new
  self.not_before = Time.now
  self.not_after = Time.now + 60 * 60 * 24 * 365 #One year
  self.parent = self
  self.extensions = load_extensions()

  self.signing_entity = false

end

Instance Attribute Details

#distinguished_nameObject 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

#extensionsObject

Returns the value of attribute extensions.



12
13
14
# File 'lib/certificate_authority/certificate.rb', line 12

def extensions
  @extensions
end

#key_materialObject

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_afterObject

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_beforeObject

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_bodyObject

Returns the value of attribute openssl_body.



13
14
15
# File 'lib/certificate_authority/certificate.rb', line 13

def openssl_body
  @openssl_body
end

#parentObject

Returns the value of attribute parent.



17
18
19
# File 'lib/certificate_authority/certificate.rb', line 17

def parent
  @parent
end

#revoked_atObject

Returns the value of attribute revoked_at.



11
12
13
# File 'lib/certificate_authority/certificate.rb', line 11

def revoked_at
  @revoked_at
end

#serial_numberObject

Returns the value of attribute serial_number.



7
8
9
# File 'lib/certificate_authority/certificate.rb', line 7

def serial_number
  @serial_number
end

Instance Method Details

#is_intermediate_entity?Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/certificate_authority/certificate.rb', line 124

def is_intermediate_entity?
  (self.parent != self) && is_signing_entity?
end

#is_root_entity?Boolean

Returns:

  • (Boolean)


120
121
122
# File 'lib/certificate_authority/certificate.rb', line 120

def is_root_entity?
  self.parent == self && is_signing_entity?
end

#is_signing_entity?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/certificate_authority/certificate.rb', line 103

def is_signing_entity?
  self.extensions["basicConstraints"].ca
end

#revoked?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/certificate_authority/certificate.rb', line 111

def revoked?
  !self.revoked_at.nil?
end

#sign!(signing_profile = {}) ⇒ Object



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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/certificate_authority/certificate.rb', line 45

def sign!(signing_profile={})
  raise "Invalid certificate #{self.errors.full_messages}" 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

  require 'tempfile'
  t = Tempfile.new("bullshit_conf")
  # t = File.new("/tmp/openssl.cnf")
  ## The config requires a file even though we won't use it
  openssl_config = OpenSSL::Config.new(t.path)

  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

  self.extensions.keys.each do |k|
    config_extensions = extensions[k].config_extensions
    openssl_config = merge_options(openssl_config,config_extensions)
  end

  # p openssl_config.sections

  factory.config = 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)
    openssl_cert.add_extension(ext)
  end

  if signing_profile["digest"].nil?
    digest = OpenSSL::Digest::Digest.new("SHA512")
  else
    digest = OpenSSL::Digest::Digest.new(signing_profile["digest"])
  end
  self.openssl_body = openssl_cert.sign(parent.key_material.private_key,digest)
  t.close! if t.is_a?(Tempfile)# We can get rid of the ridiculous temp file
  self.openssl_body
end

#signing_entity=(signing) ⇒ Object



107
108
109
# File 'lib/certificate_authority/certificate.rb', line 107

def signing_entity=(signing)
  self.extensions["basicConstraints"].ca = signing
end

#to_pemObject



115
116
117
118
# File 'lib/certificate_authority/certificate.rb', line 115

def to_pem
  raise "Certificate has no signed body" if self.openssl_body.nil?
  self.openssl_body.to_pem
end