main
1# frozen_string_literal: true
2
3RSpec.describe Xml::Kit::Certificate do
4 subject { described_class.new(certificate, use: :signing) }
5
6 let(:certificate) { generate_key_pair('password')[0] }
7
8 describe '#fingerprint' do
9 specify { expect(subject.fingerprint).to be_instance_of(Xml::Kit::Fingerprint) }
10 end
11
12 describe '#for?' do
13 context 'when it is for signing' do
14 subject { described_class.new(certificate, use: :signing) }
15
16 specify { expect(subject).to be_for(:signing) }
17 specify { expect(subject).to be_signing }
18 specify { expect(subject).not_to be_for(:encryption) }
19 specify { expect(subject).not_to be_encryption }
20 end
21
22 context 'when it is for encryption' do
23 subject { described_class.new(certificate, use: :encryption) }
24
25 specify { expect(subject).to be_for(:encryption) }
26 specify { expect(subject).not_to be_for(:signing) }
27 specify { expect(subject).to be_encryption }
28 specify { expect(subject).not_to be_signing }
29 end
30
31 context 'when it is for both signing and encryption' do
32 subject { described_class.new(certificate) }
33
34 specify { expect(subject).to be_for(:encryption) }
35 specify { expect(subject).to be_for(:signing) }
36 specify { expect(subject).to be_encryption }
37 specify { expect(subject).to be_signing }
38 end
39 end
40
41 describe 'equality' do
42 specify { expect(subject).to eql(subject) }
43 specify { expect(described_class.new(certificate, use: :signing)).to eql(described_class.new(certificate, use: :signing)) }
44 end
45
46 describe '#to_h' do
47 specify { expect(subject.to_h).to eql(use: :signing, fingerprint: subject.fingerprint.to_s) }
48 end
49
50 describe '#stripped' do
51 let(:expected) { certificate.to_s.gsub(/-----BEGIN CERTIFICATE-----/, '').gsub(/-----END CERTIFICATE-----/, '').delete("\n") }
52
53 specify { expect(subject.stripped).to eql(expected) }
54 end
55
56 describe '#x509' do
57 let(:expected) { OpenSSL::X509::Certificate.new(certificate.to_s) }
58 let(:actual) { subject.x509 }
59
60 specify { expect(actual).to be_instance_of(OpenSSL::X509::Certificate) }
61 specify { expect(actual.to_s).to eql(expected.to_s) }
62 end
63
64 describe '#expired?' do
65 let(:certificate) { OpenSSL::X509::Certificate.new }
66
67 context 'when the certificate has not expired yet' do
68 subject { described_class.new(certificate, use: :signing) }
69
70 before do
71 certificate.not_before = 1.minute.ago
72 certificate.not_after = 10.minutes.from_now
73 end
74
75 specify { expect(subject).not_to be_expired(Time.now) }
76 end
77
78 context 'when the current time is after the time of the expiration' do
79 subject { described_class.new(certificate, use: :signing) }
80
81 before do
82 certificate.not_before = 10.minutes.ago
83 certificate.not_after = 1.minute.ago
84 end
85
86 specify { expect(subject).to be_expired(Time.now) }
87 end
88 end
89
90 describe '#active?' do
91 subject { described_class.new(certificate, use: :signing) }
92
93 let(:certificate) { OpenSSL::X509::Certificate.new }
94 let(:private_key) { OpenSSL::PKey::RSA.new(2048) }
95
96 context 'when the current time is within the active window' do
97 before do
98 certificate.not_before = 1.minute.ago
99 certificate.not_after = 10.minutes.from_now
100 certificate.public_key = private_key.public_key
101 certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
102 end
103
104 specify { expect(subject).to be_active(Time.now) }
105
106 context 'when reading an x509 pem' do
107 subject { described_class.new(certificate.to_pem, use: :signing) }
108
109 specify { expect(subject).to be_active(Time.now) }
110 end
111 end
112
113 context 'when the current time is before the active window' do
114 before do
115 certificate.not_before = 1.minute.from_now
116 certificate.not_after = 10.minutes.from_now
117 certificate.public_key = private_key.public_key
118 certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
119 end
120
121 specify { expect(subject).not_to be_active(Time.now) }
122
123 context 'when reading an x509 pem' do
124 subject { described_class.new(certificate.to_pem, use: :signing) }
125
126 specify { expect(subject).not_to be_active(Time.now) }
127 end
128 end
129
130 context 'when the current time is after the active window' do
131 before do
132 certificate.not_before = 10.minutes.ago
133 certificate.not_after = 1.minute.ago
134 certificate.public_key = private_key.public_key
135 certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
136 end
137
138 specify { expect(subject).not_to be_active(Time.now) }
139
140 context 'when reading an x509 pem' do
141 subject { described_class.new(certificate.to_pem, use: :signing) }
142
143 specify { expect(subject).not_to be_active(Time.now) }
144 end
145 end
146 end
147
148 describe '#not_after, #not_before' do
149 subject { described_class.new(certificate, use: :signing) }
150
151 let(:certificate) { OpenSSL::X509::Certificate.new }
152
153 before do
154 certificate.not_before = 1.minute.from_now
155 certificate.not_after = 10.minutes.from_now
156 end
157
158 specify { expect(subject.not_after).to eql(certificate.not_after) }
159 specify { expect(subject.not_before).to eql(certificate.not_before) }
160 end
161
162 describe '#to_xml' do
163 context 'when generated' do
164 let(:result) { Hash.from_xml(subject.to_xml) }
165
166 specify { expect(result['KeyDescriptor']).to be_present }
167 specify { expect(result['KeyDescriptor']['use']).to eql('signing') }
168 specify { expect(result['KeyDescriptor']['KeyInfo']['xmlns']).to eql(Xml::Kit::Namespaces::XMLDSIG) }
169 specify { expect(result['KeyDescriptor']['KeyInfo']['X509Data']['X509Certificate']).to eql(subject.stripped) }
170 end
171
172 context 'when the certificate can be used for both signing and encryption' do
173 subject { described_class.new(certificate, use: nil) }
174
175 let(:result) { Hash.from_xml(subject.to_xml) }
176
177 specify { expect(result['KeyDescriptor']).to be_present }
178 specify { expect(result['KeyDescriptor']['use']).to be_nil }
179 end
180 end
181end