Class: R509::CertificateAuthority::Signer

Inherits:
Object
  • Object
show all
Defined in:
lib/r509/certificate_authority.rb

Overview

Contains the certification authority signing operation methods

Instance Method Summary (collapse)

Constructor Details

- (Signer) initialize(config = nil)

A new instance of Signer

Parameters:



12
13
14
15
16
17
18
19
20
21
# File 'lib/r509/certificate_authority.rb', line 12

def initialize(config=nil)
  @config = config

  if not @config.nil? and not @config.kind_of?(R509::Config::CAConfig)
    raise R509::R509Error, "config must be a kind of R509::Config::CAConfig or nil (for self-sign only)"
  end
  if not @config.nil? and not @config.ca_cert.has_private_key?
    raise R509::R509Error, "You must have a private key associated with your CA certificate to issue"
  end
end

Instance Method Details

- (R509::Cert) selfsign(options)

Self-signs a CSR

Parameters:

  • options (Hash)

    a customizable set of options

Options Hash (options):

  • :csr (R509::CSR)
  • :message_digest (String)

    the message digest to use for this certificate (defaults to sha1)

  • :serial (String)

    the serial number you want to issue the certificate with (defaults to random)

  • :not_before (Time)

    the notBefore for the certificate (defaults to now)

  • :not_after (Time)

    the notAfter for the certificate (defaults to 1 year)

  • :san_names (Array, R509::ASN1::GeneralNames)

    optional either an array of names that will be automatically parsed to determine their type, or an explicit R509::ASN1::GeneralNames object

Returns:



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/r509/certificate_authority.rb', line 103

def selfsign(options)
  if not options.kind_of?(Hash)
    raise ArgumentError, "You must pass a hash of options consisting of at minimum :csr"
  end
  csr = options[:csr]
  if csr.key.nil?
    raise ArgumentError, 'CSR must also have a private key to self sign'
  end
  cert = build_cert(
    :subject => csr.subject.name,
    :issuer => csr.subject.name,
    :not_before => options[:not_before],
    :not_after => options[:not_after],
    :public_key => csr.public_key,
    :serial => options[:serial]
  )

  sans = (options.has_key?(:san_names))? options[:san_names] : csr.san
  san_names = parse_san_names(sans)

  build_extensions(
    :subject_certificate => cert,
    :issuer_certificate => cert,
    :basic_constraints => {"ca" => true },
    :san_names => san_names
  )


  if options.has_key?(:message_digest)
    message_digest = R509::MessageDigest.new(options[:message_digest])
  else
    message_digest = R509::MessageDigest.new('sha1')
  end

  # CSR#key returns R509::PrivateKey and #key on that returns OpenSSL object we need
  cert.sign( csr.key.key, message_digest.digest )
  R509::Cert.new(:cert => cert)
end

- (R509::Cert) sign(options)

Signs a CSR

Parameters:

  • options (Hash)

    a customizable set of options

Options Hash (options):

  • :csr (R509::CSR)
  • :spki (R509::SPKI)
  • :profile_name (String)

    The CA profile you want to use (eg "server" in your config)

  • :subject (R509::Subject, OpenSSL::X509::Subject, Array) — default: optional for R509::CSR, required for R509::SPKI
  • :san_names (Array, R509::ASN1::GeneralNames)

    optional either an array of names that will be automatically parsed to determine their type, or an explicit R509::ASN1::GeneralNames object

  • :message_digest (String)

    the message digest to use for this certificate instead of the config's default

  • :serial (String)

    the serial number you want to issue the certificate with

  • :not_before (Time)

    the notBefore for the certificate

  • :not_after (Time)

    the notAfter for the certificate

Returns:



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
88
89
90
91
92
93
# File 'lib/r509/certificate_authority.rb', line 34

def sign(options)
  if @config.nil?
    raise R509::R509Error, "When instantiating the signer without a config you can only call #selfsign"
  elsif @config.num_profiles == 0
    raise R509::R509Error, "You must have at least one CAProfile on your CAConfig to issue"
  end

  check_options(options)

  subject, san_names, public_key = extract_public_key_subject_san(options)


  if options.has_key?(:csr) and not options[:csr].verify_signature
    raise R509::R509Error, "Certificate request signature is invalid."
  end

  # prior to OpenSSL 1.0 DSA could only use DSS1 (aka SHA1) signatures. post-1.0 anything
  # goes but at the moment we don't enforce this restriction so an OpenSSL error could
  # bubble up if they do it wrong.
  message_digest = (options.has_key?(:message_digest))? R509::MessageDigest.new(options[:message_digest]) : R509::MessageDigest.new(@config.message_digest)

  profile = @config.profile(options[:profile_name])

  validated_subject = validate_subject(subject,profile)

  cert = build_cert(
    :subject => validated_subject.name,
    :issuer => @config.ca_cert.subject.name,
    :not_before => options[:not_before],
    :not_after => options[:not_after],
    :public_key => public_key,
    :serial => options[:serial]
  )

  basic_constraints = profile.basic_constraints
  key_usage = profile.key_usage
  extended_key_usage = profile.extended_key_usage
  certificate_policies = profile.certificate_policies
  ocsp_no_check = profile.ocsp_no_check

  build_extensions(
    :subject_certificate => cert,
    :issuer_certificate => @config.ca_cert.cert,
    :basic_constraints => basic_constraints,
    :key_usage => key_usage,
    :extended_key_usage => extended_key_usage,
    :ocsp_no_check => ocsp_no_check,
    :certificate_policies => certificate_policies,
    :san_names => san_names,
    :inhibit_any_policy => profile.inhibit_any_policy,
    :policy_constraints => profile.policy_constraints,
    :name_constraints => profile.name_constraints
  )


  #@config.ca_cert.key.key ... ugly. ca_cert returns R509::Cert
  # #key returns R509::PrivateKey and #key on that returns OpenSSL object we need
  cert.sign( @config.ca_cert.key.key, message_digest.digest )
  R509::Cert.new(:cert => cert)
end