0,0 → 1,189 |
# -*- coding: utf-8 -*- |
# |
# SelfTest/Hash/common.py: Common code for CryptoPlus.SelfTest.Hash |
# |
# ======================================================================= |
# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net> |
# |
# Permission is hereby granted, free of charge, to any person obtaining |
# a copy of this software and associated documentation files (the |
# "Software"), to deal in the Software without restriction, including |
# without limitation the rights to use, copy, modify, merge, publish, |
# distribute, sublicense, and/or sell copies of the Software, and to |
# permit persons to whom the Software is furnished to do so. |
# |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# ======================================================================= |
# |
|
"""Self-testing for PyCryptoPlus hash modules""" |
|
__revision__ = "$Id$" |
|
import sys |
import unittest |
from binascii import a2b_hex, b2a_hex |
|
# For compatibility with Python 2.1 and Python 2.2 |
if sys.hexversion < 0x02030000: |
# Python 2.1 doesn't have a dict() function |
# Python 2.2 dict() function raises TypeError if you do dict(MD5='blah') |
def dict(**kwargs): |
return kwargs.copy() |
else: |
dict = __builtins__['dict'] |
|
class _NoDefault: pass # sentinel object |
def _extract(d, k, default=_NoDefault): |
"""Get an item from a dictionary, and remove it from the dictionary.""" |
try: |
retval = d[k] |
except KeyError: |
if default is _NoDefault: |
raise |
return default |
del d[k] |
return retval |
|
# Generic cipher test case |
class CipherSelfTest(unittest.TestCase): |
|
def __init__(self, module, params): |
unittest.TestCase.__init__(self) |
self.module = module |
|
# Extract the parameters |
params = params.copy() |
self.description = _extract(params, 'description') |
self.key = _extract(params, 'key') |
self.plaintext = _extract(params, 'plaintext') |
self.ciphertext = _extract(params, 'ciphertext') |
|
mode = _extract(params, 'mode', None) |
if mode is not None: |
# Block cipher |
self.mode = getattr(self.module, "MODE_" + mode) |
self.iv = _extract(params, 'iv', None) |
else: |
# Stream cipher |
self.mode = None |
self.iv = None |
|
self.extra_params = params |
|
def shortDescription(self): |
return self.description |
|
def _new(self): |
if self.mode is None: |
# Stream cipher |
return self.module.new(a2b_hex(self.key), **self.extra_params) |
elif self.iv is None: |
# Block cipher without iv |
return self.module.new(a2b_hex(self.key), self.mode, **self.extra_params) |
else: |
# Block cipher with iv |
return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.iv), **self.extra_params) |
|
def runTest(self): |
plaintext = a2b_hex(self.plaintext) |
ciphertext = a2b_hex(self.ciphertext) |
|
ct1 = b2a_hex(self._new().encrypt(plaintext)) |
pt1 = b2a_hex(self._new().decrypt(ciphertext)) |
ct2 = b2a_hex(self._new().encrypt(plaintext)) |
pt2 = b2a_hex(self._new().decrypt(ciphertext)) |
|
self.assertEqual(self.ciphertext, ct1) |
self.assertEqual(self.ciphertext, ct2) |
self.assertEqual(self.plaintext, pt1) |
self.assertEqual(self.plaintext, pt2) |
|
def make_block_tests(module, module_name, test_data): |
tests = [] |
for i in range(len(test_data)): |
row = test_data[i] |
|
# Build the "params" dictionary |
params = {'mode': 'ECB'} |
if len(row) == 3: |
(params['plaintext'], params['ciphertext'], params['key']) = row |
elif len(row) == 4: |
(params['plaintext'], params['ciphertext'], params['key'], params['description']) = row |
elif len(row) == 5: |
(params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row |
params.update(extra_params) |
else: |
raise AssertionError("Unsupported tuple size %d" % (len(row),)) |
|
# Build the display-name for the test |
p2 = params.copy() |
p_key = _extract(p2, 'key') |
p_plaintext = _extract(p2, 'plaintext') |
p_ciphertext = _extract(p2, 'ciphertext') |
p_description = _extract(p2, 'description', None) |
p_mode = p2.get('mode', 'ECB') |
if p_mode == 'ECB': |
_extract(p2, 'mode', 'ECB') |
|
if p_description is not None: |
description = p_description |
elif p_mode == 'ECB' and not p2: |
description = "p=%s, k=%s" % (p_plaintext, p_key) |
else: |
description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) |
name = "%s #%d: %s" % (module_name, i+1, description) |
params['description'] = name |
|
# Add the test to the test suite |
tests.append(CipherSelfTest(module, params)) |
return tests |
|
def make_stream_tests(module, module_name, test_data): |
tests = [] |
for i in range(len(test_data)): |
row = test_data[i] |
|
# Build the "params" dictionary |
params = {} |
if len(row) == 3: |
(params['plaintext'], params['ciphertext'], params['key']) = row |
elif len(row) == 4: |
(params['plaintext'], params['ciphertext'], params['key'], params['description']) = row |
elif len(row) == 5: |
(params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row |
params.update(extra_params) |
else: |
raise AssertionError("Unsupported tuple size %d" % (len(row),)) |
|
# Build the display-name for the test |
p2 = params.copy() |
p_key = _extract(p2, 'key') |
p_plaintext = _extract(p2, 'plaintext') |
p_ciphertext = _extract(p2, 'ciphertext') |
p_description = _extract(p2, 'description', None) |
|
if p_description is not None: |
description = p_description |
elif not p2: |
description = "p=%s, k=%s" % (p_plaintext, p_key) |
else: |
description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) |
name = "%s #%d: %s" % (module_name, i+1, description) |
params['description'] = name |
|
# Add the test to the test suite |
tests.append(CipherSelfTest(module, params)) |
return tests |
|
# vim:set ts=4 sw=4 sts=4 expandtab: |