diff options
author | Eli Collins <elic@assurancetechnologies.com> | 2012-04-17 23:14:51 -0400 |
---|---|---|
committer | Eli Collins <elic@assurancetechnologies.com> | 2012-04-17 23:14:51 -0400 |
commit | 64ab6fc89b497efa9169f11d55251e417c4db0ba (patch) | |
tree | b3f6f5dc27b87a6bc90cb3686fa98239ee8ff053 /passlib/tests/test_utils.py | |
parent | 8eb4c4d3b58eec6802c698ddbf357b2fd243a68c (diff) | |
parent | cd029846fdc0c3d7ffc7f53caad4579e7e0e8725 (diff) | |
download | passlib-ironpython-support-dev.tar.gz |
Merge from defaultironpython-support-dev
Diffstat (limited to 'passlib/tests/test_utils.py')
-rw-r--r-- | passlib/tests/test_utils.py | 514 |
1 files changed, 85 insertions, 429 deletions
diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py index 678ae06..d317629 100644 --- a/passlib/tests/test_utils.py +++ b/passlib/tests/test_utils.py @@ -26,6 +26,60 @@ class MiscTest(TestCase): #NOTE: could test xor_bytes(), but it's exercised well enough by pbkdf2 test + def test_classproperty(self): + from passlib.utils import classproperty + + class test(object): + xvar = 1 + @classproperty + def xprop(cls): + return cls.xvar + + self.assertEqual(test.xprop, 1) + prop = test.__dict__['xprop'] + self.assertIs(prop.im_func, prop.__func__) + + def test_deprecated_function(self): + from passlib.utils import deprecated_function + # NOTE: not comprehensive, just tests the basic behavior + + @deprecated_function(deprecated="1.6", removed="1.8") + def test_func(*args): + "test docstring" + return args + + self.assertTrue(".. deprecated::" in test_func.__doc__) + + with catch_warnings(record=True) as wlog: + self.assertEqual(test_func(1,2), (1,2)) + self.consumeWarningList(wlog,[ + dict(category=DeprecationWarning, + message="the function passlib.tests.test_utils.test_func() " + "is deprecated as of Passlib 1.6, and will be " + "removed in Passlib 1.8." + ), + ]) + + def test_memoized_property(self): + from passlib.utils import memoized_property + + class dummy(object): + counter = 0 + + @memoized_property + def value(self): + value = self.counter + self.counter = value+1 + return value + + d = dummy() + self.assertEqual(d.value, 0) + self.assertEqual(d.value, 0) + self.assertEqual(d.counter, 1) + + prop = dummy.value + self.assertIs(prop.im_func, prop.__func__) + def test_getrandbytes(self): "test getrandbytes()" from passlib.utils import getrandbytes, rng @@ -241,13 +295,11 @@ class MiscTest(TestCase): def test_saslprep(self): "test saslprep() unicode normalizer" - from passlib.utils import saslprep as sp, _ipy_missing_stringprep - + self.require_stringprep() + from passlib.utils.compat import IRONPYTHON if IRONPYTHON: - self.assertTrue(_ipy_missing_stringprep, - "alert passlib author that IPY has stringprep support!") - self.assertRaises(NotImplementedError, sp, u('abc')) - raise self.skipTest("stringprep missing under IPY") + warn("IronPython now has stringprep support!") + from passlib.utils import saslprep as sp # invalid types self.assertRaises(TypeError, sp, None) @@ -290,6 +342,8 @@ class MiscTest(TestCase): # unassigned code points (as of unicode 3.2) self.assertRaises(ValueError, sp, u("\u0900")) self.assertRaises(ValueError, sp, u("\uFFF8")) + # tagging characters + self.assertRaises(ValueError, sp, u("\U000e0001")) # verify bidi behavior # if starts with R/AL -- must end with R/AL @@ -450,86 +504,32 @@ class CodecTest(TestCase): self.assertFalse(is_same_codec("ascii", "utf-8")) #========================================================= -#test des module +# base64engine #========================================================= -import passlib.utils.des as des - -class DesTest(TestCase): - - #test vectors taken from http://www.skepticfiles.org/faq/testdes.htm - - #data is list of (key, plaintext, ciphertext), all as 64 bit hex string - test_des_vectors = [ - (line[4:20], line[21:37], line[38:54]) - for line in -b(""" 0000000000000000 0000000000000000 8CA64DE9C1B123A7 - FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58 - 3000000000000000 1000000000000001 958E6E627A05557B - 1111111111111111 1111111111111111 F40379AB9E0EC533 - 0123456789ABCDEF 1111111111111111 17668DFC7292532D - 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD - 0000000000000000 0000000000000000 8CA64DE9C1B123A7 - FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4 - 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B - 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 - 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A - 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A - 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 - 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B - 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 - 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A - 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F - 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 - 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 - 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A - 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 - 025816164629B007 480D39006EE762F2 A1F9915541020B56 - 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 - 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC - 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A - 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 - 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 - 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100 - 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606 - E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7 - 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451 - FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE - 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D - FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2 - """).split(b("\n")) if line.strip() - ] +class Base64EngineTest(TestCase): + "test standalone parts of Base64Engine" + # NOTE: most Base64Engine testing done via _Base64Test subclasses below. - def test_des_encrypt_block(self): - for k,p,c in self.test_des_vectors: - k = unhexlify(k) - p = unhexlify(p) - c = unhexlify(c) - result = des.des_encrypt_block(k,p) - self.assertEqual(result, c, "key=%r p=%r:" % (k,p)) - - #test 7 byte key - #FIXME: use a better key - k,p,c = b('00000000000000'), b('FFFFFFFFFFFFFFFF'), b('355550B2150E2451') - k = unhexlify(k) - p = unhexlify(p) - c = unhexlify(c) - result = des.des_encrypt_block(k,p) - self.assertEqual(result, c, "key=%r p=%r:" % (k,p)) - - def test_mdes_encrypt_int_block(self): - for k,p,c in self.test_des_vectors: - k = int(k,16) - p = int(p,16) - c = int(c,16) - result = des.mdes_encrypt_int_block(k,p, salt=0, rounds=1) - self.assertEqual(result, c, "key=%r p=%r:" % (k,p)) - - #TODO: test other des methods (eg: mdes_encrypt_int_block w/ salt & rounds) - # though des-crypt builtin backend test should thump it well enough + def test_constructor(self): + from passlib.utils import Base64Engine, AB64_CHARS + + # bad charmap type + self.assertRaises(TypeError, Base64Engine, 1) + + # bad charmap size + self.assertRaises(ValueError, Base64Engine, AB64_CHARS[:-1]) + + # dup charmap letter + self.assertRaises(ValueError, Base64Engine, AB64_CHARS[:-1] + "A") + + def test_ab64(self): + from passlib.utils import ab64_decode + # TODO: make ab64_decode (and a b64 variant) *much* stricter about + # padding chars, etc. + + # 1 mod 4 not valid + self.assertRaises(ValueError, ab64_decode, "abcde") -#========================================================= -# base64engine -#========================================================= class _Base64Test(TestCase): "common tests for all Base64Engine instances" #========================================================= @@ -730,6 +730,8 @@ class _Base64Test(TestCase): out = engine.decode_bytes(tmp) self.assertEqual(out, result) + self.assertRaises(TypeError, engine.encode_transposed_bytes, u("a"), []) + def test_decode_transposed_bytes(self): "test decode_transposed_bytes()" engine = self.engine @@ -895,351 +897,5 @@ class H64Big_Test(_Base64Test): ] #========================================================= -#test md4 -#========================================================= -class _MD4_Test(TestCase): - #test vectors from http://www.faqs.org/rfcs/rfc1320.html - A.5 - - hash = None - - vectors = [ - # input -> hex digest - (b(""), "31d6cfe0d16ae931b73c59d7e0c089c0"), - (b("a"), "bde52cb31de33e46245e05fbdbd6fb24"), - (b("abc"), "a448017aaf21d8525fc10ae87aa6729d"), - (b("message digest"), "d9130a8164549fe818874806e1c7014b"), - (b("abcdefghijklmnopqrstuvwxyz"), "d79e1c308aa5bbcdeea8ed63df412da9"), - (b("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), "043f8582f241db351ce627e153e7f0e4"), - (b("12345678901234567890123456789012345678901234567890123456789012345678901234567890"), "e33b4ddc9c38f2199c3e7b164fcc0536"), - ] - - def test_md4_update(self): - "test md4 update" - md4 = self.hash - h = md4(b('')) - self.assertEqual(h.hexdigest(), "31d6cfe0d16ae931b73c59d7e0c089c0") - - #NOTE: under py2, hashlib methods try to encode to ascii, - # though shouldn't rely on that. - if PY3: - self.assertRaises(TypeError, h.update, u('x')) - - h.update(b('a')) - self.assertEqual(h.hexdigest(), "bde52cb31de33e46245e05fbdbd6fb24") - - h.update(b('bcdefghijklmnopqrstuvwxyz')) - self.assertEqual(h.hexdigest(), "d79e1c308aa5bbcdeea8ed63df412da9") - - def test_md4_hexdigest(self): - "test md4 hexdigest()" - md4 = self.hash - for input, hex in self.vectors: - out = md4(input).hexdigest() - self.assertEqual(out, hex) - - def test_md4_digest(self): - "test md4 digest()" - md4 = self.hash - for input, hex in self.vectors: - out = bascii_to_str(hexlify(md4(input).digest())) - self.assertEqual(out, hex) - - def test_md4_copy(self): - "test md4 copy()" - md4 = self.hash - h = md4(b('abc')) - - h2 = h.copy() - h2.update(b('def')) - self.assertEqual(h2.hexdigest(), '804e7f1c2586e50b49ac65db5b645131') - - h.update(b('ghi')) - self.assertEqual(h.hexdigest(), 'c5225580bfe176f6deeee33dee98732c') - -# -#now do a bunch of things to test multiple possible backends. -# -import passlib.utils.md4 as md4_mod - -has_ssl_md4 = (md4_mod.md4 is not md4_mod._builtin_md4) - -if has_ssl_md4: - class MD4_SSL_Test(_MD4_Test): - descriptionPrefix = "MD4 (SSL version)" - hash = staticmethod(md4_mod.md4) - -if not has_ssl_md4 or enable_option("cover"): - class MD4_Builtin_Test(_MD4_Test): - descriptionPrefix = "MD4 (builtin version)" - hash = md4_mod._builtin_md4 - -#========================================================= -#test passlib.utils.pbkdf2 -#========================================================= -import hashlib -import hmac -from passlib.utils import pbkdf2 - -#TODO: should we bother testing hmac_sha1() function? it's verified via sha1_crypt testing. -class CryptoTest(TestCase): - "test various crypto functions" - - ndn_formats = ["hashlib", "iana"] - ndn_values = [ - # (iana name, hashlib name, ... other unnormalized names) - ("md5", "md5", "SCRAM-MD5-PLUS", "MD-5"), - ("sha1", "sha-1", "SCRAM-SHA-1", "SHA1"), - ("sha256", "sha-256", "SHA_256", "sha2-256"), - ("ripemd", "ripemd", "SCRAM-RIPEMD", "RIPEMD"), - ("ripemd160", "ripemd-160", - "SCRAM-RIPEMD-160", "RIPEmd160"), - ("test128", "test-128", "TEST128"), - ("test2", "test2", "TEST-2"), - ("test3128", "test3-128", "TEST-3-128"), - ] - - def test_norm_hash_name(self): - "test norm_hash_name()" - from itertools import chain - from passlib.utils.pbkdf2 import norm_hash_name, _nhn_hash_names - - # test formats - for format in self.ndn_formats: - norm_hash_name("md4", format) - self.assertRaises(ValueError, norm_hash_name, "md4", None) - self.assertRaises(ValueError, norm_hash_name, "md4", "fake") - - # test types - self.assertEqual(norm_hash_name(u("MD4")), "md4") - self.assertEqual(norm_hash_name(b("MD4")), "md4") - self.assertRaises(TypeError, norm_hash_name, None) - - # test selected results - with catch_warnings(): - warnings.filterwarnings("ignore", '.*unknown hash') - for row in chain(_nhn_hash_names, self.ndn_values): - for idx, format in enumerate(self.ndn_formats): - correct = row[idx] - for value in row: - result = norm_hash_name(value, format) - self.assertEqual(result, correct, - "name=%r, format=%r:" % (value, - format)) - -class KdfTest(TestCase): - "test kdf helpers" - - def test_pbkdf1(self): - "test pbkdf1" - for secret, salt, rounds, klen, hash, correct in [ - #http://www.di-mgt.com.au/cryptoKDFs.html - (b('password'), hb('78578E5A5D63CB06'), 1000, 16, 'sha1', - hb('dc19847e05c64d2faf10ebfb4a3d2a20')), - ]: - result = pbkdf2.pbkdf1(secret, salt, rounds, klen, hash) - self.assertEqual(result, correct) - - #test rounds < 1 - #test klen < 0 - #test klen > block size - #test invalid hash - -#NOTE: this is not run directly, but via two subclasses (below) -class _Pbkdf2BackendTest(TestCase): - "test builtin unix crypt backend" - enable_m2crypto = False - - def setUp(self): - #disable m2crypto support so we'll always use software backend - if not self.enable_m2crypto: - self._orig_EVP = pbkdf2._EVP - pbkdf2._EVP = None - else: - #set flag so tests can check for m2crypto presence quickly - self.enable_m2crypto = bool(pbkdf2._EVP) - pbkdf2._clear_prf_cache() - - def tearDown(self): - if not self.enable_m2crypto: - pbkdf2._EVP = self._orig_EVP - pbkdf2._clear_prf_cache() - - #TODO: test get_prf() behavior in various situations - though overall behavior tested via pbkdf2 - - def test_rfc3962(self): - "rfc3962 test vectors" - self.assertFunctionResults(pbkdf2.pbkdf2, [ - # result, secret, salt, rounds, keylen, digest="sha1" - - #test case 1 / 128 bit - ( - hb("cdedb5281bb2f801565a1122b2563515"), - b("password"), b("ATHENA.MIT.EDUraeburn"), 1, 16 - ), - - #test case 2 / 128 bit - ( - hb("01dbee7f4a9e243e988b62c73cda935d"), - b("password"), b("ATHENA.MIT.EDUraeburn"), 2, 16 - ), - - #test case 2 / 256 bit - ( - hb("01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86"), - b("password"), b("ATHENA.MIT.EDUraeburn"), 2, 32 - ), - - #test case 3 / 256 bit - ( - hb("5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13"), - b("password"), b("ATHENA.MIT.EDUraeburn"), 1200, 32 - ), - - #test case 4 / 256 bit - ( - hb("d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee"), - b("password"), b('\x12\x34\x56\x78\x78\x56\x34\x12'), 5, 32 - ), - - #test case 5 / 256 bit - ( - hb("139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1"), - b("X"*64), b("pass phrase equals block size"), 1200, 32 - ), - - #test case 6 / 256 bit - ( - hb("9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a"), - b("X"*65), b("pass phrase exceeds block size"), 1200, 32 - ), - ]) - - def test_rfc6070(self): - "rfc6070 test vectors" - self.assertFunctionResults(pbkdf2.pbkdf2, [ - - ( - hb("0c60c80f961f0e71f3a9b524af6012062fe037a6"), - b("password"), b("salt"), 1, 20, - ), - - ( - hb("ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"), - b("password"), b("salt"), 2, 20, - ), - - ( - hb("4b007901b765489abead49d926f721d065a429c1"), - b("password"), b("salt"), 4096, 20, - ), - - #just runs too long - could enable if ALL option is set - ##( - ## - ## unhexlify("eefe3d61cd4da4e4e9945b3d6ba2158c2634e984"), - ## "password", "salt", 16777216, 20, - ##), - - ( - hb("3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"), - b("passwordPASSWORDpassword"), - b("saltSALTsaltSALTsaltSALTsaltSALTsalt"), - 4096, 25, - ), - - ( - hb("56fa6aa75548099dcc37d7f03425e0c3"), - b("pass\00word"), b("sa\00lt"), 4096, 16, - ), - ]) - - def test_invalid_values(self): - - #invalid rounds - self.assertRaises(ValueError, pbkdf2.pbkdf2, b('password'), b('salt'), -1, 16) - self.assertRaises(ValueError, pbkdf2.pbkdf2, b('password'), b('salt'), 0, 16) - self.assertRaises(TypeError, pbkdf2.pbkdf2, b('password'), b('salt'), 'x', 16) - - #invalid keylen - self.assertRaises(ValueError, pbkdf2.pbkdf2, b('password'), b('salt'), - 1, 20*(2**32-1)+1) - - #invalid salt type - self.assertRaises(TypeError, pbkdf2.pbkdf2, b('password'), 5, 1, 10) - - #invalid secret type - self.assertRaises(TypeError, pbkdf2.pbkdf2, 5, b('salt'), 1, 10) - - #invalid hash - self.assertRaises(ValueError, pbkdf2.pbkdf2, b('password'), b('salt'), 1, 16, 'hmac-foo') - self.assertRaises(ValueError, pbkdf2.pbkdf2, b('password'), b('salt'), 1, 16, 'foo') - self.assertRaises(TypeError, pbkdf2.pbkdf2, b('password'), b('salt'), 1, 16, 5) - - def test_default_keylen(self): - "test keylen==-1" - self.assertEqual(len(pbkdf2.pbkdf2(b('password'), b('salt'), 1, -1, - prf='hmac-sha1')), 20) - - self.assertEqual(len(pbkdf2.pbkdf2(b('password'), b('salt'), 1, -1, - prf='hmac-sha256')), 32) - - def test_hmac_sha1(self): - "test independant hmac_sha1() method" - self.assertEqual( - pbkdf2.hmac_sha1(b("secret"), b("salt")), - b('\xfc\xd4\x0c;]\r\x97\xc6\xf1S\x8d\x93\xb9\xeb\xc6\x00\x04.\x8b\xfe') - ) - - def test_sha1_string(self): - "test various prf values" - self.assertEqual( - pbkdf2.pbkdf2(b("secret"), b("salt"), 10, 16, "hmac-sha1"), - b('\xe2H\xfbk\x136QF\xf8\xacc\x07\xcc"(\x12') - ) - - def test_sha512_string(self): - "test alternate digest string (sha512)" - self.assertFunctionResults(pbkdf2.pbkdf2, [ - # result, secret, salt, rounds, keylen, digest="sha1" - - #case taken from example in http://grub.enbug.org/Authentication - ( - hb("887CFF169EA8335235D8004242AA7D6187A41E3187DF0CE14E256D85ED97A97357AAA8FF0A3871AB9EEFF458392F462F495487387F685B7472FC6C29E293F0A0"), - b("hello"), - hb("9290F727ED06C38BA4549EF7DE25CF5642659211B7FC076F2D28FEFD71784BB8D8F6FB244A8CC5C06240631B97008565A120764C0EE9C2CB0073994D79080136"), - 10000, 64, "hmac-sha512" - ), - ]) - - def test_sha512_function(self): - "test custom digest function" - def prf(key, msg): - return hmac.new(key, msg, hashlib.sha512).digest() - - self.assertFunctionResults(pbkdf2.pbkdf2, [ - # result, secret, salt, rounds, keylen, digest="sha1" - - #case taken from example in http://grub.enbug.org/Authentication - ( - hb("887CFF169EA8335235D8004242AA7D6187A41E3187DF0CE14E256D85ED97A97357AAA8FF0A3871AB9EEFF458392F462F495487387F685B7472FC6C29E293F0A0"), - b("hello"), - hb("9290F727ED06C38BA4549EF7DE25CF5642659211B7FC076F2D28FEFD71784BB8D8F6FB244A8CC5C06240631B97008565A120764C0EE9C2CB0073994D79080136"), - 10000, 64, prf, - ), - ]) - -has_m2crypto = (pbkdf2._EVP is not None) - -if has_m2crypto: - class Pbkdf2_M2Crypto_Test(_Pbkdf2BackendTest): - descriptionPrefix = "pbkdf2 (m2crypto backend)" - enable_m2crypto = True - -if not has_m2crypto or enable_option("cover"): - class Pbkdf2_Builtin_Test(_Pbkdf2BackendTest): - descriptionPrefix = "pbkdf2 (builtin backend)" - enable_m2crypto = False - -#========================================================= #EOF #========================================================= |