/
create_certs.rb
168 lines (134 loc) · 4.49 KB
/
create_certs.rb
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# frozen_string_literal: true
require 'openssl'
class CertificateBuilder
attr_reader :start
def initialize(key_size = 2048)
@start = Time.utc 2012, 01, 01, 00, 00, 00
@end_of_time = Time.utc 9999, 12, 31, 23, 59, 59
@end_of_time_32 = Time.utc 2038, 01, 19, 03, 14, 07
@key_size = key_size
@serial = 0
end
def create_certificates(key, subject, issuer_key = key, issuer_cert = nil,
not_before: @start, not_after: :end_of_time,
is_ca: false)
certificates = []
not_before, not_before_32 = validity_for not_before
not_after, not_after_32 = validity_for not_after
issuer_cert, issuer_cert_32 = issuer_cert
certificates <<
create_certificate(key, subject, issuer_key, issuer_cert,
not_before, not_after, is_ca)
certificates <<
create_certificate(key, subject, issuer_key, issuer_cert_32,
not_before_32, not_after_32, is_ca)
certificates
end
def create_certificate(key, subject, issuer_key, issuer_cert,
not_before, not_after, is_ca)
cert = OpenSSL::X509::Certificate.new
issuer_cert ||= cert # if not specified, create self signing cert
cert.version = 2
cert.serial = 0
cert.not_before = not_before
cert.not_after = not_after
cert.serial = next_serial
cert.public_key = key.public_key
cert.subject = OpenSSL::X509::Name.new [%W[CN #{subject}], %w[DC example]]
cert.issuer = issuer_cert.subject
ef = OpenSSL::X509::ExtensionFactory.new issuer_cert, cert
cert.extensions = [
ef.create_extension('subjectAltName', "email:#{subject}@example"),
ef.create_extension('subjectKeyIdentifier', 'hash'),
]
if cert != issuer_cert # not self-signed cert
cert.add_extension ef.create_extension('authorityKeyIdentifier', 'keyid:always')
end
if is_ca
cert.add_extension ef.create_extension('basicConstraints', 'CA:TRUE', true)
cert.add_extension ef.create_extension('keyUsage', 'keyCertSign', true)
end
cert.sign issuer_key, 'SHA1'
puts "created cert - subject: #{cert.subject}, issuer: #{cert.issuer}"
cert
end
def create_key
puts "creating key"
OpenSSL::PKey::RSA.new @key_size
end
def create_keys(names)
keys = {}
names.each do |name|
keys[name] = create_key
end
keys
end
def next_serial
serial = @serial
@serial += 1
serial
end
def validity_for(time)
if time == :end_of_time
validity = @end_of_time
validity_32 = @end_of_time_32
else
validity = validity_32 = time
end
[validity, validity_32]
end
end
cb = CertificateBuilder.new
keys = cb.create_keys [
:alternate,
:child,
:grandchild,
:invalid,
:invalidchild,
:private,
]
keys[:public] = keys[:private].public_key
certs = {}
certs[:public] =
cb.create_certificates(keys[:private], 'nobody',
is_ca: true)
certs[:child] =
cb.create_certificates(keys[:child], 'child',
keys[:private], certs[:public],
is_ca: true)
certs[:alternate] =
cb.create_certificates(keys[:alternate], 'alternate')
certs[:expired] =
cb.create_certificates(keys[:private], 'nobody',
not_before: Time.at(0),
not_after: Time.at(0))
certs[:future] =
cb.create_certificates(keys[:private], 'nobody',
not_before: :end_of_time,
not_after: :end_of_time)
certs[:invalid_issuer] =
cb.create_certificates(keys[:invalid], 'invalid',
keys[:invalid], certs[:public],
is_ca: true)
certs[:grandchild] =
cb.create_certificates(keys[:grandchild], 'grandchild',
keys[:child], certs[:child])
certs[:invalid_signer] =
cb.create_certificates(keys[:invalid], 'invalid',
keys[:private], certs[:invalid])
certs[:invalidchild] =
cb.create_certificates(keys[:invalidchild], 'invalidchild',
keys[:invalid], certs[:child])
certs[:wrong_key] =
cb.create_certificates(keys[:alternate], 'nobody')
base_dir = 'test/rubygems'
keys.each do |name, key|
dest = File.join base_dir, "#{name}_key.pem"
File.write dest, key.to_pem
end
certs.each do |name, (cert, cert_32)|
dest = File.join base_dir, "#{name}_cert.pem"
File.write dest, cert.to_pem
dest = File.join base_dir, "#{name}_cert_32.pem"
File.write dest, cert_32.to_pem
end