bin/r509 in r509-0.8.1 vs bin/r509 in r509-0.9
- old
+ new
@@ -1,143 +1,157 @@
-#!/usr/bin/ruby
+#!/usr/bin/env ruby
require 'rubygems'
require 'r509'
-require 'r509/version'
-require 'openssl'
require 'trollop'
opts = Trollop::options do
- opt :interactive, "Interactive CSR/self-signed certificate generation. Overrides all flags other than keyout and out."
- opt :subject, "X509 subject / delimited. Example: /CN=test.com/O=Org/C=US/ST=Illinois/L=Chicago", :type => :string
- opt :message_digest, "Message digest to use. sha1, sha256, sha512, md5", :type => :string, :default => 'sha1'
- opt :duration, "Self-sign the certificate with the duration (in days) specified.", :type => :integer
- opt :bits, "Bit length of generated key.", :type => :integer, :default => 2048
- opt :keyout, "File name to save generated key.", :type => :string
- opt :out, "File name to save generated CSR or self-signed certificate", :type => :string
- version "r509 #{R509::VERSION}"
+ opt :interactive, "Interactive CSR/self-signed certificate generation. Overrides all flags other than keyout and out."
+ opt :subject, "X509 subject / delimited. Example: /CN=test.com/O=Org/C=US/ST=Illinois/L=Chicago", :type => :string
+ opt :message_digest, "Message digest to use. sha1, sha224, sha256, sha384, sha512, md5", :type => :string, :default => 'sha1'
+ opt :duration, "Self-sign the certificate with the duration (in days) specified.", :type => :integer
+ opt :bits, "Bit length of generated key. Ignored for EC.", :type => :integer, :default => 2048
+ opt :curve_name, "Name of elliptic curve to use. Only used for EC.", :type => :string, :default => 'secp384r1'
+ opt :keyout, "File name to save generated key.", :type => :string
+ opt :out, "File name to save generated CSR or self-signed certificate", :type => :string
+ opt :type, "Type of key to generate. RSA/DSA/EC", :type => :string, :default => "RSA"
+ version "r509 #{R509::VERSION}"
end
if opts[:interactive] == true or opts[:subject].nil? then
+ if opts[:type].upcase == "RSA" or opts[:type].upcase == "DSA"
print "CSR Bit Strength (2048):"
bit_strength = gets.chomp
bit_strength = (bit_strength.to_i > 0)? bit_strength.to_i : 2048
+ elsif opts[:type].upcase == "EC"
+ print "Curve Name (secp384r1):"
+ curve_name = gets.chomp
+ curve_name = (not curve_name.empty?)? curve_name : 'secp384r1'
+ else
+ puts "Invalid key type specified. RSA/DSA/EC"
+ exit
+ end
- print "Message Digest (sha1):"
- md = gets.chomp
- md = case md
- when 'sha1' then 'sha1'
- when 'sha256' then 'sha256'
- when 'sha512' then 'sha512'
- when 'md5' then 'md5'
- else 'sha1'
- end
+ print "Message Digest (sha1):"
+ md = gets.chomp
+ opts[:message_digest] = case md
+ when 'sha1' then 'sha1'
+ when 'sha224' then 'sha224'
+ when 'sha256' then 'sha256'
+ when 'sha384' then 'sha384'
+ when 'sha512' then 'sha512'
+ when 'md5' then 'md5'
+ else 'sha1'
+ end
- subject = []
- print "C (US): "
- c = gets.chomp
- c = c.empty? ? 'US':c;
- subject.push ['C',c]
+ subject = []
+ print "C (US): "
+ c = gets.chomp
+ c = c.empty? ? 'US':c;
+ subject.push ['C',c]
- print "ST (Illinois): "
- st = gets.chomp
- st = st.empty? ? 'Illinois':st;
- subject.push ['ST',st]
+ print "ST (Illinois): "
+ st = gets.chomp
+ st = st.empty? ? 'Illinois':st;
+ subject.push ['ST',st]
- print "L (Chicago): "
- l = gets.chomp
- l = l.empty? ? 'Chicago':l;
- subject.push ['L',l]
+ print "L (Chicago): "
+ l = gets.chomp
+ l = l.empty? ? 'Chicago':l;
+ subject.push ['L',l]
- print "O (r509 LLC): "
- o = gets.chomp
- o = o.empty? ? 'r509 LLC':o;
- subject.push ['O',o]
+ print "O (r509 LLC): "
+ o = gets.chomp
+ o = o.empty? ? 'r509 LLC':o;
+ subject.push ['O',o]
- print "OU (null by default): "
- ou = gets.chomp
- if(!ou.empty?) then
- subject.push ['OU',ou]
- end
+ print "OU (null by default): "
+ ou = gets.chomp
+ if(!ou.empty?) then
+ subject.push ['OU',ou]
+ end
- print "CN: "
- subject.push ['CN',gets.chomp]
- print "SAN Domains (comma separated):"
- san_domains = []
- san_domains = gets.chomp.split(',').collect { |domain| domain.strip }
- csr = R509::Csr.new(
- :subject => subject,
- :bit_strength => bit_strength,
- :san_names => san_domains,
- :message_digest => md
- )
+ print "CN: "
+ subject.push ['CN',gets.chomp]
+ print "SAN Domains (comma separated):"
+ san_domains = []
+ san_domains = gets.chomp.split(',').collect { |domain| domain.strip }
+ csr = R509::CSR.new(
+ :subject => subject,
+ :bit_strength => bit_strength,
+ :type => opts[:type].downcase.to_sym,
+ :curve_name => curve_name,
+ :san_names => san_domains,
+ :message_digest => opts[:message_digest]
+ )
- selfsign = 0
- print "Self-signed cert duration in days (null disables self-sign):"
- selfsign_input = gets.chomp
- if selfsign_input.to_i > 0
- selfsign = selfsign_input.to_i
- end
+ selfsign = 0
+ print "Self-signed cert duration in days (null disables self-sign):"
+ selfsign_input = gets.chomp
+ if selfsign_input.to_i > 0
+ selfsign = selfsign_input.to_i
+ end
elsif not opts[:subject].nil?
- subject = OpenSSL::X509::Name.new
- opts[:subject].chomp.split('/').each { |item|
- if item != '' then
- value = item.split('=')
- subject.add_entry(value[0],value[1])
- end
- }
- bit_strength = opts[:bits]
- csr = R509::Csr.new(
- :subject => subject,
- :bit_strength => bit_strength,
- :message_digest => opts[:message_digest]
- )
- selfsign = opts[:duration] || 0
+ subject = OpenSSL::X509::Name.new
+ opts[:subject].chomp.split('/').each { |item|
+ if item != '' then
+ value = item.split('=')
+ subject.add_entry(value[0],value[1])
+ end
+ }
+ csr = R509::CSR.new(
+ :subject => subject,
+ :bit_strength => opts[:bits],
+ :type => opts[:type].downcase.to_sym,
+ :curve_name => opts[:curve_name],
+ :message_digest => opts[:message_digest]
+ )
+ selfsign = opts[:duration] || 0
end
if selfsign > 0
- ca = R509::CertificateAuthority::Signer.new
- cert = ca.selfsign(
- :csr => csr,
- :not_after => Time.now.to_i+86400*selfsign,
- :message_digest => opts[:message_digest]
- )
- if opts[:keyout].nil?
- puts csr.key.to_pem
- else
- File.open(opts[:keyout], 'w') {|f| f.write(csr.key.to_pem) }
- end
- if opts[:out].nil?
- puts cert.to_pem
- else
- File.open(opts[:out], 'w') {|f| f.write(cert.to_pem) }
- end
+ ca = R509::CertificateAuthority::Signer.new
+ cert = ca.selfsign(
+ :csr => csr,
+ :not_after => Time.now.to_i+86400*selfsign,
+ :message_digest => opts[:message_digest]
+ )
+ if opts[:keyout].nil?
+ puts csr.key.to_pem
+ else
+ File.open(opts[:keyout], 'w') {|f| f.write(csr.key.to_pem) }
+ end
+ if opts[:out].nil?
+ puts cert.to_pem
+ else
+ File.open(opts[:out], 'w') {|f| f.write(cert.to_pem) }
+ end
- puts cert.subject
- if not cert.san_names.empty?
- puts "SAN(s): "+cert.san_names.join(", ")
- end
+ puts cert.subject
+ if not cert.san.nil?
+ puts "SAN(s): "+cert.san.names.map { |n| n.value }.join(", ")
+ end
else
- if opts[:keyout].nil?
- puts csr.key.to_pem
- else
- File.open(opts[:keyout], 'w') {|f| f.write(csr.key.to_pem) }
- end
+ if opts[:keyout].nil?
+ puts csr.key.to_pem
+ else
+ File.open(opts[:keyout], 'w') {|f| f.write(csr.key.to_pem) }
+ end
- if opts[:out].nil?
- puts csr.to_pem
- else
- File.open(opts[:out], 'w') {|f| f.write(csr.to_pem) }
- end
+ if opts[:out].nil?
+ puts csr.to_pem
+ else
+ File.open(opts[:out], 'w') {|f| f.write(csr.to_pem) }
+ end
- puts csr.subject
- if not csr.san_names.empty?
- puts "SAN(s): "+csr.san_names.join(", ")
- end
+ puts csr.subject
+ if not csr.san.nil?
+ puts "SAN(s): "+csr.san.names.map{|n| n.value}.join(", ")
+ end
end
if RUBY_PLATFORM.match('darwin') != nil then
- if selfsign > 0
- IO.popen('pbcopy','w').puts cert
- else
- IO.popen('pbcopy','w').puts csr
- end
+ if selfsign > 0
+ IO.popen('pbcopy','w').puts cert
+ else
+ IO.popen('pbcopy','w').puts csr
+ end
end