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/:ec

  • :curve_name (String) — default: "secp384r1"

    Only used if :type is :ec

  • :bit_strength (Integer) — default: 2048

    Only used if :type is :rsa or :dsa

  • :message_digest (String)

    Optional digest. sha1, sha224, sha256, sha384, sha512, md5. Defaults to sha1

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



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

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
  @curve_name = opts[:curve_name] || "secp384r1"

  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 not [:rsa,:dsa,:ec].include?(@type) and @key.nil?
    raise ArgumentError, 'Must provide :rsa, :dsa, or :ec 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



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

def attributes
  @attributes
end

- (Object) key (readonly)

Returns the value of attribute key



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

def key
  @key
end

- (Object) message_digest (readonly)

Returns the value of attribute message_digest



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

def message_digest
  @message_digest
end

- (Object) req (readonly)

Returns the value of attribute req



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

def req
  @req
end

- (Object) san_names (readonly)

Returns the value of attribute san_names



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

def san_names
  @san_names
end

- (Object) subject (readonly)

Returns the value of attribute subject



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

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:



92
93
94
# File 'lib/r509/csr.rb', line 92

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.



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

def bit_strength
  if self.rsa?
    return @req.public_key.n.num_bits
  elsif self.dsa?
    return @req.public_key.p.num_bits
  elsif self.ec?
    raise R509::R509Error, 'Bit strength is not available for EC at this time.'
  end
end

- (String) curve_name

Returns the short name of the elliptic curve used to generate the public key if the key is EC. If not, raises an error.

Returns:

  • (String)

    elliptic curve name



187
188
189
190
191
192
193
# File 'lib/r509/csr.rb', line 187

def curve_name
  if self.ec?
    self.public_key.group.curve_name
  else
    raise R509::R509Error, 'Curve name is only available with EC CSRs'
  end
end

- (Boolean) dsa?

Returns whether the public key is DSA

Returns:

  • (Boolean)

    true if the public key is DSA, false otherwise



160
161
162
# File 'lib/r509/csr.rb', line 160

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

- (Boolean) ec?

Returns whether the public key is EC

Returns:

  • (Boolean)

    true if the public key is EC, false otherwise



167
168
169
# File 'lib/r509/csr.rb', line 167

def ec?
  @req.public_key.kind_of?(OpenSSL::PKey::EC)
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



110
111
112
113
114
115
116
# File 'lib/r509/csr.rb', line 110

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

- (String) key_algorithm

Returns key algorithm (RSA/DSA/EC)

Returns:

  • (String)

    value of the key algorithm. RSA, DSA, EC



217
218
219
220
221
222
223
224
225
# File 'lib/r509/csr.rb', line 217

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'
  elsif @req.public_key.kind_of? OpenSSL::PKey::EC then
    'EC'
  end
end

- (OpenSSL::PKey::RSA, ...) public_key

Public key

Returns:



97
98
99
100
101
# File 'lib/r509/csr.rb', line 97

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



153
154
155
# File 'lib/r509/csr.rb', line 153

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



210
211
212
# File 'lib/r509/csr.rb', line 210

def signature_algorithm
  @req.signature_algorithm
end

- (String) subject_component(short_name)

Returns subject component

Returns:

  • (String)

    value of the subject component requested



198
199
200
201
202
203
204
205
# File 'lib/r509/csr.rb', line 198

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.



130
131
132
# File 'lib/r509/csr.rb', line 130

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



232
233
234
# File 'lib/r509/csr.rb', line 232

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.



121
122
123
# File 'lib/r509/csr.rb', line 121

def to_pem
  @req.to_pem
end

- (Boolean) verify_signature

Verifies the integrity of the signature on the request

Returns:

  • (Boolean)


105
106
107
# File 'lib/r509/csr.rb', line 105

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.



146
147
148
# File 'lib/r509/csr.rb', line 146

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.



138
139
140
# File 'lib/r509/csr.rb', line 138

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