зеркало из https://github.com/github/putty.git
Add tests of all the AES cipher modes.
This tests the CBC and SDCTR modes, in all key lengths, and in particular includes a set of SDCTR tests designed to test the procedure for incrementing the IV as a single 128-bit integer, by checking propagation of the carry between every pair of words.
This commit is contained in:
Родитель
7fd815014e
Коммит
48ff6f13e2
|
@ -5,7 +5,6 @@ import struct
|
|||
import itertools
|
||||
import contextlib
|
||||
import hashlib
|
||||
from binascii import unhexlify as unhex
|
||||
try:
|
||||
from math import gcd
|
||||
except ImportError:
|
||||
|
@ -28,6 +27,9 @@ def nbits(n):
|
|||
toret += 1
|
||||
return toret
|
||||
|
||||
def unhex(s):
|
||||
return s.replace(" ", "").replace("\n", "").decode("hex")
|
||||
|
||||
def ssh_uint32(n):
|
||||
return struct.pack(">L", n)
|
||||
def ssh_string(s):
|
||||
|
@ -753,6 +755,132 @@ class crypt(unittest.TestCase):
|
|||
self.assertEqual(
|
||||
fp, b"768 96:12:c8:bc:e6:03:75:86:e8:c7:b9:af:d8:0c:15:75")
|
||||
|
||||
def testAES(self):
|
||||
# My own test cases, generated by a mostly independent
|
||||
# reference implementation of AES in Python. ('Mostly'
|
||||
# independent in that it was written by me.)
|
||||
|
||||
def vector(cipher, key, iv, plaintext, ciphertext):
|
||||
c = ssh2_cipher_new(cipher)
|
||||
ssh2_cipher_setkey(c, key)
|
||||
ssh2_cipher_setiv(c, iv)
|
||||
self.assertEqual(ssh2_cipher_encrypt(c, plaintext), ciphertext)
|
||||
ssh2_cipher_setiv(c, iv)
|
||||
self.assertEqual(ssh2_cipher_decrypt(c, ciphertext), plaintext)
|
||||
|
||||
# Tests of CBC mode.
|
||||
|
||||
key = unhex(
|
||||
'98483c6eb40b6c31a448c22a66ded3b5e5e8d5119cac8327b655c8b5c4836489')
|
||||
iv = unhex('38f87b0b9b736160bfc0cbd8447af6ee')
|
||||
plaintext = unhex('''
|
||||
ee16271827b12d828f61d56fddccc38ccaa69601da2b36d3af1a34c51947b71a
|
||||
362f05e07bf5e7766c24599799b252ad2d5954353c0c6ca668c46779c2659c94
|
||||
8df04e4179666e335470ff042e213c8bcff57f54842237fbf9f3c7e6111620ac
|
||||
1c007180edd25f0e337c2a49d890a7173f6b52d61e3d2a21ddc8e41513a0e825
|
||||
afd5932172270940b01014b5b7fb8495946151520a126518946b44ea32f9b2a9
|
||||
''')
|
||||
|
||||
vector('aes128', key[:16], iv, plaintext, unhex('''
|
||||
547ee90514cb6406d5bb00855c8092892c58299646edda0b4e7c044247795c8d
|
||||
3c3eb3d91332e401215d4d528b94a691969d27b7890d1ae42fe3421b91c989d5
|
||||
113fefa908921a573526259c6b4f8e4d90ea888e1d8b7747457ba3a43b5b79b9
|
||||
34873ebf21102d14b51836709ee85ed590b7ca618a1e884f5c57c8ea73fe3d0d
|
||||
6bf8c082dd602732bde28131159ed0b6e9cf67c353ffdd010a5a634815aaa963'''))
|
||||
|
||||
vector('aes192', key[:24], iv, plaintext, unhex('''
|
||||
e3dee5122edd3fec5fab95e7db8c784c0cb617103e2a406fba4ae3b4508dd608
|
||||
4ff5723a670316cc91ed86e413c11b35557c56a6f5a7a2c660fc6ee603d73814
|
||||
73a287645be0f297cdda97aef6c51faeb2392fec9d33adb65138d60f954babd9
|
||||
8ee0daab0d1decaa8d1e07007c4a3c7b726948025f9fb72dd7de41f74f2f36b4
|
||||
23ac6a5b4b6b39682ec74f57d9d300e547f3c3e467b77f5e4009923b2f94c903'''))
|
||||
|
||||
vector('aes256', key[:32], iv, plaintext, unhex('''
|
||||
088c6d4d41997bea79c408925255266f6c32c03ea465a5f607c2f076ec98e725
|
||||
7e0beed79609b3577c16ebdf17d7a63f8865278e72e859e2367de81b3b1fe9ab
|
||||
8f045e1d008388a3cfc4ff87daffedbb47807260489ad48566dbe73256ce9dd4
|
||||
ae1689770a883b29695928f5983f33e8d7aec4668f64722e943b0b671c365709
|
||||
dfa86c648d5fb00544ff11bd29121baf822d867e32da942ba3a0d26299bcee13'''))
|
||||
|
||||
# Tests of SDCTR mode, one with a random IV and one with an IV
|
||||
# about to wrap round. More vigorous tests of IV carry and
|
||||
# wraparound behaviour are in the testAESSDCTR method.
|
||||
|
||||
sdctrIVs = [
|
||||
unhex('38f87b0b9b736160bfc0cbd8447af6ee'),
|
||||
unhex('fffffffffffffffffffffffffffffffe'),
|
||||
]
|
||||
|
||||
vector('aes128_ctr', key[:16], sdctrIVs[0], plaintext[:64], unhex('''
|
||||
d0061d7b6e8c4ef4fe5614b95683383f46cdd2766e66b6fb0b0f0b3a24520b2d
|
||||
15d869b06cbf685ede064bcf8fb5fb6726cfd68de7016696a126e9e84420af38'''))
|
||||
vector('aes128_ctr', key[:16], sdctrIVs[1], plaintext[:64], unhex('''
|
||||
49ac67164fd9ce8701caddbbc9a2b06ac6524d4aa0fdac95253971974b8f3bc2
|
||||
bb8d7c970f6bcd79b25218cc95582edf7711aae2384f6cf91d8d07c9d9b370bc'''))
|
||||
|
||||
vector('aes192_ctr', key[:24], sdctrIVs[0], plaintext[:64], unhex('''
|
||||
0baa86acbe8580845f0671b7ebad4856ca11b74e5108f515e34e54fa90f87a9a
|
||||
c6eee26686253c19156f9be64957f0dbc4f8ecd7cabb1f4e0afefe33888faeec'''))
|
||||
vector('aes192_ctr', key[:24], sdctrIVs[1], plaintext[:64], unhex('''
|
||||
2da1791250100dc0d1461afe1bbfad8fa0320253ba5d7905d837386ba0a3a41f
|
||||
01965c770fcfe01cf307b5316afb3981e0e4aa59a6e755f0a5784d9accdc52be'''))
|
||||
|
||||
vector('aes256_ctr', key[:32], sdctrIVs[0], plaintext[:64], unhex('''
|
||||
49c7b284222d408544c770137b6ef17ef770c47e24f61fa66e7e46cae4888882
|
||||
f980a0f2446956bf47d2aed55ebd2e0694bfc46527ed1fd33efe708fec2f8b1f'''))
|
||||
vector('aes256_ctr', key[:32], sdctrIVs[1], plaintext[:64], unhex('''
|
||||
f1d013c3913ccb4fc0091e25d165804480fb0a1d5c741bf012bba144afda6db2
|
||||
c512f3942018574bd7a8fdd88285a73d25ef81e621aebffb6e9b8ecc8e2549d4'''))
|
||||
|
||||
def testAESSDCTR(self):
|
||||
# A thorough test of the IV-incrementing component of SDCTR
|
||||
# mode. We set up an AES-SDCTR cipher object with the given
|
||||
# input IV; we encrypt two all-zero blocks, expecting the
|
||||
# return values to be the AES-ECB encryptions of the input IV
|
||||
# and the incremented version. Then we decrypt each of them by
|
||||
# feeding them to an AES-CBC cipher object with its IV set to
|
||||
# zero.
|
||||
|
||||
def increment(keylen, iv):
|
||||
key = b'\xab' * (keylen//8)
|
||||
sdctr = ssh2_cipher_new("aes{}_ctr".format(keylen))
|
||||
ssh2_cipher_setkey(sdctr, key)
|
||||
cbc = ssh2_cipher_new("aes{}".format(keylen))
|
||||
ssh2_cipher_setkey(cbc, key)
|
||||
|
||||
ssh2_cipher_setiv(sdctr, iv)
|
||||
ec0 = ssh2_cipher_encrypt(sdctr, b'\x00' * 16)
|
||||
ec1 = ssh2_cipher_encrypt(sdctr, b'\x00' * 16)
|
||||
ssh2_cipher_setiv(cbc, b'\x00' * 16)
|
||||
dc0 = ssh2_cipher_decrypt(cbc, ec0)
|
||||
ssh2_cipher_setiv(cbc, b'\x00' * 16)
|
||||
dc1 = ssh2_cipher_decrypt(cbc, ec1)
|
||||
self.assertEqual(iv, dc0)
|
||||
return dc1
|
||||
|
||||
def test(keylen, ivInteger):
|
||||
mask = (1 << 128) - 1
|
||||
ivInteger &= mask
|
||||
ivBinary = unhex("{:032x}".format(ivInteger))
|
||||
ivIntegerInc = (ivInteger + 1) & mask
|
||||
ivBinaryInc = unhex("{:032x}".format((ivIntegerInc)))
|
||||
actualResult = increment(keylen, ivBinary)
|
||||
self.assertEqual(actualResult, ivBinaryInc)
|
||||
|
||||
# Check every input IV you can make by gluing together 32-bit
|
||||
# pieces of the form 0, 1 or -1. This should test all the
|
||||
# places where carry propagation within the 128-bit integer
|
||||
# can go wrong.
|
||||
#
|
||||
# We also test this at all three AES key lengths, in case the
|
||||
# core cipher routines are written separately for each one.
|
||||
|
||||
for keylen in [128, 192, 256]:
|
||||
hexTestValues = ["00000000", "00000001", "ffffffff"]
|
||||
for ivHexBytes in itertools.product(*([hexTestValues] * 4)):
|
||||
ivInteger = int("".join(ivHexBytes), 16)
|
||||
test(keylen, ivInteger)
|
||||
|
||||
class standard_test_vectors(unittest.TestCase):
|
||||
def testAES(self):
|
||||
def vector(cipher, key, plaintext, ciphertext):
|
||||
|
|
Загрузка…
Ссылка в новой задаче