Class: R509::CertificateAuthority::Signer

Inherits:
Object
  • Object
show all
Defined in:
lib/r509/certificateauthority.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:



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

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)

    Optional array of subject alternative names

Returns:



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/r509/certificateauthority.rb', line 121

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]
    )

    if options.has_key?(:san_names)
        san_names = options[:san_names]
    else
        san_names = csr.san_names
    end

    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)

  • :data_hash (Hash)

    a hash containing the subject and SAN names you want encoded for this cert. Generate by calling Csr#to_hash or Spki#to_hash

  • :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:



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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/r509/certificateauthority.rb', line 32

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

    if options.has_key?(:csr) and options.has_key?(:spki)
        raise ArgumentError, "You can't pass both :csr and :spki"
    elsif not options.has_key?(:csr) and not options.has_key?(:spki)
        raise ArgumentError, "You must supply either :csr or :spki"
    elsif options.has_key?(:csr)
        if not options[:csr].kind_of?(R509::Csr)
            raise ArgumentError, "You must pass an R509::Csr object for :csr"
        else
            signable_object = options[:csr]
        end
    elsif not options.has_key?(:csr) and options.has_key?(:spki)
        if not options[:spki].kind_of?(R509::Spki)
            raise ArgumentError, "You must pass an R509::Spki object for :spki"
        else
            signable_object = options[:spki]
        end
    end

    if options.has_key?(:data_hash)
        san_names = options[:data_hash][:san_names]
        subject = options[:data_hash][:subject]
    else
        san_names = signable_object.to_hash[:san_names]
        subject = signable_object.to_hash[:subject]
    end



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

    #handle DSA here
    if options.has_key?(:message_digest)
        message_digest = R509::MessageDigest.new(options[:message_digest])
    else
        message_digest = R509::MessageDigest.new(@config.message_digest)
    end

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

    validated_subject = validate_subject(subject,profile)

    cert = build_cert(
        :subject => validated_subject.name,
        :issuer => @config.ca_cert.subject,
        :not_before => options[:not_before],
        :not_after => options[:not_after],
        :public_key => signable_object.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

    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,
        :certificate_policies => certificate_policies,
        :san_names => san_names
    )


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