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}')"
|