blob: dfc80f270a0a4634b334b83b02442464f7e4693c [file] [log] [blame]
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05001"""
2Unit tests for L{OpenSSL.crypto}.
3"""
4
5from unittest import TestCase
6
7from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05008from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05009from OpenSSL.crypto import X509Req, X509ReqType
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050010
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -050011class _Python23TestCaseHelper:
Jean-Paul Calderone7da26a72008-03-06 00:35:20 -050012 # Python 2.3 compatibility.
13 def assertTrue(self, *a, **kw):
14 return self.failUnless(*a, **kw)
15
16
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -050017 def assertFalse(self, *a, **kw):
18 return self.failIf(*a, **kw)
19
20
21
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -050022class PKeyTests(TestCase, _Python23TestCaseHelper):
23 """
24 Unit tests for L{OpenSSL.crypto.PKey}.
25 """
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050026 def test_construction(self):
27 """
28 L{PKey} takes no arguments and returns a new L{PKeyType} instance.
29 """
30 self.assertRaises(TypeError, PKey, None)
31 key = PKey()
32 self.assertTrue(
33 isinstance(key, PKeyType),
34 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
35
36
37 def test_pregeneration(self):
38 """
39 L{PKeyType.bits} and L{PKeyType.type} return C{0} before the key is
40 generated.
41 """
42 key = PKey()
43 self.assertEqual(key.type(), 0)
44 self.assertEqual(key.bits(), 0)
45
46
47 def test_failedGeneration(self):
48 """
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -050049 L{PKeyType.generate_key} takes two arguments, the first giving the key
50 type as one of L{TYPE_RSA} or L{TYPE_DSA} and the second giving the
51 number of bits to generate. If an invalid type is specified or
52 generation fails, L{Error} is raised. If an invalid number of bits is
53 specified, L{ValueError} or L{Error} is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050054 """
55 key = PKey()
56 self.assertRaises(TypeError, key.generate_key)
57 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
58 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
59 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -050060
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -050061 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
62 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -050063
64 # XXX RSA generation for small values of bits is fairly buggy in a wide
65 # range of OpenSSL versions. I need to figure out what the safe lower
66 # bound for a reasonable number of OpenSSL versions is and explicitly
67 # check for that in the wrapper. The failure behavior is typically an
68 # infinite loop inside OpenSSL.
69
70 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050071
72 # XXX DSA generation seems happy with any number of bits. The DSS
73 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
74 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -050075 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050076 # So, it doesn't seem possible to make generate_key fail for
77 # TYPE_DSA with a bits argument which is at least an int.
78
79 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
80
81
82 def test_rsaGeneration(self):
83 """
84 L{PKeyType.generate_key} generates an RSA key when passed
85 L{TYPE_RSA} as a type and a reasonable number of bits.
86 """
87 bits = 128
88 key = PKey()
89 key.generate_key(TYPE_RSA, bits)
90 self.assertEqual(key.type(), TYPE_RSA)
91 self.assertEqual(key.bits(), bits)
92
93
94 def test_dsaGeneration(self):
95 """
96 L{PKeyType.generate_key} generates a DSA key when passed
97 L{TYPE_DSA} as a type and a reasonable number of bits.
98 """
99 # 512 is a magic number. The DSS (Digital Signature Standard)
100 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
101 # will silently promote any value below 512 to 512.
102 bits = 512
103 key = PKey()
104 key.generate_key(TYPE_DSA, bits)
105 self.assertEqual(key.type(), TYPE_DSA)
106 self.assertEqual(key.bits(), bits)
107
108
109 def test_regeneration(self):
110 """
111 L{PKeyType.generate_key} can be called multiple times on the same
112 key to generate new keys.
113 """
114 key = PKey()
115 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
116 key.generate_key(type, bits)
117 self.assertEqual(key.type(), type)
118 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500119
120
121
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500122class X509NameTests(TestCase, _Python23TestCaseHelper):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500123 """
124 Unit tests for L{OpenSSL.crypto.X509Name}.
125 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500126 def _x509name(self, **attrs):
127 # XXX There's no other way to get a new X509Name yet.
128 name = X509().get_subject()
129 attrs = attrs.items()
130 # Make the order stable - order matters!
131 attrs.sort(lambda (k1, v1), (k2, v2): cmp(v1, v2))
132 for k, v in attrs:
133 setattr(name, k, v)
134 return name
135
136
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500137 def test_attributes(self):
138 """
139 L{X509NameType} instances have attributes for each standard (?)
140 X509Name field.
141 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500142 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500143 name.commonName = "foo"
144 self.assertEqual(name.commonName, "foo")
145 self.assertEqual(name.CN, "foo")
146 name.CN = "baz"
147 self.assertEqual(name.commonName, "baz")
148 self.assertEqual(name.CN, "baz")
149 name.commonName = "bar"
150 self.assertEqual(name.commonName, "bar")
151 self.assertEqual(name.CN, "bar")
152 name.CN = "quux"
153 self.assertEqual(name.commonName, "quux")
154 self.assertEqual(name.CN, "quux")
155
156
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500157 def test_copy(self):
158 """
159 L{X509Name} creates a new L{X509NameType} instance with all the same
160 attributes as an existing L{X509NameType} instance when called with
161 one.
162 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500163 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500164
165 copy = X509Name(name)
166 self.assertEqual(copy.commonName, "foo")
167 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500168
169 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500170 copy.commonName = "baz"
171 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500172
173 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500174 name.emailAddress = "quux@example.com"
175 self.assertEqual(copy.emailAddress, "bar@example.com")
176
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500177
178 def test_repr(self):
179 """
180 L{repr} passed an L{X509NameType} instance should return a string
181 containing a description of the type and the NIDs which have been set
182 on it.
183 """
184 name = self._x509name(commonName="foo", emailAddress="bar")
185 self.assertEqual(
186 repr(name),
187 "<X509Name object '/emailAddress=bar/CN=foo'>")
188
189
190 def test_comparison(self):
191 """
192 L{X509NameType} instances should compare based on their NIDs.
193 """
194 def _equality(a, b, assertTrue, assertFalse):
195 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
196 assertFalse(a != b)
197 assertTrue(b == a)
198 assertFalse(b != a)
199
200 def assertEqual(a, b):
201 _equality(a, b, self.assertTrue, self.assertFalse)
202
203 # Instances compare equal to themselves.
204 name = self._x509name()
205 assertEqual(name, name)
206
207 # Empty instances should compare equal to each other.
208 assertEqual(self._x509name(), self._x509name())
209
210 # Instances with equal NIDs should compare equal to each other.
211 assertEqual(self._x509name(commonName="foo"),
212 self._x509name(commonName="foo"))
213
214 # Instance with equal NIDs set using different aliases should compare
215 # equal to each other.
216 assertEqual(self._x509name(commonName="foo"),
217 self._x509name(CN="foo"))
218
219 # Instances with more than one NID with the same values should compare
220 # equal to each other.
221 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
222 self._x509name(commonName="foo", OU="bar"))
223
224 def assertNotEqual(a, b):
225 _equality(a, b, self.assertFalse, self.assertTrue)
226
227 # Instances with different values for the same NID should not compare
228 # equal to each other.
229 assertNotEqual(self._x509name(CN="foo"),
230 self._x509name(CN="bar"))
231
232 # Instances with different NIDs should not compare equal to each other.
233 assertNotEqual(self._x509name(CN="foo"),
234 self._x509name(OU="foo"))
235
236 def _inequality(a, b, assertTrue, assertFalse):
237 assertTrue(a < b)
238 assertTrue(a <= b)
239 assertTrue(b > a)
240 assertTrue(b >= a)
241 assertFalse(a > b)
242 assertFalse(a >= b)
243 assertFalse(b < a)
244 assertFalse(b <= a)
245
246 def assertLessThan(a, b):
247 _inequality(a, b, self.assertTrue, self.assertFalse)
248
249 # An X509Name with a NID with a value which sorts less than the value
250 # of the same NID on another X509Name compares less than the other
251 # X509Name.
252 assertLessThan(self._x509name(CN="abc"),
253 self._x509name(CN="def"))
254
255 def assertGreaterThan(a, b):
256 _inequality(a, b, self.assertFalse, self.assertTrue)
257
258 # An X509Name with a NID with a value which sorts greater than the
259 # value of the same NID on another X509Name compares greater than the
260 # other X509Name.
261 assertGreaterThan(self._x509name(CN="def"),
262 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500263
264
265
266class X509ReqTests(TestCase, _Python23TestCaseHelper):
267 """
268 Tests for L{OpenSSL.crypto.X509Req}.
269 """
270 def test_construction(self):
271 """
272 L{X509Req} takes no arguments and returns an L{X509ReqType} instance.
273 """
274 request = X509Req()
275 self.assertTrue(
276 isinstance(request, X509ReqType),
277 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
278
279
280 def test_get_subject(self):
281 """
282 L{X509ReqType.get_subject} returns an L{X509Name} for the subject of
283 the request and which is valid even after the request object is
284 otherwise dead.
285 """
286 request = X509Req()
287 subject = request.get_subject()
288 self.assertTrue(
289 isinstance(subject, X509NameType),
290 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
291 subject.commonName = "foo"
292 self.assertEqual(request.get_subject().commonName, "foo")
293 del request
294 subject.commonName = "bar"
295 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500296
297
298
299class X509Tests(TestCase, _Python23TestCaseHelper):
300 """
301 Tests for L{OpenSSL.crypto.X509}.
302 """
303 def test_construction(self):
304 """
305 L{X509} takes no arguments and returns an instance of L{X509Type}.
306 """
307 certificate = X509()
308 self.assertTrue(
309 isinstance(certificate, X509Type),
310 "%r is of type %r, should be %r" % (certificate,
311 type(certificate),
312 X509Type))
313
314
315 def test_serial_number(self):
316 """
317 The serial number of an L{X509Type} can be retrieved and modified with
318 L{X509Type.get_serial_number} and L{X509Type.set_serial_number}.
319 """
320 certificate = X509()
321 self.assertRaises(TypeError, certificate.set_serial_number)
322 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
323 self.assertRaises(TypeError, certificate.set_serial_number, "1")
324 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
325 self.assertEqual(certificate.get_serial_number(), 0)
326 certificate.set_serial_number(1)
327 self.assertEqual(certificate.get_serial_number(), 1)
328 certificate.set_serial_number(2 ** 32 + 1)
329 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
330 certificate.set_serial_number(2 ** 64 + 1)
331 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)