OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 # |
| 3 # SelfTest/PublicKey/test_DSA.py: Self-test for the DSA primitive |
| 4 # |
| 5 # Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> |
| 6 # |
| 7 # =================================================================== |
| 8 # The contents of this file are dedicated to the public domain. To |
| 9 # the extent that dedication to the public domain is not available, |
| 10 # everyone is granted a worldwide, perpetual, royalty-free, |
| 11 # non-exclusive license to exercise all rights associated with the |
| 12 # contents of this file for any purpose whatsoever. |
| 13 # No rights are reserved. |
| 14 # |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 16 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 17 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 19 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 20 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 21 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 22 # SOFTWARE. |
| 23 # =================================================================== |
| 24 |
| 25 """Self-test suite for Crypto.PublicKey.DSA""" |
| 26 |
| 27 __revision__ = "$Id$" |
| 28 |
| 29 import sys |
| 30 import os |
| 31 if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
| 32 from Crypto.Util.py21compat import * |
| 33 from Crypto.Util.py3compat import * |
| 34 |
| 35 import unittest |
| 36 from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex |
| 37 |
| 38 def _sws(s): |
| 39 """Remove whitespace from a text or byte string""" |
| 40 if isinstance(s,str): |
| 41 return "".join(s.split()) |
| 42 else: |
| 43 return b("").join(s.split()) |
| 44 |
| 45 class DSATest(unittest.TestCase): |
| 46 # Test vector from "Appendix 5. Example of the DSA" of |
| 47 # "Digital Signature Standard (DSS)", |
| 48 # U.S. Department of Commerce/National Institute of Standards and Technology |
| 49 # FIPS 186-2 (+Change Notice), 2000 January 27. |
| 50 # http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf |
| 51 |
| 52 y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85 |
| 53 9bfd6c56 75da9d21 2d3a36ef 1672ef66 0b8c7c25 5cc0ec74 |
| 54 858fba33 f44c0669 9630a76b 030ee333""") |
| 55 |
| 56 g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb |
| 57 3bff10f3 99ce2c2e 71cb9de5 fa24babf 58e5b795 21925c9c |
| 58 c42e9f6f 464b088c c572af53 e6d78802""") |
| 59 |
| 60 p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7 |
| 61 cbb8324f 0d7882e5 d0762fc5 b7210eaf c2e9adac 32ab7aac |
| 62 49693dfb f83724c2 ec0736ee 31c80291""") |
| 63 |
| 64 q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""") |
| 65 |
| 66 x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""") |
| 67 |
| 68 k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""") |
| 69 k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""") |
| 70 m = b2a_hex(b("abc")) |
| 71 m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""") |
| 72 r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""") |
| 73 s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""") |
| 74 |
| 75 def setUp(self): |
| 76 global DSA, Random, bytes_to_long, size |
| 77 from Crypto.PublicKey import DSA |
| 78 from Crypto import Random |
| 79 from Crypto.Util.number import bytes_to_long, inverse, size |
| 80 |
| 81 self.dsa = DSA |
| 82 |
| 83 def test_generate_1arg(self): |
| 84 """DSA (default implementation) generated key (1 argument)""" |
| 85 dsaObj = self.dsa.generate(1024) |
| 86 self._check_private_key(dsaObj) |
| 87 pub = dsaObj.publickey() |
| 88 self._check_public_key(pub) |
| 89 |
| 90 def test_generate_2arg(self): |
| 91 """DSA (default implementation) generated key (2 arguments)""" |
| 92 dsaObj = self.dsa.generate(1024, Random.new().read) |
| 93 self._check_private_key(dsaObj) |
| 94 pub = dsaObj.publickey() |
| 95 self._check_public_key(pub) |
| 96 |
| 97 def test_construct_4tuple(self): |
| 98 """DSA (default implementation) constructed key (4-tuple)""" |
| 99 (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self
.g, self.p, self.q)] |
| 100 dsaObj = self.dsa.construct((y, g, p, q)) |
| 101 self._test_verification(dsaObj) |
| 102 |
| 103 def test_construct_5tuple(self): |
| 104 """DSA (default implementation) constructed key (5-tuple)""" |
| 105 (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, s
elf.g, self.p, self.q, self.x)] |
| 106 dsaObj = self.dsa.construct((y, g, p, q, x)) |
| 107 self._test_signing(dsaObj) |
| 108 self._test_verification(dsaObj) |
| 109 |
| 110 def _check_private_key(self, dsaObj): |
| 111 # Check capabilities |
| 112 self.assertEqual(1, dsaObj.has_private()) |
| 113 self.assertEqual(1, dsaObj.can_sign()) |
| 114 self.assertEqual(0, dsaObj.can_encrypt()) |
| 115 self.assertEqual(0, dsaObj.can_blind()) |
| 116 |
| 117 # Check dsaObj.[ygpqx] -> dsaObj.key.[ygpqx] mapping |
| 118 self.assertEqual(dsaObj.y, dsaObj.key.y) |
| 119 self.assertEqual(dsaObj.g, dsaObj.key.g) |
| 120 self.assertEqual(dsaObj.p, dsaObj.key.p) |
| 121 self.assertEqual(dsaObj.q, dsaObj.key.q) |
| 122 self.assertEqual(dsaObj.x, dsaObj.key.x) |
| 123 |
| 124 # Sanity check key data |
| 125 self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q |
| 126 self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bit
s |
| 127 self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of
p-1 |
| 128 self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y ==
g**x mod p |
| 129 self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q |
| 130 |
| 131 def _check_public_key(self, dsaObj): |
| 132 k = a2b_hex(self.k) |
| 133 m_hash = a2b_hex(self.m_hash) |
| 134 |
| 135 # Check capabilities |
| 136 self.assertEqual(0, dsaObj.has_private()) |
| 137 self.assertEqual(1, dsaObj.can_sign()) |
| 138 self.assertEqual(0, dsaObj.can_encrypt()) |
| 139 self.assertEqual(0, dsaObj.can_blind()) |
| 140 |
| 141 # Check dsaObj.[ygpq] -> dsaObj.key.[ygpq] mapping |
| 142 self.assertEqual(dsaObj.y, dsaObj.key.y) |
| 143 self.assertEqual(dsaObj.g, dsaObj.key.g) |
| 144 self.assertEqual(dsaObj.p, dsaObj.key.p) |
| 145 self.assertEqual(dsaObj.q, dsaObj.key.q) |
| 146 |
| 147 # Check that private parameters are all missing |
| 148 self.assertEqual(0, hasattr(dsaObj, 'x')) |
| 149 self.assertEqual(0, hasattr(dsaObj.key, 'x')) |
| 150 |
| 151 # Sanity check key data |
| 152 self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q |
| 153 self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bit
s |
| 154 self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of
p-1 |
| 155 |
| 156 # Public-only key objects should raise an error when .sign() is called |
| 157 self.assertRaises(TypeError, dsaObj.sign, m_hash, k) |
| 158 |
| 159 # Check __eq__ and __ne__ |
| 160 self.assertEqual(dsaObj.publickey() == dsaObj.publickey(),True) # assert
_ |
| 161 self.assertEqual(dsaObj.publickey() != dsaObj.publickey(),False) # failI
f |
| 162 |
| 163 def _test_signing(self, dsaObj): |
| 164 k = a2b_hex(self.k) |
| 165 m_hash = a2b_hex(self.m_hash) |
| 166 r = bytes_to_long(a2b_hex(self.r)) |
| 167 s = bytes_to_long(a2b_hex(self.s)) |
| 168 (r_out, s_out) = dsaObj.sign(m_hash, k) |
| 169 self.assertEqual((r, s), (r_out, s_out)) |
| 170 |
| 171 def _test_verification(self, dsaObj): |
| 172 m_hash = a2b_hex(self.m_hash) |
| 173 r = bytes_to_long(a2b_hex(self.r)) |
| 174 s = bytes_to_long(a2b_hex(self.s)) |
| 175 self.assertEqual(1, dsaObj.verify(m_hash, (r, s))) |
| 176 self.assertEqual(0, dsaObj.verify(m_hash + b("\0"), (r, s))) |
| 177 |
| 178 class DSAFastMathTest(DSATest): |
| 179 def setUp(self): |
| 180 DSATest.setUp(self) |
| 181 self.dsa = DSA.DSAImplementation(use_fast_math=True) |
| 182 |
| 183 def test_generate_1arg(self): |
| 184 """DSA (_fastmath implementation) generated key (1 argument)""" |
| 185 DSATest.test_generate_1arg(self) |
| 186 |
| 187 def test_generate_2arg(self): |
| 188 """DSA (_fastmath implementation) generated key (2 arguments)""" |
| 189 DSATest.test_generate_2arg(self) |
| 190 |
| 191 def test_construct_4tuple(self): |
| 192 """DSA (_fastmath implementation) constructed key (4-tuple)""" |
| 193 DSATest.test_construct_4tuple(self) |
| 194 |
| 195 def test_construct_5tuple(self): |
| 196 """DSA (_fastmath implementation) constructed key (5-tuple)""" |
| 197 DSATest.test_construct_5tuple(self) |
| 198 |
| 199 class DSASlowMathTest(DSATest): |
| 200 def setUp(self): |
| 201 DSATest.setUp(self) |
| 202 self.dsa = DSA.DSAImplementation(use_fast_math=False) |
| 203 |
| 204 def test_generate_1arg(self): |
| 205 """DSA (_slowmath implementation) generated key (1 argument)""" |
| 206 DSATest.test_generate_1arg(self) |
| 207 |
| 208 def test_generate_2arg(self): |
| 209 """DSA (_slowmath implementation) generated key (2 arguments)""" |
| 210 DSATest.test_generate_2arg(self) |
| 211 |
| 212 def test_construct_4tuple(self): |
| 213 """DSA (_slowmath implementation) constructed key (4-tuple)""" |
| 214 DSATest.test_construct_4tuple(self) |
| 215 |
| 216 def test_construct_5tuple(self): |
| 217 """DSA (_slowmath implementation) constructed key (5-tuple)""" |
| 218 DSATest.test_construct_5tuple(self) |
| 219 |
| 220 |
| 221 def get_tests(config={}): |
| 222 tests = [] |
| 223 tests += list_test_cases(DSATest) |
| 224 try: |
| 225 from Crypto.PublicKey import _fastmath |
| 226 tests += list_test_cases(DSAFastMathTest) |
| 227 except ImportError: |
| 228 from distutils.sysconfig import get_config_var |
| 229 import inspect |
| 230 _fm_path = os.path.normpath(os.path.dirname(os.path.abspath( |
| 231 inspect.getfile(inspect.currentframe()))) |
| 232 +"/../../PublicKey/_fastmath"+get_config_var("SO")) |
| 233 if os.path.exists(_fm_path): |
| 234 raise ImportError("While the _fastmath module exists, importing "+ |
| 235 "it failed. This may point to the gmp or mpir shared library "+ |
| 236 "not being in the path. _fastmath was found at "+_fm_path) |
| 237 tests += list_test_cases(DSASlowMathTest) |
| 238 return tests |
| 239 |
| 240 if __name__ == '__main__': |
| 241 suite = lambda: unittest.TestSuite(get_tests()) |
| 242 unittest.main(defaultTest='suite') |
| 243 |
| 244 # vim:set ts=4 sw=4 sts=4 expandtab: |
OLD | NEW |