OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 # |
| 3 # SelfTest/PublicKey/test_ElGamal.py: Self-test for the ElGamal primitive |
| 4 # |
| 5 # =================================================================== |
| 6 # The contents of this file are dedicated to the public domain. To |
| 7 # the extent that dedication to the public domain is not available, |
| 8 # everyone is granted a worldwide, perpetual, royalty-free, |
| 9 # non-exclusive license to exercise all rights associated with the |
| 10 # contents of this file for any purpose whatsoever. |
| 11 # No rights are reserved. |
| 12 # |
| 13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 14 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 15 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 16 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 17 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 18 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 19 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 20 # SOFTWARE. |
| 21 # =================================================================== |
| 22 |
| 23 """Self-test suite for Crypto.PublicKey.ElGamal""" |
| 24 |
| 25 __revision__ = "$Id$" |
| 26 |
| 27 import unittest |
| 28 from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex |
| 29 from Crypto import Random |
| 30 from Crypto.PublicKey import ElGamal |
| 31 from Crypto.Util.number import * |
| 32 from Crypto.Util.py3compat import * |
| 33 |
| 34 class ElGamalTest(unittest.TestCase): |
| 35 |
| 36 # |
| 37 # Test vectors |
| 38 # |
| 39 # There seem to be no real ElGamal test vectors available in the |
| 40 # public domain. The following test vectors have been generated |
| 41 # with libgcrypt 1.5.0. |
| 42 # |
| 43 # Encryption |
| 44 tve=[ |
| 45 { |
| 46 # 256 bits |
| 47 'p' :'BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933'
, |
| 48 'g' :'05', |
| 49 'y' :'60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF'
, |
| 50 'x' :'1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932', |
| 51 'k' :'F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1', |
| 52 'pt' :'48656C6C6F207468657265', |
| 53 'ct1':'32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7'
, |
| 54 'ct2':'7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68' |
| 55 }, |
| 56 |
| 57 { |
| 58 # 512 bits |
| 59 'p' :'F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6
CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227', |
| 60 'g' :'07', |
| 61 'y' :'688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B
02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C', |
| 62 'x' :'14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68', |
| 63 'k' :'38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7', |
| 64 'pt' :'48656C6C6F207468657265', |
| 65 'ct1':'290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED67608
3FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B', |
| 66 'ct2':'1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C
80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0' |
| 67 } |
| 68 ] |
| 69 |
| 70 # Signature |
| 71 tvs=[ |
| 72 { |
| 73 # 256 bits |
| 74 'p' :'D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7'
, |
| 75 'g' :'05', |
| 76 'y' :'C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7'
, |
| 77 'x' :'165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB', |
| 78 'k' :'C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F'
, |
| 79 'h' :'48656C6C6F207468657265', |
| 80 'sig1':'35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2
', |
| 81 'sig2':'0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7
', |
| 82 }, |
| 83 { |
| 84 # 512 bits |
| 85 'p' :'E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC
4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF', |
| 86 'g' :'0B', |
| 87 'y' :'2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB
67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC', |
| 88 'x' :'16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB', |
| 89 'k' :'8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57A
BAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69', |
| 90 'h' :'48656C6C6F207468657265', |
| 91 'sig1':'BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE8
0D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F', |
| 92 'sig2':'5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954
468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE', |
| 93 } |
| 94 ] |
| 95 |
| 96 def test_generate_128(self): |
| 97 self._test_random_key(128) |
| 98 |
| 99 def test_generate_512(self): |
| 100 self._test_random_key(512) |
| 101 |
| 102 def test_encryption(self): |
| 103 for tv in self.tve: |
| 104 for as_longs in (0,1): |
| 105 d = self.convert_tv(tv, as_longs) |
| 106 key = ElGamal.construct(d['key']) |
| 107 ct = key.encrypt(d['pt'], d['k']) |
| 108 self.assertEquals(ct[0], d['ct1']) |
| 109 self.assertEquals(ct[1], d['ct2']) |
| 110 |
| 111 def test_decryption(self): |
| 112 for tv in self.tve: |
| 113 for as_longs in (0,1): |
| 114 d = self.convert_tv(tv, as_longs) |
| 115 key = ElGamal.construct(d['key']) |
| 116 pt = key.decrypt((d['ct1'], d['ct2'])) |
| 117 self.assertEquals(pt, d['pt']) |
| 118 |
| 119 def test_signing(self): |
| 120 for tv in self.tvs: |
| 121 for as_longs in (0,1): |
| 122 d = self.convert_tv(tv, as_longs) |
| 123 key = ElGamal.construct(d['key']) |
| 124 sig1, sig2 = key.sign(d['h'], d['k']) |
| 125 self.assertEquals(sig1, d['sig1']) |
| 126 self.assertEquals(sig2, d['sig2']) |
| 127 |
| 128 def test_verification(self): |
| 129 for tv in self.tvs: |
| 130 for as_longs in (0,1): |
| 131 d = self.convert_tv(tv, as_longs) |
| 132 key = ElGamal.construct(d['key']) |
| 133 # Positive test |
| 134 res = key.verify( d['h'], (d['sig1'],d['sig2']) ) |
| 135 self.failUnless(res) |
| 136 # Negative test |
| 137 res = key.verify( d['h'], (d['sig1']+1,d['sig2']) ) |
| 138 self.failIf(res) |
| 139 |
| 140 def convert_tv(self, tv, as_longs=0): |
| 141 """Convert a test vector from textual form (hexadecimal ascii |
| 142 to either integers or byte strings.""" |
| 143 key_comps = 'p','g','y','x' |
| 144 tv2 = {} |
| 145 for c in tv.keys(): |
| 146 tv2[c] = a2b_hex(tv[c]) |
| 147 if as_longs or c in key_comps or c in ('sig1','sig2'): |
| 148 tv2[c] = bytes_to_long(tv2[c]) |
| 149 tv2['key']=[] |
| 150 for c in key_comps: |
| 151 tv2['key'] += [tv2[c]] |
| 152 del tv2[c] |
| 153 return tv2 |
| 154 |
| 155 def _test_random_key(self, bits): |
| 156 elgObj = ElGamal.generate(bits, Random.new().read) |
| 157 self._check_private_key(elgObj) |
| 158 self._exercise_primitive(elgObj) |
| 159 pub = elgObj.publickey() |
| 160 self._check_public_key(pub) |
| 161 self._exercise_public_primitive(elgObj) |
| 162 |
| 163 def _check_private_key(self, elgObj): |
| 164 |
| 165 # Check capabilities |
| 166 self.failUnless(elgObj.has_private()) |
| 167 self.failUnless(elgObj.can_sign()) |
| 168 self.failUnless(elgObj.can_encrypt()) |
| 169 |
| 170 # Sanity check key data |
| 171 self.failUnless(1<elgObj.g<(elgObj.p-1)) |
| 172 self.assertEquals(pow(elgObj.g, elgObj.p-1, elgObj.p), 1) |
| 173 self.failUnless(1<elgObj.x<(elgObj.p-1)) |
| 174 self.assertEquals(pow(elgObj.g, elgObj.x, elgObj.p), elgObj.y) |
| 175 |
| 176 def _check_public_key(self, elgObj): |
| 177 |
| 178 # Check capabilities |
| 179 self.failIf(elgObj.has_private()) |
| 180 self.failUnless(elgObj.can_sign()) |
| 181 self.failUnless(elgObj.can_encrypt()) |
| 182 |
| 183 # Sanity check key data |
| 184 self.failUnless(1<elgObj.g<(elgObj.p-1)) |
| 185 self.assertEquals(pow(elgObj.g, elgObj.p-1, elgObj.p), 1) |
| 186 |
| 187 def _exercise_primitive(self, elgObj): |
| 188 # Test encryption/decryption |
| 189 plaintext = b("Test") |
| 190 ciphertext = elgObj.encrypt(plaintext, 123456789L) |
| 191 plaintextP = elgObj.decrypt(ciphertext) |
| 192 self.assertEquals(plaintext, plaintextP) |
| 193 |
| 194 # Test signature/verification |
| 195 signature = elgObj.sign(plaintext, 987654321L) |
| 196 elgObj.verify(plaintext, signature) |
| 197 |
| 198 def _exercise_public_primitive(self, elgObj): |
| 199 plaintext = b("Test") |
| 200 ciphertext = elgObj.encrypt(plaintext, 123456789L) |
| 201 |
| 202 def get_tests(config={}): |
| 203 tests = [] |
| 204 tests += list_test_cases(ElGamalTest) |
| 205 return tests |
| 206 |
| 207 if __name__ == '__main__': |
| 208 suite = lambda: unittest.TestSuite(get_tests()) |
| 209 unittest.main(defaultTest='suite') |
| 210 |
OLD | NEW |