aboutsummaryrefslogtreecommitdiffstats
path: root/examples/gen_cert.rb
blob: acb6e18b7d9b38c77f34d5c1d0aec2d235c79821 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/env ruby

require 'openssl'
require 'getopts'

include OpenSSL

passwd_cb = Proc.new{|flag|
  print "Enter password: "
  pass = $stdin.gets.chop!

  # when the flag is true, this passphrase
  # will be used to perform encryption; otherwise it will
  # be used to perform decryption.
  if flag
    print "Verify password: "
    pass2 = $stdin.gets.chop!
    raise "verify failed." if pass != pass2
  end
  pass
}

def usage
  myname = File::basename($0)
  $stderr.puts "Usage: #{myname} [-c ca_cert] [-k ca_key] serial csr.pem"
  exit
end

getopts nil, "c:", "k:", "type:user"

num = ARGV.shift or usage()
csr = ARGV.shift  or usage()
ARGV.empty?      or usage()

cert_type = $OPT_type
$stdout.sync = true

ca_file = $OPT_c || "./0cert.pem"
puts "Reading CA cert (from #{ca_file})"
ca = X509::Certificate.new(File.read(ca_file))

ca_key_file = $OPT_k || "./0key-plain.pem"
puts "Reading CA key (from #{ca_key_file})"
ca_key = PKey::RSA.new(File.read(ca_key_file), &passwd_cb)

puts "Reading CSR (from #{csr})"
req = X509::Request.new(File.read(csr))

cert = X509::Certificate.new
cert.subject = req.subject
cert.issuer = ca.subject
cert.not_before = Time.now
cert.not_after = Time.now + 365 * 24 * 60 * 60
cert.public_key = req.public_key
cert.serial = num.to_i
cert.version = 2 # X509v3

key_usage = []
ext_key_usage = []

case cert_type
when "subca"
  basic_constraint = "CA:TRUE,pathlen:0"
  key_usage << "cRLSign" << "keyCertSign"
when "server"
  basic_constraint = "CA:FALSE"
  key_usage << "nonRepudiation" << "digitalSignature" << "keyEncipherment"
  key_usage << "dataEncipherment"
  ext_key_usage << "serverAuth"
when "ocsp"
  basic_constraint = "CA:FALSE"
  key_usage << "nonRepudiation" << "digitalSignature" << "keyEncipherment"
  key_usage << "dataEncipherment"
  ext_key_usage << "serverAuth" << "OCSPSigning"
when "user"
  basic_constraint = "CA:FALSE"
  key_usage << "nonRepudiation" << "digitalSignature" << "keyEncipherment"
  ext_key_usage << "clientAuth" << "codeSigning" << "emailProtection"
else
  raise "unknonw cert type \"#{cert_type}\" is specified."
end

ext = []
ef = X509::ExtensionFactory.new
ef.subject_certificate = cert
ef.issuer_certificate = ca
ext << ef.create_extension("basicConstraints", basic_constraint, true)
ext << ef.create_extension("keyUsage", key_usage.join(","), true)
if ext_key_usage.size > 0
  ext << ef.create_extension("extendedKeyUsage", ext_key_usage.join(","), false)
end
ext << ef.create_extension("nsComment","Generated by OpenSSL for Ruby.")
ext << ef.create_extension("subjectKeyIdentifier", "hash")
ext << ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
cert.extensions = ext
cert.sign(ca_key, Digest::SHA1.new)

cert_file = "./#{cert.serial}cert.pem"
puts "Writing #{cert_file}."
File.open(cert_file, "w") do |f|
  f << cert.to_pem
end

puts "DONE. (Generated certificate for '#{cert.subject}')"