lib/r509/csr.rb in r509-0.10.0 vs lib/r509/csr.rb in r509-1.0
- old
+ new
@@ -16,11 +16,11 @@
# @option opts [String,OpenSSL::X509::Request] :csr a csr
# @option opts [String] :type Required if not providing existing :csr. Defaults to R509::PrivateKey::DEFAULT_TYPE. Allows R509::PrivateKey::KNOWN_TYPES.
# @option opts [String] :curve_name ("secp384r1") Only used if :type is EC
# @option opts [Integer] :bit_length (2048) Only used if :type is RSA or DSA
# @option opts [Integer] :bit_strength (2048) Deprecated, identical to bit_length.
- # @option opts [String] :message_digest Optional digest. sha1, sha224, sha256, sha384, sha512, md5. Defaults to sha1
+ # @option opts [String] :message_digest Optional digest. sha1, sha224, sha256, sha384, sha512, md5. Defaults to sha256
# @option opts [Array,R509::ASN1::GeneralNames] :san_names List of domains, IPs, email addresses, or URIs to encode as subjectAltNames. The type is determined from the structure of the strings via the R509::ASN1.general_name_parser method. You can also pass an explicit R509::ASN1::GeneralNames object. Parsed names will be uniqued, but a GeneralNames object will not be touched.
# @option opts [R509::Subject,Array,OpenSSL::X509::Name] :subject array of subject items
# @option opts [R509::PrivateKey,String] :key 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)
# @example Generate a 4096-bit RSA key + CSR
# :type => "RSA",
@@ -41,96 +41,93 @@
# :curve_name => 'secp384r1',
# :message_digest => 'sha512',
# :subject => [
# ['CN','somedomain.com'],
# ]
- def initialize(opts={})
- if not opts.kind_of?(Hash)
+ def initialize(opts = {})
+ unless opts.is_a?(Hash)
raise ArgumentError, 'Must provide a hash of options'
end
- if opts.has_key?(:subject) and opts.has_key?(:csr)
+ if opts.key?(:subject) && opts.key?(:csr)
raise ArgumentError, "You must provide :subject or :csr, not both"
end
@bit_length = opts[:bit_length] || opts[:bit_strength] || R509::PrivateKey::DEFAULT_STRENGTH
@curve_name = opts[:curve_name] || R509::PrivateKey::DEFAULT_CURVE
@key = load_private_key(opts)
-
@type = opts[:type] || R509::PrivateKey::DEFAULT_TYPE
- if not R509::PrivateKey::KNOWN_TYPES.include?(@type.upcase) and @key.nil?
+ if !R509::PrivateKey::KNOWN_TYPES.include?(@type.upcase) && @key.nil?
raise ArgumentError, "Must provide #{R509::PrivateKey::KNOWN_TYPES.join(", ")} as type when key is nil"
end
- if opts.has_key?(:subject)
+ if opts.key?(:subject)
san_names = R509::ASN1.general_name_parser(opts[:san_names])
- create_request(opts[:subject], san_names) #sets @req
- elsif opts.has_key?(:csr)
- if opts.has_key?(:san_names)
+ create_request(opts[:subject], san_names) # sets @req
+ elsif opts.key?(:csr)
+ if opts.key?(:san_names)
raise ArgumentError, "You can't add domains to an existing CSR"
end
parse_csr(opts[:csr])
else
raise ArgumentError, "You must provide :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
+ # 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')
else
@message_digest = R509::MessageDigest.new(opts[:message_digest])
end
- if not opts.has_key?(:csr)
+ unless opts.key?(:csr)
@req.sign(@key.key, @message_digest.digest)
end
- if not @key.nil? and not @req.verify(@key.public_key) then
+ if @key && !@req.verify(@key.public_key)
raise R509Error, 'Key does not match request.'
end
-
end
# Helper method to quickly load a CSR from the filesystem
#
# @param [String] filename Path to file you want to load
# @return [R509::CSR] CSR object
- def self.load_from_file( filename )
- return R509::CSR.new(:csr => IOHelpers.read_data(filename) )
+ def self.load_from_file(filename)
+ R509::CSR.new(:csr => IOHelpers.read_data(filename))
end
# @return [OpenSSL::PKey::RSA,OpenSSL::PKey::DSA,OpenSSL::PKey::EC] public key
def public_key
- if(@req.kind_of?(OpenSSL::X509::Request)) then
- @req.public_key
- end
+ @req.public_key
end
# Verifies the integrity of the signature on the request
# @return [Boolean]
def verify_signature
@req.verify(public_key)
end
# @return [Boolean] Boolean of whether the object contains a private key
def has_private_key?
- if not @key.nil?
+ if @key
true
else
false
end
end
- alias :to_s :to_pem
+ alias_method :to_s, :to_pem
# Returns subject component
+ # @param [String] short_name short name subject component (e.g. CN, O, ST)
#
# @return [String] value of the subject component requested
- def subject_component short_name
+ def subject_component(short_name)
@req.subject.to_a.each do |element|
- if element[0].downcase == short_name.downcase then
+ if element[0].downcase == short_name.downcase
return element[1]
end
end
nil
end
@@ -144,49 +141,49 @@
# Returns key algorithm (RSA/DSA/EC)
#
# @return [String] value of the key algorithm. RSA, DSA, or EC
def key_algorithm
- if @req.public_key.kind_of? OpenSSL::PKey::RSA then
+ if @req.public_key.is_a? OpenSSL::PKey::RSA
"RSA"
- elsif @req.public_key.kind_of? OpenSSL::PKey::DSA then
+ elsif @req.public_key.is_a? OpenSSL::PKey::DSA
"DSA"
- elsif @req.public_key.kind_of? OpenSSL::PKey::EC then
+ elsif @req.public_key.is_a? OpenSSL::PKey::EC
"EC"
end
end
private
def parse_csr(csr)
begin
@req = OpenSSL::X509::Request.new csr
rescue OpenSSL::X509::RequestError
- #let's try to load this thing by handling a few
- #common error cases
- if csr.kind_of?(String)
- #normalize line endings (really just for the next replace)
+ # let's try to load this thing by handling a few
+ # common error cases
+ if csr.is_a?(String)
+ # normalize line endings (really just for the next replace)
csr.gsub!(/\r\n?/, "\n")
- #remove extraneous newlines
- csr.gsub!(/^\s*\n/,'')
- #and leading/trailing whitespace
- csr.gsub!(/^\s*|\s*$/,'')
- if not csr.match(/-----BEGIN.+-----/) and csr.match(/MII/)
- #if csr is probably PEM (MII is the beginning of every base64
- #encoded DER) then add the wrapping lines if they aren't provided.
- #tools like Microsoft's xenroll do this.
- csr = "-----BEGIN CERTIFICATE REQUEST-----\n"+csr+"\n-----END CERTIFICATE REQUEST-----"
+ # remove extraneous newlines
+ csr.gsub!(/^\s*\n/, '')
+ # and leading/trailing whitespace
+ csr.gsub!(/^\s*|\s*$/, '')
+ if !csr.match(/-----BEGIN.+-----/) && csr.match(/MII/)
+ # if csr is probably PEM (MII is the beginning of every base64
+ # encoded DER) then add the wrapping lines if they aren't provided.
+ # tools like Microsoft's xenroll do this.
+ csr = "-----BEGIN CERTIFICATE REQUEST-----\n" + csr + "\n-----END CERTIFICATE REQUEST-----"
end
end
- #and now we try again...
+ # and now we try again...
@req = OpenSSL::X509::Request.new csr
end
@subject = R509::Subject.new(@req.subject)
parse_san_attribute_from_csr(@req)
end
- def create_request(subject,san_names)
+ def create_request(subject, san_names)
@req = OpenSSL::X509::Request.new
@req.version = 0
@subject = R509::Subject.new(subject)
@req.subject = @subject.name
if @key.nil?
@@ -199,34 +196,31 @@
# @return [Array] array of GeneralName objects
def parse_san_attribute_from_csr(req)
req.attributes.each do |attribute|
if attribute.oid == 'extReq'
set = OpenSSL::ASN1.decode attribute.value
- extensions = set.value[0].value.collect{|asn1ext| OpenSSL::X509::Extension.new(asn1ext) }
- r509_extensions = R509::Cert::Extensions.wrap_openssl_extensions( extensions )
- if not r509_extensions[R509::Cert::Extensions::SubjectAlternativeName].nil?
+ extensions = set.value[0].value.map { |asn1ext| OpenSSL::X509::Extension.new(asn1ext) }
+ r509_extensions = R509::Cert::Extensions.wrap_openssl_extensions(extensions)
+ unless r509_extensions[R509::Cert::Extensions::SubjectAlternativeName].nil?
@san = r509_extensions[R509::Cert::Extensions::SubjectAlternativeName].general_names
end
break
end
end
end
def add_san_extension(san_names)
- if san_names.kind_of?(R509::ASN1::GeneralNames) and not san_names.names.empty?
- ef = OpenSSL::X509::ExtensionFactory.new
- serialized = san_names.serialize_names
- ef.config = OpenSSL::Config.parse(serialized[:conf])
- ex = []
- ex << ef.create_extension("subjectAltName", serialized[:extension_string])
- request_extension_set = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(ex)])
- @req.add_attribute(OpenSSL::X509::Attribute.new("extReq", request_extension_set))
- parse_san_attribute_from_csr(@req)
- end
+ return unless san_names.is_a?(R509::ASN1::GeneralNames) && !san_names.names.empty?
+ ef = OpenSSL::X509::ExtensionFactory.new
+ serialized = san_names.serialize_names
+ ef.config = OpenSSL::Config.parse(serialized[:conf])
+ ex = []
+ ex << ef.create_extension("subjectAltName", serialized[:extension_string])
+ request_extension_set = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(ex)])
+ @req.add_attribute(OpenSSL::X509::Attribute.new("extReq", request_extension_set))
+ parse_san_attribute_from_csr(@req)
end
- def internal_obj
- @req
- end
-
+ # Returns the proper instance variable
+ alias_method :internal_obj, :req
end
end