Class: R509::Csr

Inherits:
Object
  • Object
show all
Includes:
IOHelpers
Defined in:
lib/r509/csr.rb

Overview

The primary certificate signing request object

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from IOHelpers

#read_data, read_data, #write_data, write_data

Constructor Details

- (Csr) initialize(opts = {})

you can also pass OIDs (see tests)

Examples:

['CN','langui.sh'],,['L','Chicago'],,['emailAddress','ca@langui.sh']


    
  

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :csr (String, OpenSSL::X509::Request)

    a csr

  • :type (Symbol)

    :rsa/:dsa

  • :bit_strength (Integer)
  • :san_names (Array)

    List of domains to encode as subjectAltNames

  • :subject (R509::Subject, Array, OpenSSL::X509::Name)

    array of subject items

  • :cert (String, R509::Cert, OpenSSL::X509::Certificate)

    takes a cert (used for generating a CSR with the certificate's values)

  • :key (R509::PrivateKey, String)

    optional private key to supply. either an unencrypted PEM/DER string or an R509::PrivateKey object (use the latter if you need password/hardware support)



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
# File 'lib/r509/csr.rb', line 21

def initialize(opts={})
    if not opts.kind_of?(Hash)
        raise ArgumentError, 'Must provide a hash of options'
    end
    if (opts.has_key?(:cert) and opts.has_key?(:subject)) or
        (opts.has_key?(:cert) and opts.has_key?(:csr)) or
        (opts.has_key?(:subject) and opts.has_key?(:csr))
        raise ArgumentError, "Can only provide one of cert, subject, or csr"
    end
    @bit_strength = opts[:bit_strength] || 2048

    if opts.has_key?(:key)
        if opts[:key].kind_of?(R509::PrivateKey)
            @key = opts[:key]
        else
            @key = R509::PrivateKey.new(:key => opts[:key])
        end
    end

    @type = opts[:type] || :rsa
    if @type != :rsa and @type != :dsa and @key.nil?
        raise ArgumentError, 'Must provide :rsa or :dsa as type when key is nil'
    end

    if opts.has_key?(:cert)
        domains = opts[:san_names] || []
        parsed_domains = prefix_domains(domains)
        cert_data = parse_cert(opts[:cert])
        merged_domains = cert_data[:subjectAltName].concat(parsed_domains)
        create_request(cert_data[:subject],merged_domains) #sets @req
    elsif opts.has_key?(:subject)
        domains = opts[:san_names] || []
        parsed_domains = prefix_domains(domains)
        create_request(opts[:subject], parsed_domains) #sets @req
    elsif opts.has_key?(:csr)
        if opts.has_key?(:san_names)
            raise ArgumentError, "You can't add domains to an existing CSR"
        end
        parse_csr(opts[:csr])
    else
        raise ArgumentError, "Must provide one of cert, subject, or csr"
    end

    if dsa?
        #only DSS1 is acceptable for DSA signing in OpenSSL < 1.0
        #post-1.0 you can sign with anything, but let's be conservative
        #see: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/PKey/DSA.html
        @message_digest = R509::MessageDigest.new('dss1')
    elsif opts.has_key?(:message_digest)
        @message_digest = R509::MessageDigest.new(opts[:message_digest])
    else
        @message_digest = R509::MessageDigest.new('sha1')
    end

    if not opts.has_key?(:csr)
        @req.sign(@key.key, @message_digest.digest)
    end
    if not @key.nil? and not @req.verify(@key.public_key) then
        raise R509Error, 'Key does not match request.'
    end

end

Instance Attribute Details

- (Object) attributes (readonly)

Returns the value of attribute attributes



11
12
13
# File 'lib/r509/csr.rb', line 11

def attributes
  @attributes
end

- (Object) key (readonly)

Returns the value of attribute key



11
12
13
# File 'lib/r509/csr.rb', line 11

def key
  @key
end

- (Object) message_digest (readonly)

Returns the value of attribute message_digest



11
12
13
# File 'lib/r509/csr.rb', line 11

def message_digest
  @message_digest
end

- (Object) req (readonly)

Returns the value of attribute req



11
12
13
# File 'lib/r509/csr.rb', line 11

def req
  @req
end

- (Object) san_names (readonly)

Returns the value of attribute san_names



11
12
13
# File 'lib/r509/csr.rb', line 11

def san_names
  @san_names
end

- (Object) subject (readonly)

Returns the value of attribute subject



11
12
13
# File 'lib/r509/csr.rb', line 11

def subject
  @subject
end

Class Method Details

+ (R509::Csr) load_from_file(filename)

Helper method to quickly load a CSR from the filesystem

Parameters:

  • filename (String)

    Path to file you want to load

Returns:



88
89
90
# File 'lib/r509/csr.rb', line 88

def self.load_from_file( filename )
    return R509::Csr.new(:csr => IOHelpers.read_data(filename) )
end

Instance Method Details

- (Integer) bit_strength

Returns the bit strength of the key used to create the CSR

Returns:

  • (Integer)

    the integer bit strength.



162
163
164
165
166
167
168
# File 'lib/r509/csr.rb', line 162

def bit_strength
    if self.rsa?
        return @req.public_key.n.num_bits
    elsif self.dsa?
        return @req.public_key.p.num_bits
    end
end

- (Boolean) dsa?

Returns whether the public key is DSA

Returns:

  • (Boolean)

    true if the public key is DSA, false otherwise



156
157
158
# File 'lib/r509/csr.rb', line 156

def dsa?
    @req.public_key.kind_of?(OpenSSL::PKey::DSA)
end

- (Boolean) has_private_key?

Boolean of whether the object contains a private key

Returns:

  • (Boolean)

    Boolean of whether the object contains a private key



106
107
108
109
110
111
112
# File 'lib/r509/csr.rb', line 106

def has_private_key?
    if not @key.nil?
        true
    else
        false
    end
end

- (String) key_algorithm

Returns key algorithm (RSA/DSA)

Returns:

  • (String)

    value of the key algorithm. RSA or DSA



192
193
194
195
196
197
198
# File 'lib/r509/csr.rb', line 192

def key_algorithm
    if @req.public_key.kind_of? OpenSSL::PKey::RSA then
        'RSA'
    elsif @req.public_key.kind_of? OpenSSL::PKey::DSA then
        'DSA'
    end
end

- (OpenSSL::PKey::RSA) public_key

Public key

Returns:

  • (OpenSSL::PKey::RSA)

    public key



93
94
95
96
97
# File 'lib/r509/csr.rb', line 93

def public_key
    if(@req.kind_of?(OpenSSL::X509::Request)) then
        @req.public_key
    end
end

- (Boolean) rsa?

Returns whether the public key is RSA

Returns:

  • (Boolean)

    true if the public key is RSA, false otherwise



149
150
151
# File 'lib/r509/csr.rb', line 149

def rsa?
    @req.public_key.kind_of?(OpenSSL::PKey::RSA)
end

- (String) signature_algorithm

Returns signature algorithm

Returns:

  • (String)

    value of the signature algorithm. E.g. sha1WithRSAEncryption, sha256WithRSAEncryption, md5WithRSAEncryption



185
186
187
# File 'lib/r509/csr.rb', line 185

def signature_algorithm
    @req.signature_algorithm
end

- (String) subject_component(short_name)

Returns subject component

Returns:

  • (String)

    value of the subject component requested



173
174
175
176
177
178
179
180
# File 'lib/r509/csr.rb', line 173

def subject_component short_name
    @req.subject.to_a.each do |element|
        if element[0].downcase == short_name.downcase then
            return element[1]
        end
    end
    nil
end

- (String) to_der

Converts the CSR into the DER format

Returns:

  • (String)

    the CSR converted into DER format.



126
127
128
# File 'lib/r509/csr.rb', line 126

def to_der
    @req.to_der
end

- (Hash) to_hash

Returns a hash structure you can pass to the Ca. You will want to call this method if you intend to alter the values and then pass them to the Ca class.

Returns:

  • (Hash)

    :subject and :san_names you can pass to Ca



205
206
207
# File 'lib/r509/csr.rb', line 205

def to_hash
    { :subject => @subject.dup , :san_names => @san_names.dup }
end

- (String) to_pem Also known as: to_s

Converts the CSR into the PEM format

Returns:

  • (String)

    the CSR converted into PEM format.



117
118
119
# File 'lib/r509/csr.rb', line 117

def to_pem
    @req.to_pem
end

- (Boolean) verify_signature

Verifies the integrity of the signature on the request

Returns:

  • (Boolean)


101
102
103
# File 'lib/r509/csr.rb', line 101

def verify_signature
    @req.verify(public_key)
end

- (Object) write_der(filename_or_io)

Writes the CSR into the DER format

Parameters:

  • filename_or_io (String, #write)

    Either a string of the path for the file that you'd like to write, or an IO-like object.



142
143
144
# File 'lib/r509/csr.rb', line 142

def write_der(filename_or_io)
    write_data(filename_or_io, @req.to_der)
end

- (Object) write_pem(filename_or_io)

Writes the CSR into the PEM format

Parameters:

  • filename_or_io (String, #write)

    Either a string of the path for the file that you'd like to write, or an IO-like object.



134
135
136
# File 'lib/r509/csr.rb', line 134

def write_pem(filename_or_io)
    write_data(filename_or_io, @req.to_pem)
end