flores 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/flores.gemspec +1 -1
- data/lib/flores/pki.rb +1 -229
- data/lib/flores/pki/csr.rb +232 -0
- data/lib/flores/random.rb +1 -1
- data/lib/flores/rspec/analyze.rb +19 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0109a1c44c651b3d002eef3719f0888c5723dee9
|
4
|
+
data.tar.gz: bd9a91773854cbbbeaf7833297d9a20f3c11d3dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be9b7d18c06c04a310af5d11ec0ce5676be812bc8474e4743696d842fe369b8aed382d8b00504dc3201d60e80c8374de02282730c7c481d5ec4d9be5dbbdf406
|
7
|
+
data.tar.gz: f7e581e34aac90f9f96add6014949e0ab5fa486c5674056e8413c19c85634b6ef12fbaa05dcc0768ea9e3cf8fa1766688a9d2903635df9e46ccebb048d311751
|
data/flores.gemspec
CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |spec|
|
|
2
2
|
files = %x(git ls-files).split("\n")
|
3
3
|
|
4
4
|
spec.name = "flores"
|
5
|
-
spec.version = "0.0.
|
5
|
+
spec.version = "0.0.7"
|
6
6
|
spec.summary = "Fuzz, randomize, and stress your tests"
|
7
7
|
spec.description = <<-DESCRIPTION
|
8
8
|
Add fuzzing, randomization, and stress to your tests.
|
data/lib/flores/pki.rb
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
|
18
18
|
require "flores/namespace"
|
19
19
|
require "flores/random"
|
20
|
+
require "flores/pki/csr"
|
20
21
|
require "English"
|
21
22
|
require "openssl"
|
22
23
|
|
@@ -65,233 +66,4 @@ module Flores::PKI
|
|
65
66
|
return [certificate, key]
|
66
67
|
end
|
67
68
|
end
|
68
|
-
|
69
|
-
# A certificate signing request.
|
70
|
-
#
|
71
|
-
# From here, you can configure a certificate to be created based on your
|
72
|
-
# desired configuration.
|
73
|
-
#
|
74
|
-
# Example making a root CA:
|
75
|
-
#
|
76
|
-
# key = OpenSSL::PKey::RSA.generate(4096, 65537)
|
77
|
-
# csr = Flores::PKI::CertificateSigningRequest.new
|
78
|
-
# csr.subject = "OU=Fancy Pants Inc."
|
79
|
-
# certificate = csr.create_root(key)
|
80
|
-
#
|
81
|
-
# Example making an intermediate CA:
|
82
|
-
#
|
83
|
-
# root_key = OpenSSL::PKey::RSA.generate(4096, 65537)
|
84
|
-
# root_csr = Flores::PKI::CertificateSigningRequest.new
|
85
|
-
# root_csr.subject = "OU=Fancy Pants Inc."
|
86
|
-
# root_csr.public_key = root_key.public
|
87
|
-
# root_certificate = csr.create_root(root_key)
|
88
|
-
#
|
89
|
-
# intermediate_key = OpenSSL::PKey::RSA.generate(4096, 65537)
|
90
|
-
# intermediate_csr = Flores::PKI::CertificateSigningRequest.new
|
91
|
-
# intermediate_csr.public_key = intermediate_key.public
|
92
|
-
# intermediate_csr.subject = "OU=Fancy Pants Inc. Intermediate 1"
|
93
|
-
# intermediate_certificate = csr.create_intermediate(root_certificate, root_key)
|
94
|
-
class CertificateSigningRequest
|
95
|
-
# raised when an invalid signing configuration is given
|
96
|
-
class InvalidRequest < StandardError; end
|
97
|
-
|
98
|
-
# raised when invalid data is present in a certificate request
|
99
|
-
class InvalidData < StandardError; end
|
100
|
-
|
101
|
-
# raised when an invalid subject (format, or whatever) is given in a certificate request
|
102
|
-
class InvalidSubject < InvalidData; end
|
103
|
-
|
104
|
-
# raised when an invalid time value is given for a certificate request
|
105
|
-
class InvalidTime < InvalidData; end
|
106
|
-
|
107
|
-
def initialize
|
108
|
-
self.serial = Flores::PKI.random_serial
|
109
|
-
self.digest_method = default_digest_method
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def validate_subject(value)
|
115
|
-
OpenSSL::X509::Name.parse(value)
|
116
|
-
rescue OpenSSL::X509::NameError => e
|
117
|
-
raise InvalidSubject, "Invalid subject '#{value}'. (#{e})"
|
118
|
-
rescue TypeError => e
|
119
|
-
# Bug(?) in MRI 2.1.6(?)
|
120
|
-
raise InvalidSubject, "Invalid subject '#{value}'. (#{e})"
|
121
|
-
end
|
122
|
-
|
123
|
-
def subject=(value)
|
124
|
-
@subject = validate_subject(value)
|
125
|
-
end
|
126
|
-
|
127
|
-
attr_reader :subject
|
128
|
-
|
129
|
-
def subject_alternates=(values)
|
130
|
-
@subject_alternates = values
|
131
|
-
end
|
132
|
-
|
133
|
-
attr_reader :subject_alternates
|
134
|
-
|
135
|
-
def public_key=(value)
|
136
|
-
@public_key = validate_public_key(value)
|
137
|
-
end
|
138
|
-
|
139
|
-
def validate_public_key(value)
|
140
|
-
raise InvalidData, "public key must be a OpenSSL::PKey::PKey" unless value.is_a? OpenSSL::PKey::PKey
|
141
|
-
value
|
142
|
-
end
|
143
|
-
|
144
|
-
attr_reader :public_key
|
145
|
-
|
146
|
-
def start_time=(value)
|
147
|
-
@start_time = validate_time(value)
|
148
|
-
end
|
149
|
-
|
150
|
-
attr_reader :start_time
|
151
|
-
|
152
|
-
def expire_time=(value)
|
153
|
-
@expire_time = validate_time(value)
|
154
|
-
end
|
155
|
-
|
156
|
-
attr_reader :expire_time
|
157
|
-
|
158
|
-
def validate_time(value)
|
159
|
-
raise InvalidTime, "#{value.inspect} (class #{value.class.name})" unless value.is_a?(Time)
|
160
|
-
value
|
161
|
-
end
|
162
|
-
|
163
|
-
def certificate
|
164
|
-
return @certificate if @certificate
|
165
|
-
@certificate = OpenSSL::X509::Certificate.new
|
166
|
-
|
167
|
-
# RFC5280
|
168
|
-
# > 4.1.2.1. Version
|
169
|
-
# > version MUST be 3 (value is 2).
|
170
|
-
#
|
171
|
-
# Version value of '2' means a v3 certificate.
|
172
|
-
@certificate.version = 2
|
173
|
-
|
174
|
-
@certificate.subject = subject
|
175
|
-
@certificate.not_before = start_time
|
176
|
-
@certificate.not_after = expire_time
|
177
|
-
@certificate.public_key = public_key
|
178
|
-
@certificate
|
179
|
-
end
|
180
|
-
|
181
|
-
def default_digest_method
|
182
|
-
OpenSSL::Digest::SHA256.new
|
183
|
-
end
|
184
|
-
|
185
|
-
def self_signed?
|
186
|
-
@signing_certificate.nil?
|
187
|
-
end
|
188
|
-
|
189
|
-
def validate!
|
190
|
-
if self_signed?
|
191
|
-
if @signing_key.nil?
|
192
|
-
raise InvalidRequest, "No signing_key given. Cannot sign key."
|
193
|
-
end
|
194
|
-
elsif @signing_certificate.nil? && @signing_key
|
195
|
-
raise InvalidRequest, "signing_key given, but no signing_certificate is set"
|
196
|
-
elsif @signing_certificate && @signing_key.nil?
|
197
|
-
raise InvalidRequest, "signing_certificate given, but no signing_key is set"
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def create
|
202
|
-
validate!
|
203
|
-
extensions = OpenSSL::X509::ExtensionFactory.new
|
204
|
-
extensions.subject_certificate = certificate
|
205
|
-
extensions.issuer_certificate = self_signed? ? certificate : signing_certificate
|
206
|
-
|
207
|
-
certificate.issuer = extensions.issuer_certificate.subject
|
208
|
-
certificate.add_extension(extensions.create_extension("subjectKeyIdentifier", "hash", false))
|
209
|
-
|
210
|
-
# RFC 5280 4.2.1.1. Authority Key Identifier
|
211
|
-
# This is "who signed this key"
|
212
|
-
certificate.add_extension(extensions.create_extension("authorityKeyIdentifier", "keyid:always", false))
|
213
|
-
#certificate.add_extension(extensions.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always", false))
|
214
|
-
|
215
|
-
if want_signature_ability?
|
216
|
-
# Create a CA.
|
217
|
-
certificate.add_extension(extensions.create_extension("basicConstraints", "CA:TRUE", true))
|
218
|
-
# Rough googling seems to indicate at least keyCertSign is required for CA and intermediate certs.
|
219
|
-
certificate.add_extension(extensions.create_extension("keyUsage", "keyCertSign, cRLSign, digitalSignature", true))
|
220
|
-
else
|
221
|
-
# Create a client+server certificate
|
222
|
-
#
|
223
|
-
# It feels weird to create a certificate that's valid as both server and client, but a brief inspection of major
|
224
|
-
# web properties (apple.com, google.com, yahoo.com, github.com, fastly.com, mozilla.com, amazon.com) reveals that
|
225
|
-
# major web properties have certificates with both clientAuth and serverAuth extended key usages. Further,
|
226
|
-
# these major server certificates all have digitalSignature and keyEncipherment for key usage.
|
227
|
-
#
|
228
|
-
# Here's the command I used to check this:
|
229
|
-
# echo mozilla.com apple.com github.com google.com yahoo.com fastly.com elastic.co amazon.com \
|
230
|
-
# | xargs -n1 sh -c 'openssl s_client -connect $1:443 \
|
231
|
-
# | sed -ne "/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p" \
|
232
|
-
# | openssl x509 -text -noout | sed -ne "/X509v3 extensions/,/Signature Algorithm/p" | sed -e "s/^/$1 /"' - \
|
233
|
-
# | grep -A2 'Key Usage'
|
234
|
-
certificate.add_extension(extensions.create_extension("keyUsage", "digitalSignature, keyEncipherment", true))
|
235
|
-
certificate.add_extension(extensions.create_extension("extendedKeyUsage", "clientAuth, serverAuth", false))
|
236
|
-
end
|
237
|
-
|
238
|
-
if @subject_alternates
|
239
|
-
certificate.add_extension(extensions.create_extension("subjectAltName", @subject_alternates.join(",")))
|
240
|
-
end
|
241
|
-
|
242
|
-
certificate.serial = OpenSSL::BN.new(serial)
|
243
|
-
certificate.sign(signing_key, digest_method)
|
244
|
-
certificate
|
245
|
-
end
|
246
|
-
|
247
|
-
# Set the certificate which is going to be signing this request.
|
248
|
-
def signing_certificate=(certificate)
|
249
|
-
raise InvalidData, "signing_certificate must be an OpenSSL::X509::Certificate" unless certificate.is_a?(OpenSSL::X509::Certificate)
|
250
|
-
@signing_certificate = certificate
|
251
|
-
end
|
252
|
-
attr_reader :signing_certificate
|
253
|
-
|
254
|
-
attr_reader :signing_key
|
255
|
-
def signing_key=(private_key)
|
256
|
-
raise InvalidData, "signing_key must be an OpenSSL::PKey::PKey (or a subclass)" unless private_key.is_a?(OpenSSL::PKey::PKey)
|
257
|
-
@signing_key = private_key
|
258
|
-
end
|
259
|
-
|
260
|
-
def want_signature_ability=(value)
|
261
|
-
raise InvalidData, "want_signature_ability must be a boolean" unless value == true || value == false
|
262
|
-
@want_signature_ability = value
|
263
|
-
end
|
264
|
-
|
265
|
-
def want_signature_ability?
|
266
|
-
@want_signature_ability == true
|
267
|
-
end
|
268
|
-
|
269
|
-
attr_reader :digest_method
|
270
|
-
def digest_method=(value)
|
271
|
-
raise InvalidData, "digest_method must be a OpenSSL::Digest (or a subclass)" unless value.is_a?(OpenSSL::Digest)
|
272
|
-
@digest_method = value
|
273
|
-
end
|
274
|
-
|
275
|
-
attr_reader :serial
|
276
|
-
def serial=(value)
|
277
|
-
begin
|
278
|
-
Integer(value)
|
279
|
-
rescue
|
280
|
-
raise InvalidData, "Invalid serial value. Must be a number (or a String containing only nubers)"
|
281
|
-
end
|
282
|
-
@serial = value
|
283
|
-
end
|
284
|
-
|
285
|
-
public(:serial, :serial=)
|
286
|
-
public(:subject, :subject=)
|
287
|
-
public(:subject_alternates, :subject_alternates=)
|
288
|
-
public(:public_key, :public_key=)
|
289
|
-
public(:start_time, :start_time=)
|
290
|
-
public(:expire_time, :expire_time=)
|
291
|
-
public(:digest_method, :digest_method=)
|
292
|
-
public(:want_signature_ability?, :want_signature_ability=)
|
293
|
-
public(:signing_key, :signing_key=)
|
294
|
-
public(:signing_certificate, :signing_certificate=)
|
295
|
-
public(:create)
|
296
|
-
end # class CertificateSigningRequest
|
297
69
|
end # Flores::PKI
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require "flores/namespace"
|
2
|
+
|
3
|
+
module Flores::PKI
|
4
|
+
# A certificate signing request.
|
5
|
+
#
|
6
|
+
# From here, you can configure a certificate to be created based on your
|
7
|
+
# desired configuration.
|
8
|
+
#
|
9
|
+
# Example making a root CA:
|
10
|
+
#
|
11
|
+
# key = OpenSSL::PKey::RSA.generate(4096, 65537)
|
12
|
+
# csr = Flores::PKI::CertificateSigningRequest.new
|
13
|
+
# csr.subject = "OU=Fancy Pants Inc."
|
14
|
+
# certificate = csr.create_root(key)
|
15
|
+
#
|
16
|
+
# Example making an intermediate CA:
|
17
|
+
#
|
18
|
+
# root_key = OpenSSL::PKey::RSA.generate(4096, 65537)
|
19
|
+
# root_csr = Flores::PKI::CertificateSigningRequest.new
|
20
|
+
# root_csr.subject = "OU=Fancy Pants Inc."
|
21
|
+
# root_csr.public_key = root_key.public
|
22
|
+
# root_certificate = csr.create_root(root_key)
|
23
|
+
#
|
24
|
+
# intermediate_key = OpenSSL::PKey::RSA.generate(4096, 65537)
|
25
|
+
# intermediate_csr = Flores::PKI::CertificateSigningRequest.new
|
26
|
+
# intermediate_csr.public_key = intermediate_key.public
|
27
|
+
# intermediate_csr.subject = "OU=Fancy Pants Inc. Intermediate 1"
|
28
|
+
# intermediate_certificate = csr.create_intermediate(root_certificate, root_key)
|
29
|
+
class CertificateSigningRequest
|
30
|
+
# raised when an invalid signing configuration is given
|
31
|
+
class InvalidRequest < StandardError; end
|
32
|
+
|
33
|
+
# raised when invalid data is present in a certificate request
|
34
|
+
class InvalidData < StandardError; end
|
35
|
+
|
36
|
+
# raised when an invalid subject (format, or whatever) is given in a certificate request
|
37
|
+
class InvalidSubject < InvalidData; end
|
38
|
+
|
39
|
+
# raised when an invalid time value is given for a certificate request
|
40
|
+
class InvalidTime < InvalidData; end
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
self.serial = Flores::PKI.random_serial
|
44
|
+
self.digest_method = default_digest_method
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def validate_subject(value)
|
50
|
+
OpenSSL::X509::Name.parse(value)
|
51
|
+
rescue OpenSSL::X509::NameError => e
|
52
|
+
raise InvalidSubject, "Invalid subject '#{value}'. (#{e})"
|
53
|
+
rescue TypeError => e
|
54
|
+
# Bug(?) in MRI 2.1.6(?)
|
55
|
+
raise InvalidSubject, "Invalid subject '#{value}'. (#{e})"
|
56
|
+
end
|
57
|
+
|
58
|
+
def subject=(value)
|
59
|
+
@subject = validate_subject(value)
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :subject
|
63
|
+
|
64
|
+
def subject_alternates=(values)
|
65
|
+
@subject_alternates = values
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_reader :subject_alternates
|
69
|
+
|
70
|
+
def public_key=(value)
|
71
|
+
@public_key = validate_public_key(value)
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate_public_key(value)
|
75
|
+
raise InvalidData, "public key must be a OpenSSL::PKey::PKey" unless value.is_a? OpenSSL::PKey::PKey
|
76
|
+
value
|
77
|
+
end
|
78
|
+
|
79
|
+
attr_reader :public_key
|
80
|
+
|
81
|
+
def start_time=(value)
|
82
|
+
@start_time = validate_time(value)
|
83
|
+
end
|
84
|
+
|
85
|
+
attr_reader :start_time
|
86
|
+
|
87
|
+
def expire_time=(value)
|
88
|
+
@expire_time = validate_time(value)
|
89
|
+
end
|
90
|
+
|
91
|
+
attr_reader :expire_time
|
92
|
+
|
93
|
+
def validate_time(value)
|
94
|
+
raise InvalidTime, "#{value.inspect} (class #{value.class.name})" unless value.is_a?(Time)
|
95
|
+
value
|
96
|
+
end
|
97
|
+
|
98
|
+
def certificate
|
99
|
+
return @certificate if @certificate
|
100
|
+
@certificate = OpenSSL::X509::Certificate.new
|
101
|
+
|
102
|
+
# RFC5280
|
103
|
+
# > 4.1.2.1. Version
|
104
|
+
# > version MUST be 3 (value is 2).
|
105
|
+
#
|
106
|
+
# Version value of '2' means a v3 certificate.
|
107
|
+
@certificate.version = 2
|
108
|
+
|
109
|
+
@certificate.subject = subject
|
110
|
+
@certificate.not_before = start_time
|
111
|
+
@certificate.not_after = expire_time
|
112
|
+
@certificate.public_key = public_key
|
113
|
+
@certificate
|
114
|
+
end
|
115
|
+
|
116
|
+
def default_digest_method
|
117
|
+
OpenSSL::Digest::SHA256.new
|
118
|
+
end
|
119
|
+
|
120
|
+
def self_signed?
|
121
|
+
@signing_certificate.nil?
|
122
|
+
end
|
123
|
+
|
124
|
+
def validate!
|
125
|
+
if self_signed?
|
126
|
+
if @signing_key.nil?
|
127
|
+
raise InvalidRequest, "No signing_key given. Cannot sign key."
|
128
|
+
end
|
129
|
+
elsif @signing_certificate.nil? && @signing_key
|
130
|
+
raise InvalidRequest, "signing_key given, but no signing_certificate is set"
|
131
|
+
elsif @signing_certificate && @signing_key.nil?
|
132
|
+
raise InvalidRequest, "signing_certificate given, but no signing_key is set"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def create
|
137
|
+
validate!
|
138
|
+
extensions = OpenSSL::X509::ExtensionFactory.new
|
139
|
+
extensions.subject_certificate = certificate
|
140
|
+
extensions.issuer_certificate = self_signed? ? certificate : signing_certificate
|
141
|
+
|
142
|
+
certificate.issuer = extensions.issuer_certificate.subject
|
143
|
+
certificate.add_extension(extensions.create_extension("subjectKeyIdentifier", "hash", false))
|
144
|
+
|
145
|
+
# RFC 5280 4.2.1.1. Authority Key Identifier
|
146
|
+
# This is "who signed this key"
|
147
|
+
certificate.add_extension(extensions.create_extension("authorityKeyIdentifier", "keyid:always", false))
|
148
|
+
#certificate.add_extension(extensions.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always", false))
|
149
|
+
|
150
|
+
if want_signature_ability?
|
151
|
+
# Create a CA.
|
152
|
+
certificate.add_extension(extensions.create_extension("basicConstraints", "CA:TRUE", true))
|
153
|
+
# Rough googling seems to indicate at least keyCertSign is required for CA and intermediate certs.
|
154
|
+
certificate.add_extension(extensions.create_extension("keyUsage", "keyCertSign, cRLSign, digitalSignature", true))
|
155
|
+
else
|
156
|
+
# Create a client+server certificate
|
157
|
+
#
|
158
|
+
# It feels weird to create a certificate that's valid as both server and client, but a brief inspection of major
|
159
|
+
# web properties (apple.com, google.com, yahoo.com, github.com, fastly.com, mozilla.com, amazon.com) reveals that
|
160
|
+
# major web properties have certificates with both clientAuth and serverAuth extended key usages. Further,
|
161
|
+
# these major server certificates all have digitalSignature and keyEncipherment for key usage.
|
162
|
+
#
|
163
|
+
# Here's the command I used to check this:
|
164
|
+
# echo mozilla.com apple.com github.com google.com yahoo.com fastly.com elastic.co amazon.com \
|
165
|
+
# | xargs -n1 sh -c 'openssl s_client -connect $1:443 \
|
166
|
+
# | sed -ne "/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p" \
|
167
|
+
# | openssl x509 -text -noout | sed -ne "/X509v3 extensions/,/Signature Algorithm/p" | sed -e "s/^/$1 /"' - \
|
168
|
+
# | grep -A2 'Key Usage'
|
169
|
+
certificate.add_extension(extensions.create_extension("keyUsage", "digitalSignature, keyEncipherment", true))
|
170
|
+
certificate.add_extension(extensions.create_extension("extendedKeyUsage", "clientAuth, serverAuth", false))
|
171
|
+
end
|
172
|
+
|
173
|
+
if @subject_alternates
|
174
|
+
certificate.add_extension(extensions.create_extension("subjectAltName", @subject_alternates.join(",")))
|
175
|
+
end
|
176
|
+
|
177
|
+
certificate.serial = OpenSSL::BN.new(serial)
|
178
|
+
certificate.sign(signing_key, digest_method)
|
179
|
+
certificate
|
180
|
+
end
|
181
|
+
|
182
|
+
# Set the certificate which is going to be signing this request.
|
183
|
+
def signing_certificate=(certificate)
|
184
|
+
raise InvalidData, "signing_certificate must be an OpenSSL::X509::Certificate" unless certificate.is_a?(OpenSSL::X509::Certificate)
|
185
|
+
@signing_certificate = certificate
|
186
|
+
end
|
187
|
+
attr_reader :signing_certificate
|
188
|
+
|
189
|
+
attr_reader :signing_key
|
190
|
+
def signing_key=(private_key)
|
191
|
+
raise InvalidData, "signing_key must be an OpenSSL::PKey::PKey (or a subclass)" unless private_key.is_a?(OpenSSL::PKey::PKey)
|
192
|
+
@signing_key = private_key
|
193
|
+
end
|
194
|
+
|
195
|
+
def want_signature_ability=(value)
|
196
|
+
raise InvalidData, "want_signature_ability must be a boolean" unless value == true || value == false
|
197
|
+
@want_signature_ability = value
|
198
|
+
end
|
199
|
+
|
200
|
+
def want_signature_ability?
|
201
|
+
@want_signature_ability == true
|
202
|
+
end
|
203
|
+
|
204
|
+
attr_reader :digest_method
|
205
|
+
def digest_method=(value)
|
206
|
+
raise InvalidData, "digest_method must be a OpenSSL::Digest (or a subclass)" unless value.is_a?(OpenSSL::Digest)
|
207
|
+
@digest_method = value
|
208
|
+
end
|
209
|
+
|
210
|
+
attr_reader :serial
|
211
|
+
def serial=(value)
|
212
|
+
begin
|
213
|
+
Integer(value)
|
214
|
+
rescue
|
215
|
+
raise InvalidData, "Invalid serial value. Must be a number (or a String containing only nubers)"
|
216
|
+
end
|
217
|
+
@serial = value
|
218
|
+
end
|
219
|
+
|
220
|
+
public(:serial, :serial=)
|
221
|
+
public(:subject, :subject=)
|
222
|
+
public(:subject_alternates, :subject_alternates=)
|
223
|
+
public(:public_key, :public_key=)
|
224
|
+
public(:start_time, :start_time=)
|
225
|
+
public(:expire_time, :expire_time=)
|
226
|
+
public(:digest_method, :digest_method=)
|
227
|
+
public(:want_signature_ability?, :want_signature_ability=)
|
228
|
+
public(:signing_key, :signing_key=)
|
229
|
+
public(:signing_certificate, :signing_certificate=)
|
230
|
+
public(:create)
|
231
|
+
end # class CertificateSigningRequest
|
232
|
+
end
|
data/lib/flores/random.rb
CHANGED
@@ -160,7 +160,7 @@ module Flores::Random
|
|
160
160
|
IPV6_SEGMENT = 1 << 16
|
161
161
|
|
162
162
|
def self.ipv6_pack(length)
|
163
|
-
length.times.collect { integer(0
|
163
|
+
length.times.collect { integer(0...IPV6_SEGMENT).to_s(16) }.join(":")
|
164
164
|
end
|
165
165
|
|
166
166
|
def self.ipv6_abbreviation(length)
|
data/lib/flores/rspec/analyze.rb
CHANGED
@@ -143,11 +143,28 @@ module Flores::RSpec::Analyze
|
|
143
143
|
sample = instances.sample(1)
|
144
144
|
[
|
145
145
|
" #{percent_s(instances.length)} -> [#{instances.length}] #{error}",
|
146
|
-
" Sample
|
147
|
-
|
146
|
+
" Sample failure",
|
147
|
+
" Inputs:",
|
148
|
+
*render_values(sample.first[0]).map { |x| " #{x}" },
|
149
|
+
" Exception:",
|
150
|
+
sample.first[1].to_s.gsub(/^/, " ")
|
148
151
|
]
|
149
152
|
end # def error_summary
|
150
153
|
|
154
|
+
def render_values(values)
|
155
|
+
# values should be an RSpec::Core::MemoizedHelpers::ThreadsafeMemoized
|
156
|
+
lets = values.instance_eval { @memoized }
|
157
|
+
return ["<nothing>"] if lets.nil?
|
158
|
+
|
159
|
+
lets.sort_by { |k,v| v.to_s.size }.map do |k,v|
|
160
|
+
if v.to_s.size > 50
|
161
|
+
v = v.to_s[0, 50] + "..."
|
162
|
+
end
|
163
|
+
"#{k}=#{v}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
151
168
|
def error_sample_states(error, instances)
|
152
169
|
[
|
153
170
|
" Samples causing #{error}:",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flores
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Sissel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
Add fuzzing, randomization, and stress to your tests.
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- flores.gemspec
|
37
37
|
- lib/flores/namespace.rb
|
38
38
|
- lib/flores/pki.rb
|
39
|
+
- lib/flores/pki/csr.rb
|
39
40
|
- lib/flores/random.rb
|
40
41
|
- lib/flores/rspec.rb
|
41
42
|
- lib/flores/rspec/analyze.rb
|
@@ -67,8 +68,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
68
|
version: '0'
|
68
69
|
requirements: []
|
69
70
|
rubyforge_project:
|
70
|
-
rubygems_version: 2.
|
71
|
+
rubygems_version: 2.5.1
|
71
72
|
signing_key:
|
72
73
|
specification_version: 4
|
73
74
|
summary: Fuzz, randomize, and stress your tests
|
74
75
|
test_files: []
|
76
|
+
has_rdoc:
|