Skip to content

Commit feb6d2c

Browse files
bdewaterioquatix
authored andcommitted
Add Marshal support to X509 objects
This allows for example to use Rails' cache to store these objects. Without this patch you'd get errors like "TypeError (no _dump_data is defined for class OpenSSL::X509::Certificate)" Note that the X509::Revoked class doesn't need the newly introduced modules as the DER output of X509::CRL already includes these.
1 parent 308fb19 commit feb6d2c

File tree

7 files changed

+85
-0
lines changed

7 files changed

+85
-0
lines changed

lib/openssl/x509.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@
1414

1515
module OpenSSL
1616
module X509
17+
module Marshal
18+
def self.included(base)
19+
base.extend(ClassMethods)
20+
end
21+
22+
module ClassMethods
23+
def _load(string)
24+
new(string)
25+
end
26+
end
27+
28+
def _dump(_level)
29+
to_der
30+
end
31+
end
32+
1733
class ExtensionFactory
1834
def create_extension(*arg)
1935
if arg.size > 1
@@ -41,6 +57,8 @@ def create_ext_from_hash(hash)
4157
end
4258

4359
class Extension
60+
include Marshal
61+
4462
def ==(other)
4563
return false unless Extension === other
4664
to_der == other.to_der
@@ -116,6 +134,8 @@ def authority_key_identifier
116134
end
117135

118136
class Name
137+
include Marshal
138+
119139
module RFC2253DN
120140
Special = ',=+<>#;'
121141
HexChar = /[0-9a-fA-F]/
@@ -219,6 +239,8 @@ def pretty_print(q)
219239
end
220240

221241
class Attribute
242+
include Marshal
243+
222244
def ==(other)
223245
return false unless Attribute === other
224246
to_der == other.to_der
@@ -232,6 +254,7 @@ def cleanup
232254
end
233255

234256
class Certificate
257+
include Marshal
235258
include Extension::SubjectKeyIdentifier
236259
include Extension::AuthorityKeyIdentifier
237260

@@ -248,6 +271,7 @@ def pretty_print(q)
248271
end
249272

250273
class CRL
274+
include Marshal
251275
include Extension::AuthorityKeyIdentifier
252276

253277
def ==(other)
@@ -264,6 +288,8 @@ def ==(other)
264288
end
265289

266290
class Request
291+
include Marshal
292+
267293
def ==(other)
268294
return false unless Request === other
269295
to_der == other.to_der

test/test_x509attr.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ def test_eq
7979
assert_equal true, attr1 == attr2
8080
assert_equal false, attr1 == attr3
8181
end
82+
83+
def test_marshal
84+
val = OpenSSL::ASN1::Set([
85+
OpenSSL::ASN1::UTF8String("abc123")
86+
])
87+
attr = OpenSSL::X509::Attribute.new("challengePassword", val)
88+
deserialized = Marshal.load(Marshal.dump(attr))
89+
90+
assert_equal attr.to_der, deserialized.to_der
91+
end
8292
end
8393

8494
end

test/test_x509cert.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,17 @@ def test_eq
196196
assert_equal false, cert3 == cert4
197197
end
198198

199+
def test_marshal
200+
now = Time.now
201+
cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil,
202+
not_before: now, not_after: now + 3600)
203+
cert = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024,
204+
not_before: now, not_after: now + 3600)
205+
deserialized = Marshal.load(Marshal.dump(cert))
206+
207+
assert_equal cert.to_der, deserialized.to_der
208+
end
209+
199210
private
200211

201212
def certificate_error_returns_false

test/test_x509crl.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,22 @@ def test_eq
256256
assert_equal true, rev2 == crl2.revoked[1]
257257
end
258258

259+
def test_marshal
260+
now = Time.now
261+
262+
cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil)
263+
crl = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1024, "sha256")
264+
rev = OpenSSL::X509::Revoked.new.tap { |rev|
265+
rev.serial = 1
266+
rev.time = now
267+
}
268+
crl.add_revoked(rev)
269+
deserialized = Marshal.load(Marshal.dump(crl))
270+
271+
assert_equal crl.to_der, deserialized.to_der
272+
assert_equal crl.revoked[0].to_der, deserialized.revoked[0].to_der
273+
end
274+
259275
private
260276

261277
def crl_error_returns_false

test/test_x509ext.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ def test_eq
8787
assert_equal false, ext1 == ext3
8888
end
8989

90+
def test_marshal
91+
ef = OpenSSL::X509::ExtensionFactory.new
92+
ext = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2")
93+
deserialized = Marshal.load(Marshal.dump(ext))
94+
95+
assert_equal ext.to_der, deserialized.to_der
96+
end
97+
9098
def test_value_der
9199
ext = OpenSSL::X509::Extension.new(@basic_constraints.to_der)
92100
assert_equal @basic_constraints_value.to_der, ext.value_der

test/test_x509name.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,13 @@ def test_equality
453453
assert_equal false, name0.eql?(name2)
454454
end
455455

456+
def test_marshal
457+
name = OpenSSL::X509::Name.new([["DC", "org"], ["DC", "ruby-lang"], ["CN", "bar.ruby-lang.org"]])
458+
deserialized = Marshal.load(Marshal.dump(name))
459+
460+
assert_equal name.to_der, deserialized.to_der
461+
end
462+
456463
def test_dup
457464
name = OpenSSL::X509::Name.parse("/CN=ruby-lang.org")
458465
assert_equal(name.to_der, name.dup.to_der)

test/test_x509req.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ def test_eq
151151
assert_equal false, req1 == req3
152152
end
153153

154+
def test_marshal
155+
req = issue_csr(0, @dn, @rsa1024, "sha256")
156+
deserialized = Marshal.load(Marshal.dump(req))
157+
158+
assert_equal req.to_der, deserialized.to_der
159+
end
160+
154161
private
155162

156163
def request_error_returns_false

0 commit comments

Comments
 (0)