From: Brian Warner Date: Thu, 14 Dec 2006 10:39:50 +0000 (-0700) Subject: move all packages into src/, fix allmydata.Crypto build. Now you must perform a ... X-Git-Tag: tahoe_v0.1.0-0-UNSTABLE~431 X-Git-Url: https://git.rkrishnan.org/htmlfontify-example.html?a=commitdiff_plain;h=349037855133e4a77ee44aee51243700cadef5d0;p=tahoe-lafs%2Ftahoe-lafs.git move all packages into src/, fix allmydata.Crypto build. Now you must perform a 'setup.py build' before using anything, and you must add the build directory (build/lib.linux-i686-2.4) to your PYTHONPATH before doing anything --- diff --git a/Crypto/ACKS b/Crypto/ACKS deleted file mode 100644 index 2acfc304..00000000 --- a/Crypto/ACKS +++ /dev/null @@ -1,34 +0,0 @@ -Acknowledgements ----------------- - -This list is sorted in alphabetical order, and is probably incomplete. -I'd like to thank everybody who contributed in any way, with code, bug -reports, and comments. - ---amk - -Tim Berners-Lee -Ian Bicking -Joris Bontje -Antoon Bosselaers -Andrea Bottoni -Andrew Eland -Philippe Frycia -Peter Gutmann -Hirendra Hindocha -Nikhil Jhingan -Piers Lauder -M.-A. Lemburg -Wim Lewis -Mark Moraes -Lim Chee Siang -Bryan Olson -Wallace Owen -Colin Plumb -James P. Rutledge -Matt Schreiner -Peter Simmons -Paul Swartz -Kevin M. Turner -Eric Young - diff --git a/Crypto/ChangeLog b/Crypto/ChangeLog deleted file mode 100644 index 30e325c1..00000000 --- a/Crypto/ChangeLog +++ /dev/null @@ -1,316 +0,0 @@ - -2.0.1 -===== - - * Fix SHA256 and RIPEMD on AMD64 platform. - * Deleted Demo/ directory. - * Add PublicKey to Crypto.__all__ - - -2.0 -=== - - * Added SHA256 module contributed by Jeethu Rao, with test data - from Taylor Boon. - - * Fixed AES.c compilation problems with Borland C. - (Contributed by Jeethu Rao.) - - * Fix ZeroDivisionErrors on Windows, caused by the system clock - not having enough resolution. - - * Fix 2.1/2.2-incompatible use of (key not in dict), - pointed out by Ian Bicking. - - * Fix FutureWarning in Crypto.Util.randpool, noted by James P Rutledge. - - -1.9alpha6 -========= - - * Util.number.getPrime() would inadvertently round off the bit - size; if you asked for a 129-bit prime or 135-bit prime, you - got a 128-bit prime. - - * Added Util/test/prime_speed.py to measure the speed of prime - generation, and PublicKey/test/rsa_speed.py to measure - the speed of RSA operations. - - * Merged the _rsa.c and _dsa.c files into a single accelerator - module, _fastmath.c. - - * Speed improvements: Added fast isPrime() function to _fastmath, - cutting the time to generate a 1024-bit prime by a factor of 10. - Optimized the C version of RSA decryption to use a longer series - of operations that's roughly 3x faster than a single - exponentiation. (Contributed by Joris Bontje.) - - * Added support to RSA key objects for blinding and unblinding - data. (Contributed by Joris Bontje.) - - * Simplified RSA key generation: hard-wired the encryption - exponent to 65537 instead of generating a random prime; - generate prime factors in a loop until the product - is large enough. - - * Renamed cansign(), canencrypt(), hasprivate(), to - can_sign, can_encrypt, has_private. If people shriek about - this change very loudly, I'll add aliases for the old method - names that log a warning and call the new method. - - -1.9alpha5 -========= - - * Many randpool changes. RandomPool now has a - randomize(N:int) method that can be called to get N - bytes of entropy for the pool (N defaults to 0, - which 'fills up' the pool's entropy) KeyboardRandom - overloads this method. - - * Added src/winrand.c for Crypto.Util.winrandom and - now use winrandom for _randomize if possible. - (Calls Windows CryptoAPI CryptGenRandom) - - * Several additional places for stirring the pool, - capturing inter-event entropy when reading/writing, - stirring before and after saves. - - * RandomPool.add_event now returns the number of - estimated bits of added entropy, rather than the - pool entropy itself (since the pool entropy is - capped at the number of bits in the pool) - - * Moved termios code from KeyboardRandomPool into a - KeyboardEntry class, provided a version for Windows - using msvcrt. - - * Fix randpool.py crash on machines with poor timer resolution. - (Reported by Mark Moraes and others.) - - * If the GNU GMP library is available, two C extensions will be - compiled to speed up RSA and DSA operations. (Contributed by - Paul Swartz.) - - * DES3 with a 24-byte key was broken; now fixed. - (Patch by Philippe Frycia.) - - -1.9alpha4 -========= - - * Fix compilation problem on Windows. - - * HMAC.py fixed to work with pre-2.2 Pythons - - * setup.py now dies if built with Python 1.x - - -1.9alpha3 -========= - - * Fix a ref-counting bug that caused core dumps. - (Reported by Piers Lauder and an anonymous SF poster.) - - -1.9alpha2 -========= - - * (Backwards incompatible) The old Crypto.Hash.HMAC module is - gone, replaced by a copy of hmac.py from Python 2.2's standard - library. It will display a warning on interpreter versions - older than 2.2. - - * (Backwards incompatible) Restored the Crypto.Protocol package, - and modernized and tidied up the two modules in it, - AllOrNothing.py and Chaffing.py, renaming various methods - and changing the interface. - - * (Backwards incompatible) Changed the function names in - Crypto.Util.RFC1751. - - * Restored the Crypto.PublicKey package at user request. I - think I'll leave it in the package and warn about it in the - documentation. I hope that eventually I can point to - someone else's better public-key code, and at that point I - may insert warnings and begin the process of deprecating - this code. - - * Fix use of a Python 2.2 C function, replacing it with a - 2.1-compatible equivalent. (Bug report and patch by Andrew - Eland.) - - * Fix endianness bugs that caused test case failures on Sparc, - PPC, and doubtless other platforms. - - * Fixed compilation problem on FreeBSD and MacOS X. - - * Expanded the test suite (requires Sancho, from - http://www.mems-exchange.org/software/sancho/) - - * Added lots of docstrings, so 'pydoc Crypto' now produces - helpful output. (Open question: maybe *all* of the documentation - should be moved into docstrings?) - - * Make test.py automatically add the build/* directory to sys.path. - - * Removed 'inline' declaration from C functions. Some compilers - don't support it, and Python's pyconfig.h no longer tells you whether - it's supported or not. After this change, some ciphers got slower, - but others got faster. - - * The C-level API has been changed to reduce the amount of - memory-to-memory copying. This makes the code neater, but - had ambiguous performance effects; again, some ciphers got slower - and others became faster. Probably this is due to my compiler - optimizing slightly worse or better as a result. - - * Moved C source implementations into src/ from block/, hash/, - and stream/. Having Hash/ and hash/ directories causes problems - on case-insensitive filesystems such as Mac OS. - - * Cleaned up the C code for the extensions. - - -1.9alpha1 -========= - - * Added Crypto.Cipher.AES. - - * Added the CTR mode and the variable-sized CFB mode from the - NIST standard on feedback modes. - - * Removed Diamond, HAVAL, MD5, Sapphire, SHA, and Skipjack. MD5 - and SHA are included with Python; the others are all of marginal - usefulness in the real world. - - * Renamed the module-level constants ECB, CFB, &c., to MODE_ECB, - MODE_CFB, as part of making the block encryption modules - compliant with PEP 272. (I'm not sure about this change; - if enough users complain about it, I might back it out.) - - * Made the hashing modules compliant with PEP 247 (not backward - compatible -- the major changes are that the constructor is now - MD2.new and not MD2.MD2, and the size of the digest is now - given as 'digest_size', not 'digestsize'. - - * The Crypto.PublicKey package is no longer installed; the - interfaces are all wrong, and I have no idea what the right - interfaces should be. - - -1.1alpha2 -========= - * Most importantly, the distribution has been broken into two -parts: exportable, and export-controlled. The exportable part -contains all the hashing algorithms, signature-only public key -algorithms, chaffing & winnowing, random number generation, various -utility modules, and the documentation. - - The export-controlled part contains public-key encryption -algorithms such as RSA and ElGamal, and bulk encryption algorithms -like DES, IDEA, or Skipjack. Getting this code still requires that -you go through an access control CGI script, and denies you access if -you're outside the US or Canada. - - * Added the RIPEMD hashing algorithm. (Contributed by -Hirendra Hindocha.) - - * Implemented the recently declassified Skipjack block -encryption algorithm. My implementation runs at 864 K/sec on a -PII/266, which isn't particularly fast, but you're probably better off -using another algorithm anyway. :) - - * A simple XOR cipher has been added, mostly for use by the -chaffing/winnowing code. (Contributed by Barry Warsaw.) - - * Added Protocol.Chaffing and Hash.HMAC.py. (Contributed by -Barry Warsaw.) - - Protocol.Chaffing implements chaffing and winnowing, recently -proposed by R. Rivest, which hides a message (the wheat) by adding -many noise messages to it (the chaff). The chaff can be discarded by -the receiver through a message authentication code. The neat thing -about this is that it allows secret communication without actually -having an encryption algorithm, and therefore this falls within the -exportable subset. - - * Tidied up randpool.py, and removed its use of a block -cipher; this makes it work with only the export-controlled subset -available. - - * Various renamings and reorganizations, mostly internal. - - -1.0.2 -===== - - * Changed files to work with Python 1.5; everything has been -re-arranged into a hierarchical package. (Not backward compatible.) -The package organization is: -Crypto. - Hash. - MD2, MD4, MD5, SHA, HAVAL - Cipher. - ARC2, ARC4, Blowfish, CAST, DES, DES3, Diamond, - IDEA, RC5, Sapphire - PublicKey. - DSA, ElGamal, qNEW, RSA - Util. - number, randpool, RFC1751 - - Since this is backward-incompatible anyway, I also changed -module names from all lower-case to mixed-case: diamond -> Diamond, -rc5 -> RC5, etc. That had been an annoying inconsistency for a while. - - * Added CAST5 module contributed by . - - * Added qNEW digital signature algorithm (from the digisign.py -I advertised a while back). (If anyone would like to suggest new -algorithms that should be implemented, please do; I think I've got -everything that's really useful at the moment, but...) - - * Support for keyword arguments has been added. This allowed -removing the obnoxious key handling for Diamond and RC5, where the -first few bytes of the key indicated the number of rounds to use, and -various other parameters. Now you need only do something like: - -from Crypto.Cipher import RC5 -obj = RC5.new(key, RC5.ECB, rounds=8) - -(Not backward compatible.) - - * Various function names have been changed, and parameter -names altered. None of these were part of the public interface, so it -shouldn't really matter much. - - * Various bugs fixed, the test suite has been expanded, and -the build process simplified. - - * Updated the documentation accordingly. - - -1.0.1 -===== - - * Changed files to work with Python 1.4 . - - * The DES and DES3 modules now automatically correct the -parity of their keys. - - * Added R. Rivest's DES test (see http://theory.lcs.mit.edu/~rivest/destest.txt) - - -1.0.0 -===== - - * REDOC III succumbed to differential cryptanalysis, and has -been removed. - - * The crypt and rotor modules have been dropped; they're still -available in the standard Python distribution. - - * The Ultra-Fast crypt() module has been placed in a separate -distribution. - - * Various bugs fixed. diff --git a/Crypto/Cipher/__init__.py b/Crypto/Cipher/__init__.py deleted file mode 100644 index 9f8096ae..00000000 --- a/Crypto/Cipher/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -"""Secret-key encryption algorithms. - -Secret-key encryption algorithms transform plaintext in some way that -is dependent on a key, producing ciphertext. This transformation can -easily be reversed, if (and, hopefully, only if) one knows the key. - -The encryption modules here all support the interface described in PEP -272, "API for Block Encryption Algorithms". - -If you don't know which algorithm to choose, use AES because it's -standard and has undergone a fair bit of examination. - -Crypto.Cipher.AES Advanced Encryption Standard -Crypto.Cipher.ARC2 Alleged RC2 -Crypto.Cipher.ARC4 Alleged RC4 -Crypto.Cipher.Blowfish -Crypto.Cipher.CAST -Crypto.Cipher.DES The Data Encryption Standard. Very commonly used - in the past, but today its 56-bit keys are too small. -Crypto.Cipher.DES3 Triple DES. -Crypto.Cipher.IDEA -Crypto.Cipher.RC5 -Crypto.Cipher.XOR The simple XOR cipher. -""" - -__all__ = ['AES', 'ARC2', 'ARC4', - 'Blowfish', 'CAST', 'DES', 'DES3', - 'XOR' - ] - -__revision__ = "$Id: __init__.py,v 1.7 2003/02/28 15:28:35 akuchling Exp $" - - diff --git a/Crypto/Demo/README b/Crypto/Demo/README deleted file mode 100644 index 0e48d7c3..00000000 --- a/Crypto/Demo/README +++ /dev/null @@ -1,29 +0,0 @@ -This directory contains demonstration files that use the modules -included in the Python Cryptography Toolkit. - -Note: These programs have version numbers of their own, which are not -necessarily the same as the version number of the Toolkit package. - -cipher Encrypt and decrypt sensitive files; type 'cipher -h' - for a usage message. - -voice Allows secure voice communication over a TCP/IP link. - Currently this is Linux-specific; changes to make it - run on other systems would be greatly appreciated. - -RSAgen.py Generates a new RSA key. Demonstrates using - randpool.py, and maintains a file of random data in - "randseed". Requires that the IDEA and MD5 modules - are installed. - -testkey.py RSA public/private key pair used by example programs. - -Secure importing of Python modules: - - sign.py Sign all *.pyc files in a directory, using the - key defined in testkey.py. - - secimp.py Implementation of the secure 'import' command. - - - diff --git a/Crypto/Demo/chaum.py b/Crypto/Demo/chaum.py deleted file mode 100644 index 119a1ed9..00000000 --- a/Crypto/Demo/chaum.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python - -""" Example of Chaumian blinding """ - -import time, pprint, os, sha -from allmydata.Crypto.PublicKey import * -from allmydata.Crypto.Util.randpool import RandomPool -from allmydata.Crypto.Util import number -import cPickle as pickle - -# Globals -pool = RandomPool() -pool.stir() - -# use SHA-1 by default, if you want to use SHA-256, SHA-384 or SHA-512 you -# need shax-py from http://philosophysw.com/software/ -digest = sha.sha - -KEYSIZE = 1024 -KEYFILE = "tokenkey.pickle" -HASHSIZE = sha.digestsize*8 - -### Initialization ### - -if os.path.isfile(KEYFILE): - # Load existing key """ - print "Server: load key..." - ff = file(KEYFILE, 'r') - key = pickle.load(ff) - rsa = RSA.construct(key) -else: - # Generate an RSA key-pair of KEYSIZE bits and store the key - print "Server: create key (will take a while, but only has to be done once)..." - begintime=time.time() - rsa=RSA.generate(KEYSIZE, pool.get_bytes) - endtime=time.time() - print "Server: Generate %d bit RSA key: %f s" % (KEYSIZE, endtime-begintime) - - key = (rsa.n, rsa.e, rsa.d, rsa.p, rsa.q, rsa.u) - ff = file(KEYFILE, 'w') - pickle.dump(key, ff) - -print "RSA key:" -print "n = %s" % pprint.pformat(rsa.n) # Public key -print "e = %s" % pprint.pformat(rsa.e) # Public key - -print "d = %s" % pprint.pformat(rsa.d) # Private key -# Values below are not really needed, but cause a big speedup since the Chinese Remainders Theorem can be used -print "p = %s" % pprint.pformat(rsa.p) # Private key -print "q = %s" % pprint.pformat(rsa.q) # Private key -print "u = %s" % pprint.pformat(rsa.u) # Private key -print - -### Client ### - -# Generate random tokenId of HASHSIZE bits -tokenId = number.getRandomNumber(HASHSIZE, pool.get_bytes) - -# Generate random blindingFactor of KEYSIZE-1 (so it can still be signed) bits -while 1: - blindingFactor = number.getRandomNumber(KEYSIZE-1, pool.get_bytes) - # Verify that GCD(r, n) ==1 - if number.GCD(blindingFactor, rsa.n)==1: - break - -# Calculate the hash of the tokenId -tokenHash = number.bytes_to_long(digest(number.long_to_bytes(tokenId)).digest()) - -print "tokenId = %s" % pprint.pformat(tokenId) -print "blindingFactor = %s" % pprint.pformat(blindingFactor) -print "tokenHash = %s" % pprint.pformat(tokenHash) -print - -# Blind the hashed tokenId with blindingFactor -begintime=time.time() -blindedToken=rsa.blind(tokenHash, blindingFactor) -endtime=time.time() -print "Client: Blinding: %f s" % (endtime-begintime) -print "blindedToken = %s" % pprint.pformat(blindedToken) - -# Send blindedToken to the server -print "Client -> Server: blindedToken" -print - -### Server ### - -# Sign the blindedToken -begintime=time.time() -blindedSignature=rsa.sign(blindedToken, None)[0] -endtime=time.time() -print "Server: Signing: %f s" % (endtime-begintime) -print "blindedSignature = %s" % pprint.pformat(blindedSignature) - -# Send the blindedSignature back to the client -print "Server -> Client: blindedSignature" -print - -### Client ### - -# Unblind the blindedSignature -begintime=time.time() -signature=rsa.unblind(blindedSignature, blindingFactor) -endtime=time.time() -print "Client: Unblinding: %f s" % (endtime-begintime) -print "signature = %s" % pprint.pformat(signature) -print - -# Token is ready -token = (tokenId, signature) -print "Client: token = %s" % pprint.pformat(token) - -print -print "... user can now use the token..." -print "Client -> Server: token" -print - -### Server ### - -# Verify that the signature of hash(tokenId) is right -begintime=time.time() -v=rsa.verify(number.bytes_to_long(digest(number.long_to_bytes(token[0])).digest()), (token[1],)) -endtime=time.time() -print "Server: Verifying: %f s" % (endtime-begintime) - -if v: - print "Server: SIGNATURE OK" -else: - print "Server: SIGNATURE NOT OK" - diff --git a/Crypto/Demo/cipher b/Crypto/Demo/cipher deleted file mode 100644 index 8533c87e..00000000 --- a/Crypto/Demo/cipher +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# -*-Python-*- -# Cipher 1.00 -# -# Part of the Python Cryptography Toolkit -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# - -import sys, getopt, os - -# Determine the name of this executable -executable = os.path.basename(sys.argv[0]) -if executable=='': executable='cipher' -cipher = '' # Unknown ciphering algorithm -key = (0, '') # Empty key -magic = 'ctx\001' # Magic string prefixed to the data -NoInputFile = '' # Exceptions raised on file errors -NoOutputFile = '' - -def PrintUsage(): - print 'Usage: cipher [OPTIONS] file1 file2 ...' - print '\n -c ciphername Force use of ciphername to encrypt/decrypt' - print ' -k key Key to use for encryption/decryption' - print '\nThe default cipher algorithm is IDEA; if no key is set on the command' - print 'line, you will be prompted to enter a key.' - print 'Files are read completely into memory, so do not try to encrypt' - print 'very large files.' - -def GenerateIV(length): - import whrandom - IV='' - for i in range(0, length): - IV=IV + chr(int(256*whrandom.random())) - return IV - -def Encipher(filename, cipher, key): - if (cipher==''): cipher='IDEA' - try: - exec ('from Crypto.Cipher import '+cipher) - module=eval(cipher) - except ImportError: - print executable+ ':', cipher, ': Cipher does not exist.' - sys.exit(1) - import Crypto.Hash.MD5 - try: - input=open(filename, 'r') - except IOError: - raise NoInputFile - try: - output=open(filename+'.cip', 'w') - except IOError: - raise NoOutputFile, filename+'.cip' - - if (key[0]==0): - key=raw_input('Enter encryption key for '+ filename+ ':') - else: key=key[1] - key=Crypto.Hash.MD5.new(key).digest() - IV='' - for i in range(0, module.blocksize): IV=IV+'A' - if (module.keysize==0): - cipherobj=module.new(key, module.CBC, IV) - else: - cipherobj=module.new(key[0:module.keysize], module.CBC, IV) - output.write(magic+cipher+'\0') - data = GenerateIV(module.blocksize) - filedata=input.read() - data = data + magic + str(len(filedata))+'\0'+filename+'\0' - data = data + filedata - input.close() - padding=module.blocksize - (len(data) % module.blocksize) - for i in range(0, padding): - data = data + chr(i) - ciphertext=cipherobj.encrypt(data) - output.write(ciphertext) - output.close() - -def Decipher(filename, cipher, key): - import Crypto.Hash.MD5, string - try: - input=open(filename, 'r') - except IOError: - raise NoInputFile - if (input.read(len(magic))!=magic): - print executable+':', filename+': Does not seem to be a ciphered file' - return - t='' - while (1): - c=input.read(1) - if (ord(c)==0): break - t=t+c - if (cipher==''): cipher=t - try: - from Crypto.Cipher import * - module=eval(cipher) - except ImportError: - print executable+ ':', cipher, ': Cipher does not exist.' - sys.exit(1) - if (key[0]==0): - key=raw_input('Enter encryption key for '+ filename+ ':') - else: key=key[1] - key=Crypto.Hash.MD5.new(key).digest() - IV = '' - for i in range(0, module.blocksize): IV=IV+'A' - data=input.read() - if (module.keysize==0): - cipherobj=module.new(key, module.CBC, IV) - else: - cipherobj=module.new(key[0:module.keysize], module.CBC, IV) - plain=cipherobj.decrypt(data) # Decrypt the data - plain=plain[module.blocksize:] # Discard first block of random data - if (plain[0:len(magic)]!=magic): - print executable+':', filename+': Incorrect key or cipher algorithm' - return - else: plain=plain[len(magic):] - i=string.find(plain, '\0') - length=string.atoi(plain[0:i]) - j=string.find(plain, '\0', i+1) - newfilename=plain[i+1:j] - try: - output=open(newfilename, 'w') - except IOError: - raise NoOutputFile, newfilename - output.write(plain[j+1:j+1+length]) - output.close() - -if len(sys.argv)==1: PrintUsage() ; sys.exit(0) - -options, args=getopt.getopt(sys.argv[1:], 'c:k:hH') -for opt in options: - letter, param = opt - if (letter=='-c'): cipher = param - if (letter=='-k'): key = (1, param) - if (letter=='-h' or letter=='-H'): - PrintUsage() - sys.exit(0) - -for file in args: - try: - if (file[-4:]=='.cip'): - Decipher(file, cipher, key) - else: - Encipher(file, cipher, key) - except NoInputFile: - print executable+ ':', file+ ': No such file.' - except NoOutputFile, filename: - print executable+ ':', filename+ ': Cannot open file' - diff --git a/Crypto/Demo/enc.py b/Crypto/Demo/enc.py deleted file mode 100644 index 0a7228e7..00000000 --- a/Crypto/Demo/enc.py +++ /dev/null @@ -1,334 +0,0 @@ -#!/usr/local/bin/python -Ou - -""" enc - encrypt/decrypt files using one of SSLeay's ciphers. - - Copyright (c) 1998 by Marc-Andre Lemburg; All Rights Reserved; - mailto:mal@lemburg.com; See the documentation for further - copyright information or contact the author. - - DISCLAIMER & WARNING: This tool comes with NO WARRANTY. Use at - YOUR OWN RISK. It may destroy data ! There is NO way to recover a - forgotten pass phrase ! -""" -import exceptions,os,string,time,sys -from allmydata.CryptoWorld import Ciphers,Hashes,Utils -from CommandLine import Application,SwitchOption,ArgumentOption - -# Globals -verbose = 0 - -# Maximum block size used for en/decryption -MAX_BLOCKSIZE = 1024 * 1000 - -class OperationalError(exceptions.StandardError): - pass - -def filesize(file): - - oldpos = file.tell() - file.seek(0,2) - size = file.tell() - file.seek(oldpos) - return size - -def invisible_input(prompt='>>> '): - - """ Adapted from the Python 1.5.1 docs example getpass() - """ - import termios,TERMIOS - fd = sys.stdin.fileno() - old = termios.tcgetattr(fd) - new = termios.tcgetattr(fd) - new[3] = new[3] & ~TERMIOS.ECHO # fix lflags - try: - termios.tcsetattr(fd, TERMIOS.TCSADRAIN, new) - passwd = raw_input(prompt) - finally: - termios.tcsetattr(fd, TERMIOS.TCSADRAIN, old) - print - return passwd - -def tempfile(filename='tmp', - - maxint=sys.maxint,time=time.time,int=int,hex=hex, - exists=os.path.exists): - - """ Return a new filename for a temporary file (based on filename). - """ - temp = filename + '.' + hex(maxint % int(time())) + '.tmp' - if not exists(temp): - return temp - # Ok, find an alternative name - i = 0 - while 1: - temp = '%s.%s-%i.tmp' % (filename,hex(maxint % int(time())),i) - if not exists(temp): - return temp - i = i + 1 - -# Global key -_key = '' - -def get_cipher(name,check=0): - - global _key - - cc = getattr(Ciphers,name) - keysize = cc.keysize - if not _key: - while 1: - key1 = invisible_input('Please enter the key phrase: ') - if check: - key2 = invisible_input('Please reenter the phrase: ') - if key1 != key2: - print "Phrases don't match. Please start again..." - continue - if len(key1) == 0: - print "Empty key phrase. Please start again..." - else: - break - _key = key1 - key = _key - # Fit key - if keysize > 0: - if len(key) < keysize: - key = key + \ - 'Do not change this string, it is important !'\ - [:keysize - len(key)] - elif len(key) > keysize: - key = key[:keysize] - cipher = cc(key,Ciphers.CBC) - return cipher - -def reset_key(): - - global _key - - _key = '' - -### - -def encrypt(filename,ciphername,overwrite=0): - - if verbose: - print 'Encrypting:',filename - if filename[-4:] == '.enc': - raise OperationalError,'already encrypted' - if not os.path.isfile(filename): - raise OperationalError,'not a file or not found' - - # Check overwrites - if os.path.exists(filename + '.enc'): - if not overwrite: - raise OperationalError,'would overwrite an existing file' - elif os.path.samefile(filename, filename + '.enc'): - raise OperationalError,'would overwrite the original file' - - # Open plain file - f = open(filename,'rb') - size = filesize(f) - if verbose: - print ' total size: %i bytes' % size - - # Open work file - workfilename = tempfile(filename) - out = open(workfilename,'wb') - - try: - # Init cipher and write header - cipher = get_cipher(ciphername,check=1) - out.write('enc %s %s %i\n' % \ - (repr(filename),ciphername,size)) - - # Init hash and blocksize - hash = Hashes.MD5() - blocksize = size - if blocksize > MAX_BLOCKSIZE: - blocksize = MAX_BLOCKSIZE - blocksize = ((blocksize + cipher.blocksize - 1) / cipher.blocksize) \ - * cipher.blocksize - - # Write the encrypted data in blocks - bytesread = 0 - while bytesread < size: - if verbose: - print ' reading %i bytes...' % blocksize, - block = f.read(blocksize) - if verbose: - print 'read %i bytes' % len(block) - bytesread = bytesread + len(block) - hash.update(block) - if bytesread == size: - # Final block - offset = len(block) % cipher.blocksize - if offset: - padsize = cipher.blocksize - offset - block = block + '\0'*padsize - if verbose: - print ' padding with %i bytes' % (padsize) - encblock = cipher.encrypt(block) - out.write(encblock) - - # Write hash value - hash_value = hash.digest() - if verbose: - print ' hash value:',repr(hash_value) - out.write(hash_value) - - # Copy work file to .enc file - out.close() - f.close() - os.rename(workfilename,filename+'.enc') - workfilename = None - - finally: - if workfilename: - if not out.closed: - out.close() - os.remove(workfilename) - -### - -def decrypt(filename,overwrite=0): - - if verbose: - print 'Decrypting:',filename - if filename[-4:] != '.enc': - raise OperationalError,'decrypt a plain file' - if not os.path.isfile(filename): - raise OperationalError,'not a file or not found' - - # Read header from cipher file - f = open(filename,'rb') - header = string.split(f.readline()) - if len(header) != 4: - raise OperationalError,'wrong header format:'+ str(header) - origfilename = eval(header[1]) - ciphername = header[2] - size = string.atoi(header[3]) - if verbose: - print ' total size: %i bytes' % size - - # Check overwrites - if os.path.exists(origfilename): - if not overwrite: - raise OperationalError,'would overwrite an existing file' - elif os.path.samefile(origfilename, filename): - raise OperationalError,'would overwrite the encrypted file' - - # Open work file - workfilename = tempfile(filename) - out = open(workfilename,'wb') - - try: - - # Load cipher and init hash - cipher = get_cipher(ciphername) - hash = Hashes.MD5() - - # Read the encrypted data in blocks - blocksize = size - if blocksize > MAX_BLOCKSIZE: - blocksize = MAX_BLOCKSIZE - blocksize = ((blocksize + cipher.blocksize - 1) / cipher.blocksize) \ - * cipher.blocksize - bytesread = 0 - while bytesread < size: - if size - bytesread < blocksize: - # Read remaining data only - blocksize = size - bytesread - blocksize = ((blocksize + cipher.blocksize - 1) / \ - cipher.blocksize) * cipher.blocksize - if verbose: - print ' reading %i bytes...' % blocksize, - encblock = f.read(blocksize) - if verbose: - print 'read %i bytes' % len(encblock) - bytesread = bytesread + len(encblock) - block = cipher.decrypt(encblock) - if bytesread > size: - # Depad - padsize = bytesread - size - block = block[:-padsize] - if verbose: - print ' depadded last block by %i bytes' % (padsize) - hash.update(block) - out.write(block) - - # Check hash value - hash_value = f.read(hash.digestsize) - if verbose: - print ' hash value:',repr(hash_value) - if hash_value != hash.digest(): - raise OperationalError,'data corrupt' - - # Copy workfile to origfile - out.close() - f.close() - os.rename(workfilename,origfilename) - workfilename = None - - finally: - if workfilename: - if not out.closed: - out.close() - os.remove(workfilename) - -### - -class Encrypt(Application): - - header = "File encryption utility using the SSLeay ciphers" - - about = """\ -Encrypts or decrypts the files given on the command line. If no -options are given the filenames extensions are taken as hint: '.enc' -means encrypted, everything else not encrypted. The utility then goes -and switches the state of the files. Overwriting of files only takes -place in case the '-O' switch is set. - -The following ciphers are supported: - RC2, RC4, RC5, IDEA, Blowfish, DES, DES3, CAST - -This tool comes with NO WARRANTY. Use at YOUR OWN RISK. It may destroy -data ! There is NO way to recover a forgotten pass phrase ! -""" - - options = [SwitchOption('-e', 'encrypt'), - SwitchOption('-d', 'decyrpt'), - SwitchOption('-a', 'use the same key for all files'), - SwitchOption('-O', 'allow overwrites (use with care)'), - ArgumentOption('-c', 'cipher to use', 'RC5'), - ] - - def main(self): - - overwrite = self.values['-O'] - ciphername = self.values['-c'] - samekey = self.values['-a'] - for file in self.files: - if not samekey: - reset_key() - print '-'*78 - print 'Working on file:',file - try: - if self.values['-e']: - encrypt(file,ciphername,overwrite) - elif self.values['-d']: - decrypt(file,overwrite) - elif file[-4:] != '.enc': - encrypt(file,ciphername,overwrite) - else: - decrypt(file,overwrite) - except OperationalError,why: - print '%s skipped -- %s' % (file,why) - except IOError,(code,why): - print '%s skipped -- %s' % (file,why) - except os.error,why: - print '%s skipped -- %s' % (file,why) - except KeyboardInterrupt: - print '*user break*' - break - -if __name__ == '__main__': - Encrypt() diff --git a/Crypto/Demo/secimp/README b/Crypto/Demo/secimp/README deleted file mode 100644 index 94a6e30e..00000000 --- a/Crypto/Demo/secimp/README +++ /dev/null @@ -1,24 +0,0 @@ - -This is a simple demonstration of adding an import hook that verifies -a digital signature on a Python code object before allowing it to be -imported. There are three files: - - * sign.py, which signs all the *.pyc files in the directories -listed on the command line. The contents of the .pyc file is stored -along with the signature in a file whose name ends with .pys . - - * secimp.py, which implements a secimport() function which -will use *.pys files. - - * testkey.py is the key used to sign and verify *.pys files. - -To try it out: - 1. Run "sign.py ." to compile and sign all the *.py files in -the current directory. - - 2. Run secimp.py from the command-line; it will try to -securely import testkey.pys, which should succeed. - - 3. Fire up your favorite editor, and change a single byte in a -string somewhere in testkey.pys. Run secimp.py again; it should raise -an exception when the signature can't be verified. diff --git a/Crypto/Demo/secimp/secimp.py b/Crypto/Demo/secimp/secimp.py deleted file mode 100644 index 451aa7e3..00000000 --- a/Crypto/Demo/secimp/secimp.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/local/bin/python - -import sys ; sys.path = ['../../../'] + sys.path - -import imp, os -from sys import modules - -# Secure import: -def secimport(name, globals=None, locals=None, fromlist=None): - # Fast path: let's see if it's already in sys.modules. - # Two speed optimizations are worth mentioning: - # - We use 'modules' instead of 'sys.modules'; this saves a - # dictionary look-up per call. - # - It's also faster to use a try-except statement than - # to use modules.has_key(name) to check if it's there. - try: - return modules[name] - except KeyError: - pass - - # See if it's a built-in module - m = imp.init_builtin(name) - if m: - return m - - # See if it's a frozen module - m = imp.init_frozen(name) - if m: - return m - - # Search the default path (i.e. sys.path). - # If this raises an exception, the module is not found -- - # let the caller handle the exception. - fp, pathname, (suffix, mode, type) = imp.find_module(name) - - # See what we got... - # Note that fp will be closed automatically when we return. - - # Extensions are written in C, and can just be loaded. - if type == imp.C_EXTENSION: - return imp.load_dynamic(name, pathname) - - # For a compiled or source file, we'll check if there is a *.pys file - # present in the same directory. - if type == imp.PY_COMPILED or type == imp.PY_SOURCE: - root, ext = os.path.splitext(pathname) - testfile = root + '.pys' - try: - print testfile - secfile=open(testfile, 'rb') - except IOError, tuple: - if (tuple[0]==2): pass # Ignore 'file not found' error - else: raise IOError, tuple - else: - # Check the signature (a signed hash of the code object). - # We could sign the whole code object, but that would - # require a huge key and would double the size of the - # *.pys file. - import marshal - from allmydata.Crypto.Hash import MD5 - fp.close() # Close the original *.pyc file - from testkey import * # Get the key for verification - signature=marshal.load(secfile) # Read signature - position=secfile.tell() # Save position - data=secfile.read() # Read code object - hash=MD5.new(data).digest() # Compute its hash value - ##print 'sigcheck:', key.verify(hash, signature) - if (not key.verify(hash, signature)): - raise ImportError, 'Signature check of '+ testfile + ' failed' - secfile.seek(position) # Rewind pointer to the - # beginning of the code object - fp=secfile - del secfile - # Now we can happily import the compiled code object. - return imp.load_compiled(name, pathname, fp) - - # Shouldn't get here at all. - raise ImportError, '%s: unknown module type (%d)' % (name, type) - -if __name__=='__main__': - # A sample invocation of the secure import looks like this: - print 'Attempting secure import' - r=secimport('testkey') - print 'Secure import succeeded' diff --git a/Crypto/Demo/secimp/sign.py b/Crypto/Demo/secimp/sign.py deleted file mode 100644 index afc90166..00000000 --- a/Crypto/Demo/secimp/sign.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python - -# Using the public key defined in testkey.py, sign all *.pyc files in -# the listed directories. - -from testkey import * -from allmydata.Crypto.Hash import MD5 -import os, glob, sys -import marshal, compileall - -filelist = [] -if (len(sys.argv)>1): - for dir in sys.argv[1:]: - dir=os.path.join(dir, '') - compileall.compile_dir(dir) - filelist=filelist + glob.glob(dir + '*.pyc') -else: - print "Usage: sign.py dir1 dir2 dir3 ..." - print " All *.pyc files in the listed directories will be signed," - print "leaving the signatures in *.pys files." - sys.exit(0) - -if len(filelist)==0: - print "No *.pyc files found" - sys.exit(0) - -for file in filelist: - input=open(file, 'rb') - try: - os.unlink(file[:-4]+'.pys') # Delete any existing signed file - except os.error, tuple: - if (tuple[0]==2): pass # Ignore 'file not found' error - else: raise os.error, tuple - output=open(file[:-4]+'.pys', 'wb') - data=input.read() - hash=MD5.new(data).digest() # Compute hash of the code object - K = "random bytes" - signature=key.sign(hash, K) # Sign the hash value - marshal.dump(signature, output) # Save signature to the file - output.write(data) # Copy code object to signed file - input.close() - output.close() - print os.path.basename(file)+ ' processed.' - - - diff --git a/Crypto/Demo/secimp/testkey.py b/Crypto/Demo/secimp/testkey.py deleted file mode 100644 index 456b33ff..00000000 --- a/Crypto/Demo/secimp/testkey.py +++ /dev/null @@ -1,41 +0,0 @@ - -import sys -import allmydata.Crypto.PublicKey.DSA - -key = allmydata.Crypto.PublicKey.DSA.construct(( - # y - 0x43E9162E224CBD1B66D7C27EB7E795392310B5E7AC6E0B1F60021F5E03F90E851CB7F76603FAE73907154371AE04EDBF0D9D557DF03488F34C18324B8DFEF5D2L, - # g - 0x4D6DB63479E55D0BE31CF1BEA58AB9365FC5EA267FFCD8424B56390E6EE7DD9BF788F696EED8475516353E61F37B8441137FA4F8DC82A9F84FA52BCD37517C32L, - # p - 0x8000011124427A59DC0AF8AC982B490C75B1B3E94042F50F500E0636391C6FCC8C13E628528B4B75E158618A34592D5A68CA684371F9678BBA54DD40C0020F25L, - # q - 0x9B128544B02353FF961E1774D2FA94E52E078F5DL, - # x - 0x991386B7B92C221E42B1386D61255F5C58FD79A7L, -)) - -if __name__ == '__main__': - # Running this script directly will generate a new key and print it out - from allmydata.Crypto.PublicKey import DSA - from allmydata.Crypto.Util.randpool import KeyboardRandomPool - - pool = KeyboardRandomPool(numbytes = 64) - pool.randomize() - - if len(sys.argv) == 2: - keylen = int(sys.argv[1]) - elif len(sys.argv) == 1: - keylen = 512 - else: - print >>sys.stderr, 'Usage: '+sys.argv[0]+' [keylen]' - sys.exit(1) - key = DSA.generate(keylen, pool.get_bytes, sys.stdout.write) - print "key = allmydata.Crypto.PublicKey.DSA.construct((" - for field in key.keydata: - print " #", field - print " " + hex(getattr(key, field)) + "," - print '))' - - - diff --git a/Crypto/Doc/pycrypt.tex b/Crypto/Doc/pycrypt.tex deleted file mode 100644 index d9c9bf62..00000000 --- a/Crypto/Doc/pycrypt.tex +++ /dev/null @@ -1,1188 +0,0 @@ -\documentclass{howto} - -\title{Python Cryptography Toolkit} - -\release{2.0.1} - -\author{A.M. Kuchling} -\authoraddress{\url{www.amk.ca}} - -\begin{document} -\maketitle - -\begin{abstract} -\noindent -The Python Cryptography Toolkit describes a package containing various -cryptographic modules for the Python programming language. This -documentation assumes you have some basic knowledge about the Python -language, but not necessarily about cryptography. - -\end{abstract} - -\tableofcontents - - -%====================================================================== -\section{Introduction} - -\subsection{Design Goals} -The Python cryptography toolkit is intended to provide a reliable and -stable base for writing Python programs that require cryptographic -functions. - -A central goal of the author's has been to provide a simple, -consistent interface for similar classes of algorithms. For example, -all block cipher objects have the same methods and return values, and -support the same feedback modes. Hash functions have a different -interface, but it too is consistent over all the hash functions -available. Some of these interfaces have been codified as Python -Enhancement Proposal documents, as \pep{247}, ``API for Cryptographic -Hash Functions'', and \pep{272}, ``API for Block Encryption -Algorithms''. - -This is intended to make it easy to replace old algorithms with newer, -more secure ones. If you're given a bit of portably-written Python -code that uses the DES encryption algorithm, you should be able to use -AES instead by simply changing \code{from Crypto.Cipher import DES} to -\code{from Crypto.Cipher import AES}, and changing all references to -\code{DES.new()} to \code{AES.new()}. It's also fairly simple to -write your own modules that mimic this interface, thus letting you use -combinations or permutations of algorithms. - -Some modules are implemented in C for performance; others are written -in Python for ease of modification. Generally, low-level functions -like ciphers and hash functions are written in C, while less -speed-critical functions have been written in Python. This division -may change in future releases. When speeds are quoted in this -document, they were measured on a 500 MHz Pentium II running Linux. -The exact speeds will obviously vary with different machines, -different compilers, and the phase of the moon, but they provide a -crude basis for comparison. Currently the cryptographic -implementations are acceptably fast, but not spectacularly good. I -welcome any suggestions or patches for faster code. - -I have placed the code under no restrictions; you can redistribute the -code freely or commercially, in its original form or with any -modifications you make, subject to whatever local laws may apply in your -jurisdiction. Note that you still have to come to some agreement with -the holders of any patented algorithms you're using. If you're -intensively using these modules, please tell me about it; there's little -incentive for me to work on this package if I don't know of anyone using -it. - -I also make no guarantees as to the usefulness, correctness, or legality -of these modules, nor does their inclusion constitute an endorsement of -their effectiveness. Many cryptographic algorithms are patented; -inclusion in this package does not necessarily mean you are allowed to -incorporate them in a product and sell it. Some of these algorithms may -have been cryptanalyzed, and may no longer be secure. While I will -include commentary on the relative security of the algorithms in the -sections entitled "Security Notes", there may be more recent analyses -I'm not aware of. (Or maybe I'm just clueless.) If you're implementing -an important system, don't just grab things out of a toolbox and put -them together; do some research first. On the other hand, if you're -just interested in keeping your co-workers or your relatives out of your -files, any of the components here could be used. - -This document is very much a work in progress. If you have any -questions, comments, complaints, or suggestions, please send them to me. - -\subsection{Acknowledgements} -Much of the code that actually implements the various cryptographic -algorithms was not written by me. I'd like to thank all the people who -implemented them, and released their work under terms which allowed me -to use their code. These individuals are credited in the relevant -chapters of this documentation. Bruce Schneier's book \emph{Applied -Cryptography} was also very useful in writing this toolkit; I highly -recommend it if you're interested in learning more about cryptography. - -Good luck with your cryptography hacking! - -A.M.K. - -\email{comments@amk.ca} - -Washington DC, USA - -June 2005 - - -%====================================================================== -\section{Crypto.Hash: Hash Functions} - -Hash functions take arbitrary strings as input, and produce an output -of fixed size that is dependent on the input; it should never be -possible to derive the input data given only the hash function's -output. One simple hash function consists of simply adding together -all the bytes of the input, and taking the result modulo 256. For a -hash function to be cryptographically secure, it must be very -difficult to find two messages with the same hash value, or to find a -message with a given hash value. The simple additive hash function -fails this criterion miserably and the hash functions described below -meet this criterion (as far as we know). Examples of -cryptographically secure hash functions include MD2, MD5, and SHA1. - -Hash functions can be used simply as a checksum, or, in association with a -public-key algorithm, can be used to implement digital signatures. - -The hashing algorithms currently implemented are: - -\begin{tableii}{c|l}{}{Hash function}{Digest length} -\lineii{MD2}{128 bits} -\lineii{MD4}{128 bits} -\lineii{MD5}{128 bits} -\lineii{RIPEMD}{160 bits} -\lineii{SHA1}{160 bits} -\lineii{SHA256}{256 bits} -\end{tableii} - -All hashing modules share the same interface. After importing a given -hashing module, call the \function{new()} function to create a new -hashing object. You can now feed arbitrary strings into the object -with the \method{update()} method, and can ask for the hash value at -any time by calling the \method{digest()} or \method{hexdigest()} -methods. The \function{new()} function can also be passed an optional -string parameter that will be immediately hashed into the object's -state. - -Hash function modules define one variable: - -\begin{datadesc}{digest_size} -An integer value; the size of the digest -produced by the hashing objects. You could also obtain this value by -creating a sample object, and taking the length of the digest string -it returns, but using \member{digest_size} is faster. -\end{datadesc} - -The methods for hashing objects are always the following: - -\begin{methoddesc}{copy}{} -Return a separate copy of this hashing object. An \code{update} to -this copy won't affect the original object. -\end{methoddesc} - -\begin{methoddesc}{digest}{} -Return the hash value of this hashing object, as a string containing -8-bit data. The object is not altered in any way by this function; -you can continue updating the object after calling this function. -\end{methoddesc} - -\begin{methoddesc}{hexdigest}{} -Return the hash value of this hashing object, as a string containing -the digest data as hexadecimal digits. The resulting string will be -twice as long as that returned by \method{digest()}. The object is not -altered in any way by this function; you can continue updating the -object after calling this function. -\end{methoddesc} - -\begin{methoddesc}{update}{arg} -Update this hashing object with the string \var{arg}. -\end{methoddesc} - -Here's an example, using the MD5 algorithm: - -\begin{verbatim} ->>> from Crypto.Hash import MD5 ->>> m = MD5.new() ->>> m.update('abc') ->>> m.digest() -'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr' ->>> m.hexdigest() -'900150983cd24fb0d6963f7d28e17f72' -\end{verbatim} - - -\subsection{Security Notes} - -Hashing algorithms are broken by developing an algorithm to compute a -string that produces a given hash value, or to find two messages that -produce the same hash value. Consider an example where Alice and Bob -are using digital signatures to sign a contract. Alice computes the -hash value of the text of the contract and signs the hash value with -her private key. Bob could then compute a different contract that has -the same hash value, and it would appear that Alice signed that bogus -contract; she'd have no way to prove otherwise. Finding such a -message by brute force takes \code{pow(2, b-1)} operations, where the -hash function produces \emph{b}-bit hashes. - -If Bob can only find two messages with the same hash value but can't -choose the resulting hash value, he can look for two messages with -different meanings, such as "I will mow Bob's lawn for $10" and "I owe -Bob $1,000,000", and ask Alice to sign the first, innocuous contract. -This attack is easier for Bob, since finding two such messages by brute -force will take \code{pow(2, b/2)} operations on average. However, -Alice can protect herself by changing the protocol; she can simply -append a random string to the contract before hashing and signing it; -the random string can then be kept with the signature. - -None of the algorithms implemented here have been completely broken. -There are no attacks on MD2, but it's rather slow at 1250 K/sec. MD4 -is faster at 44,500 K/sec but there have been some partial attacks on -it. MD4 makes three iterations of a basic mixing operation; two of -the three rounds have been cryptanalyzed, but the attack can't be -extended to the full algorithm. MD5 is a strengthened version of MD4 -with four rounds; an attack against one round has been found XXX -update this. MD5 is still believed secure at the moment, but people -are gravitating toward using SHA1 in new software because there are no -known attacks against SHA1. The MD5 implementation is moderately -well-optimized and thus faster on x86 processors, running at 35,500 -K/sec. MD5 may even be faster than MD4, depending on the processor -and compiler you use. - -All the MD\var{n} algorithms produce 128-bit hashes; SHA1 produces a -larger 160-bit hash, and there are no known attacks against it. The -first version of SHA had a weakness which was later corrected; the -code used here implements the second, corrected, version. It operates -at 21,000 K/sec. SHA256 is about as half as fast as SHA1. RIPEMD has -a 160-bit output, the same output size as SHA1, and operates at 17,600 -K/sec. - -\subsection{Credits} -The MD2 and MD4 implementations were written by A.M. Kuchling, and the -MD5 code was implemented by Colin Plumb. The SHA1 code was originally -written by Peter Gutmann. The RIPEMD code was written by Antoon -Bosselaers, and adapted for the toolkit by Hirendra Hindocha. The -SHA256 code was written by Tom St.~Denis and is part of the -LibTomCrypt library (\url{http://www.libtomcrypt.org/}); it was -adapted for the toolkit by Jeethu Rao and Taylor Boon. - - -%====================================================================== -\section{Crypto.Cipher: Encryption Algorithms} - -Encryption algorithms transform their input data, or \dfn{plaintext}, -in some way that is dependent on a variable \dfn{key}, producing -\dfn{ciphertext}. This transformation can easily be reversed, if (and, -hopefully, only if) one knows the key. The key can be varied by the -user or application and chosen from some very large space of possible -keys. - -For a secure encryption algorithm, it should be very difficult to -determine the original plaintext without knowing the key; usually, no -clever attacks on the algorithm are known, so the only way of breaking -the algorithm is to try all possible keys. Since the number of possible -keys is usually of the order of 2 to the power of 56 or 128, this is not -a serious threat, although 2 to the power of 56 is now considered -insecure in the face of custom-built parallel computers and distributed -key guessing efforts. - -\dfn{Block ciphers} take multibyte inputs of a fixed size -(frequently 8 or 16 bytes long) and encrypt them. Block ciphers can -be operated in various modes. The simplest is Electronic Code Book -(or ECB) mode. In this mode, each block of plaintext is simply -encrypted to produce the ciphertext. This mode can be dangerous, -because many files will contain patterns greater than the block size; -for example, the comments in a C program may contain long strings of -asterisks intended to form a box. All these identical blocks will -encrypt to identical ciphertext; an adversary may be able to use this -structure to obtain some information about the text. - -To eliminate this weakness, there are various feedback modes in which -the plaintext is combined with the previous ciphertext before -encrypting; this eliminates any repetitive structure in the -ciphertext. - -One mode is Cipher Block Chaining (CBC mode); another is Cipher -FeedBack (CFB mode). CBC mode still encrypts in blocks, and thus is -only slightly slower than ECB mode. CFB mode encrypts on a -byte-by-byte basis, and is much slower than either of the other two -modes. The chaining feedback modes require an initialization value to -start off the encryption; this is a string of the same length as the -ciphering algorithm's block size, and is passed to the \code{new()} -function. There is also a special PGP mode, which is an oddball -variant of CFB used by the PGP program. While you can use it in -non-PGP programs, it's quite non-standard. - -The currently available block ciphers are listed in the following table, -and are in the \code{Crypto.Cipher} package: - -\begin{tableii}{c|l}{}{Cipher}{Key Size/Block Size} -\lineii{AES}{16, 24, or 32 bytes/16 bytes} -\lineii{ARC2}{Variable/8 bytes} -\lineii{Blowfish}{Variable/8 bytes} -\lineii{CAST}{Variable/8 bytes} -\lineii{DES}{8 bytes/8 bytes} -\lineii{DES3 (Triple DES)}{16 bytes/8 bytes} -\lineii{IDEA}{16 bytes/8 bytes} -\lineii{RC5}{Variable/8 bytes} -\end{tableii} - -In a strict formal sense, \dfn{stream ciphers} encrypt data bit-by-bit; -practically, stream ciphers work on a character-by-character basis. -Stream ciphers use exactly the -same interface as block ciphers, with a block length that will always -be 1; this is how block and stream ciphers can be distinguished. -The only feedback mode available for stream ciphers is ECB mode. - -The currently available stream ciphers are listed in the following table: - -\begin{tableii}{c|l}{}{Cipher}{Key Size} -\lineii{Cipher}{Key Size} - \lineii{ARC4}{Variable} - \lineii{XOR}{Variable} -\end{tableii} - -ARC4 is short for `Alleged RC4'. In September of 1994, someone posted -C code to both the Cypherpunks mailing list and to the Usenet -newsgroup \code{sci.crypt}, claiming that it implemented the RC4 -algorithm. This claim turned out to be correct. Note that there's a -damaging class of weak RC4 keys; this module won't warn you about such keys. -% XXX other analyses of RC4? - -A similar anonymous posting was made for Alleged RC2 in January, 1996. - -An example usage of the DES module: -\begin{verbatim} ->>> from Crypto.Cipher import DES ->>> obj=DES.new('abcdefgh', DES.MODE_ECB) ->>> plain="Guido van Rossum is a space alien." ->>> len(plain) -34 ->>> obj.encrypt(plain) -Traceback (innermost last): - File "", line 1, in ? -ValueError: Strings for DES must be a multiple of 8 in length ->>> ciph=obj.encrypt(plain+'XXXXXX') ->>> ciph -'\021,\343Nq\214DY\337T\342pA\372\255\311s\210\363,\300j\330\250\312\347\342I\3215w\03561\303dgb/\006' ->>> obj.decrypt(ciph) -'Guido van Rossum is a space alien.XXXXXX' -\end{verbatim} - -All cipher algorithms share a common interface. After importing a -given module, there is exactly one function and two variables -available. - -\begin{funcdesc}{new}{key, mode\optional{, IV}} -Returns a ciphering object, using \var{key} and feedback mode -\var{mode}. If \var{mode} is \constant{MODE_CBC} or \constant{MODE_CFB}, \var{IV} must be provided, -and must be a string of the same length as the block size. Some -algorithms support additional keyword arguments to this function; see -the "Algorithm-specific Notes for Encryption Algorithms" section below for the details. -\end{funcdesc} - -\begin{datadesc}{block_size} -An integer value; the size of the blocks encrypted by this module. -Strings passed to the \code{encrypt} and \code{decrypt} functions -must be a multiple of this length. For stream ciphers, -\code{block_size} will be 1. -\end{datadesc} - -\begin{datadesc}{key_size} -An integer value; the size of the keys required by this module. If -\code{key_size} is zero, then the algorithm accepts arbitrary-length -keys. You cannot pass a key of length 0 (that is, the null string -\code{''} as such a variable-length key. -\end{datadesc} - -All cipher objects have at least three attributes: - -\begin{memberdesc}{block_size} -An integer value equal to the size of the blocks encrypted by this object. -Identical to the module variable of the same name. -\end{memberdesc} - -\begin{memberdesc}{IV} -Contains the initial value which will be used to start a cipher -feedback mode. After encrypting or decrypting a string, this value -will reflect the modified feedback text; it will always be one block -in length. It is read-only, and cannot be assigned a new value. -\end{memberdesc} - -\begin{memberdesc}{key_size} -An integer value equal to the size of the keys used by this object. If -\code{key_size} is zero, then the algorithm accepts arbitrary-length -keys. For algorithms that support variable length keys, this will be 0. -Identical to the module variable of the same name. -\end{memberdesc} - -All ciphering objects have the following methods: - -\begin{methoddesc}{decrypt}{string} -Decrypts \var{string}, using the key-dependent data in the object, and -with the appropriate feedback mode. The string's length must be an exact -multiple of the algorithm's block size. Returns a string containing -the plaintext. -\end{methoddesc} - -\begin{methoddesc}{encrypt}{string} -Encrypts a non-null \var{string}, using the key-dependent data in the -object, and with the appropriate feedback mode. The string's length -must be an exact multiple of the algorithm's block size; for stream -ciphers, the string can be of any length. Returns a string containing -the ciphertext. -\end{methoddesc} - - -\subsection{Algorithm-specific Notes for Encryption Algorithms} - -RC5 has a bunch of parameters; see Ronald Rivest's paper at -\url{http://theory.lcs.mit.edu/~rivest/rc5rev.ps} for the -implementation details. The keyword parameters are: - -\begin{itemize} -\item \code{version}: -The version -of the RC5 algorithm to use; currently the only legal value is -\code{0x10} for RC5 1.0. -\item \code{wordsize}: -The word size to use; -16 or 32 are the only legal values. (A larger word size is better, so -usually 32 will be used. 16-bit RC5 is probably only of academic -interest.) -\item \code{rounds}: -The number of rounds to apply, the larger the more secure: this -can be any value from 0 to 255, so you will have to choose a value -balanced between speed and security. -\end{itemize} - - -\subsection{Security Notes} -Encryption algorithms can be broken in several ways. If you have some -ciphertext and know (or can guess) the corresponding plaintext, you can -simply try every possible key in a \dfn{known-plaintext} attack. Or, it -might be possible to encrypt text of your choice using an unknown key; -for example, you might mail someone a message intending it to be -encrypted and forwarded to someone else. This is a -\dfn{chosen-plaintext} attack, which is particularly effective if it's -possible to choose plaintexts that reveal something about the key when -encrypted. - -DES (5100 K/sec) has a 56-bit key; this is starting to become too small -for safety. It has been estimated that it would only cost \$1,000,000 to -build a custom DES-cracking machine that could find a key in 3 hours. A -chosen-ciphertext attack using the technique of \dfn{linear -cryptanalysis} can break DES in \code{pow(2, 43)} steps. However, -unless you're encrypting data that you want to be safe from major -governments, DES will be fine. DES3 (1830 K/sec) uses three DES -encryptions for greater security and a 112-bit or 168-bit key, but is -correspondingly slower. - -There are no publicly known attacks against IDEA (3050 K/sec), and -it's been around long enough to have been examined. There are no -known attacks against ARC2 (2160 K/sec), ARC4 (8830 K/sec), Blowfish -(9250 K/sec), CAST (2960 K/sec), or RC5 (2060 K/sec), but they're all -relatively new algorithms and there hasn't been time for much analysis -to be performed; use them for serious applications only after careful -research. - -AES, the Advanced Encryption Standard, was chosen by the US National -Institute of Standards and Technology from among 6 competitors, and is -probably your best choice. It runs at 7060 K/sec, so it's among the -faster algorithms around. - - -\subsection{Credits} -The code for Blowfish was written by Bryan Olson, partially based on a -previous implementation by Bruce Schneier, who also invented the -algorithm; the Blowfish algorithm has been placed in the public domain -and can be used freely. (See \url{http://www.counterpane.com} for more -information about Blowfish.) The CAST implementation was written by -Wim Lewis. The DES implementation was written by Eric Young, and the -IDEA implementation by Colin Plumb. The RC5 implementation -was written by A.M. Kuchling. - -The Alleged RC4 code was posted to the \code{sci.crypt} newsgroup by an -unknown party, and re-implemented by A.M. Kuchling. - - -%====================================================================== -\section{Crypto.Protocol: Various Protocols} - -\subsection{Crypto.Protocol.AllOrNothing} - -This module implements all-or-nothing package transformations. -An all-or-nothing package transformation is one in which some text is -transformed into message blocks, such that all blocks must be obtained before -the reverse transformation can be applied. Thus, if any blocks are corrupted -or lost, the original message cannot be reproduced. - -An all-or-nothing package transformation is not encryption, although a block -cipher algorithm is used. The encryption key is randomly generated and is -extractable from the message blocks. - -\begin{classdesc}{AllOrNothing}{ciphermodule, mode=None, IV=None} -Class implementing the All-or-Nothing package transform. - -\var{ciphermodule} is a module implementing the cipher algorithm to -use. Optional arguments \var{mode} and \var{IV} are passed directly -through to the \var{ciphermodule}.\code{new()} method; they are the -feedback mode and initialization vector to use. All three arguments -must be the same for the object used to create the digest, and to -undigest'ify the message blocks. - -The module passed as \var{ciphermodule} must provide the \pep{272} -interface. An encryption key is randomly generated automatically when -needed. -\end{classdesc} - -The methods of the \class{AllOrNothing} class are: - -\begin{methoddesc}{digest}{text} -Perform the All-or-Nothing package transform on the -string \var{text}. Output is a list of message blocks describing the -transformed text, where each block is a string of bit length equal -to the cipher module's block_size. -\end{methoddesc} - -\begin{methoddesc}{undigest}{mblocks} -Perform the reverse package transformation on a list of message -blocks. Note that the cipher module used for both transformations -must be the same. \var{mblocks} is a list of strings of bit length -equal to \var{ciphermodule}'s block_size. The output is a string object. -\end{methoddesc} - - -\subsection{Crypto.Protocol.Chaffing} - -Winnowing and chaffing is a technique for enhancing privacy without requiring -strong encryption. In short, the technique takes a set of authenticated -message blocks (the wheat) and adds a number of chaff blocks which have -randomly chosen data and MAC fields. This means that to an adversary, the -chaff blocks look as valid as the wheat blocks, and so the authentication -would have to be performed on every block. By tailoring the number of chaff -blocks added to the message, the sender can make breaking the message -computationally infeasible. There are many other interesting properties of -the winnow/chaff technique. - -For example, say Alice is sending a message to Bob. She packetizes the -message and performs an all-or-nothing transformation on the packets. Then -she authenticates each packet with a message authentication code (MAC). The -MAC is a hash of the data packet, and there is a secret key which she must -share with Bob (key distribution is an exercise left to the reader). She then -adds a serial number to each packet, and sends the packets to Bob. - -Bob receives the packets, and using the shared secret authentication key, -authenticates the MACs for each packet. Those packets that have bad MACs are -simply discarded. The remainder are sorted by serial number, and passed -through the reverse all-or-nothing transform. The transform means that an -eavesdropper (say Eve) must acquire all the packets before any of the data can -be read. If even one packet is missing, the data is useless. - -There's one twist: by adding chaff packets, Alice and Bob can make Eve's job -much harder, since Eve now has to break the shared secret key, or try every -combination of wheat and chaff packet to read any of the message. The cool -thing is that Bob doesn't need to add any additional code; the chaff packets -are already filtered out because their MACs don't match (in all likelihood -- -since the data and MACs for the chaff packets are randomly chosen it is -possible, but very unlikely that a chaff MAC will match the chaff data). And -Alice need not even be the party adding the chaff! She could be completely -unaware that a third party, say Charles, is adding chaff packets to her -messages as they are transmitted. - -\begin{classdesc}{Chaff}{factor=1.0, blocksper=1} -Class implementing the chaff adding algorithm. -\var{factor} is the number of message blocks - to add chaff to, expressed as a percentage between 0.0 and 1.0; the default value is 1.0. -\var{blocksper} is the number of chaff blocks to include for each block - being chaffed, and defaults to 1. The default settings -add one chaff block to every - message block. By changing the defaults, you can adjust how - computationally difficult it could be for an adversary to - brute-force crack the message. The difficulty is expressed as: - -\begin{verbatim} -pow(blocksper, int(factor * number-of-blocks)) -\end{verbatim} - -For ease of implementation, when \var{factor} < 1.0, only the first -\code{int(\var{factor}*number-of-blocks)} message blocks are chaffed. -\end{classdesc} - -\class{Chaff} instances have the following methods: - -\begin{methoddesc}{chaff}{blocks} -Add chaff to message blocks. \var{blocks} is a list of 3-tuples of the -form (\var{serial-number}, \var{data}, \var{MAC}). - -Chaff is created by choosing a random number of the same -byte-length as \var{data}, and another random number of the same -byte-length as \var{MAC}. The message block's serial number is placed -on the chaff block and all the packet's chaff blocks are randomly -interspersed with the single wheat block. This method then -returns a list of 3-tuples of the same form. Chaffed blocks will -contain multiple instances of 3-tuples with the same serial -number, but the only way to figure out which blocks are wheat and -which are chaff is to perform the MAC hash and compare values. -\end{methoddesc} - - -%====================================================================== -\section{Crypto.PublicKey: Public-Key Algorithms} -So far, the encryption algorithms described have all been \dfn{private -key} ciphers. The same key is used for both encryption and decryption -so all correspondents must know it. This poses a problem: you may -want encryption to communicate sensitive data over an insecure -channel, but how can you tell your correspondent what the key is? You -can't just e-mail it to her because the channel is insecure. One -solution is to arrange the key via some other way: over the phone or -by meeting in person. - -Another solution is to use \dfn{public-key} cryptography. In a public -key system, there are two different keys: one for encryption and one for -decryption. The encryption key can be made public by listing it in a -directory or mailing it to your correspondent, while you keep the -decryption key secret. Your correspondent then sends you data encrypted -with your public key, and you use the private key to decrypt it. While -the two keys are related, it's very difficult to derive the private key -given only the public key; however, deriving the private key is always -possible given enough time and computing power. This makes it very -important to pick keys of the right size: large enough to be secure, but -small enough to be applied fairly quickly. - -Many public-key algorithms can also be used to sign messages; simply -run the message to be signed through a decryption with your private -key key. Anyone receiving the message can encrypt it with your -publicly available key and read the message. Some algorithms do only -one thing, others can both encrypt and authenticate. - -The currently available public-key algorithms are listed in the -following table: - -\begin{tableii}{c|l}{}{Algorithm}{Capabilities} -\lineii{RSA}{Encryption, authentication/signatures} -\lineii{ElGamal}{Encryption, authentication/signatures} -\lineii{DSA}{Authentication/signatures} -\lineii{qNEW}{Authentication/signatures} -\end{tableii} - -Many of these algorithms are patented. Before using any of them in a -commercial product, consult a patent attorney; you may have to arrange -a license with the patent holder. - -An example of using the RSA module to sign a message: -\begin{verbatim} ->>> from Crypto.Hash import MD5 ->>> from Crypto.PublicKey import RSA ->>> RSAkey = RSA.generate(384, randfunc) # This will take a while... ->>> hash = MD5.new(plaintext).digest() ->>> signature = RSAkey.sign(hash, "") ->>> signature # Print what an RSA sig looks like--you don't really care. -('\021\317\313\336\264\315' ...,) ->>> RSAkey.verify(hash, signature) # This sig will check out -1 ->>> RSAkey.verify(hash[:-1], signature)# This sig will fail -0 -\end{verbatim} - -Public-key modules make the following functions available: - -\begin{funcdesc}{construct}{tuple} -Constructs a key object from a tuple of data. This is -algorithm-specific; look at the source code for the details. (To be -documented later.) -\end{funcdesc} - -\begin{funcdesc}{generate}{size, randfunc, progress_func=\code{None}} -Generate a fresh public/private key pair. \var{size} is a -algorithm-dependent size parameter, usually measured in bits; the -larger it is, the more difficult it will be to break the key. Safe -key sizes vary from algorithm to algorithm; you'll have to research -the question and decide on a suitable key size for your application. -An N-bit keys can encrypt messages up to N-1 bits long. - -\var{randfunc} is a random number generation function; it should -accept a single integer \var{N} and return a string of random data -\var{N} bytes long. You should always use a cryptographically secure -random number generator, such as the one defined in the -\module{Crypto.Util.randpool} module; \emph{don't} just use the -current time and the \module{random} module. - -\var{progress_func} is an optional function that will be called with a short -string containing the key parameter currently being generated; it's -useful for interactive applications where a user is waiting for a key -to be generated. -\end{funcdesc} - -If you want to interface with some other program, you will have to know -the details of the algorithm being used; this isn't a big loss. If you -don't care about working with non-Python software, simply use the -\module{pickle} module when you need to write a key or a signature to a -file. It's portable across all the architectures that Python supports, -and it's simple to use. - -Public-key objects always support the following methods. Some of them -may raise exceptions if their functionality is not supported by the -algorithm. - -\begin{methoddesc}{can_blind}{} -Returns true if the algorithm is capable of blinding data; -returns false otherwise. -\end{methoddesc} - -\begin{methoddesc}{can_encrypt}{} -Returns true if the algorithm is capable of encrypting and decrypting -data; returns false otherwise. To test if a given key object can encrypt -data, use \code{key.can_encrypt() and key.has_private()}. -\end{methoddesc} - -\begin{methoddesc}{can_sign}{} -Returns true if the algorithm is capable of signing data; returns false -otherwise. To test if a given key object can sign data, use -\code{key.can_sign() and key.has_private()}. -\end{methoddesc} - -\begin{methoddesc}{decrypt}{tuple} -Decrypts \var{tuple} with the private key, returning another string. -This requires the private key to be present, and will raise an exception -if it isn't present. It will also raise an exception if \var{string} is -too long. -\end{methoddesc} - -\begin{methoddesc}{encrypt}{string, K} -Encrypts \var{string} with the private key, returning a tuple of -strings; the length of the tuple varies from algorithm to algorithm. -\var{K} should be a string of random data that is as long as -possible. Encryption does not require the private key to be present -inside the key object. It will raise an exception if \var{string} is -too long. For ElGamal objects, the value of \var{K} expressed as a -big-endian integer must be relatively prime to \code{self.p-1}; an -exception is raised if it is not. -\end{methoddesc} - -\begin{methoddesc}{has_private}{} -Returns true if the key object contains the private key data, which -will allow decrypting data and generating signatures. -Otherwise this returns false. -\end{methoddesc} - -\begin{methoddesc}{publickey}{} -Returns a new public key object that doesn't contain the private key -data. -\end{methoddesc} - -\begin{methoddesc}{sign}{string, K} -Sign \var{string}, returning a signature, which is just a tuple; in -theory the signature may be made up of any Python objects at all; in -practice they'll be either strings or numbers. \var{K} should be a -string of random data that is as long as possible. Different algorithms -will return tuples of different sizes. \code{sign()} raises an -exception if \var{string} is too long. For ElGamal objects, the value -of \var{K} expressed as a big-endian integer must be relatively prime to -\code{self.p-1}; an exception is raised if it is not. -\end{methoddesc} - -\begin{methoddesc}{size}{} -Returns the maximum size of a string that can be encrypted or signed, -measured in bits. String data is treated in big-endian format; the most -significant byte comes first. (This seems to be a \emph{de facto} standard -for cryptographical software.) If the size is not a multiple of 8, then -some of the high order bits of the first byte must be zero. Usually -it's simplest to just divide the size by 8 and round down. -\end{methoddesc} - -\begin{methoddesc}{verify}{string, signature} -Returns true if the signature is valid, and false otherwise. -\var{string} is not processed in any way; \code{verify} does -not run a hash function over the data, but you can easily do that yourself. -\end{methoddesc} - -\subsection{The ElGamal and DSA algorithms} -For RSA, the \var{K} parameters are unused; if you like, you can just -pass empty strings. The ElGamal and DSA algorithms require a real -\var{K} value for technical reasons; see Schneier's book for a detailed -explanation of the respective algorithms. This presents a possible -hazard that can -inadvertently reveal the private key. Without going into the -mathematical details, the danger is as follows. \var{K} is never derived -or needed by others; theoretically, it can be thrown away once the -encryption or signing operation is performed. However, revealing -\var{K} for a given message would enable others to derive the secret key -data; worse, reusing the same value of \var{K} for two different -messages would also enable someone to derive the secret key data. An -adversary could intercept and store every message, and then try deriving -the secret key from each pair of messages. - -This places implementors on the horns of a dilemma. On the one hand, -you want to store the \var{K} values to avoid reusing one; on the other -hand, storing them means they could fall into the hands of an adversary. -One can randomly generate \var{K} values of a suitable length such as -128 or 144 bits, and then trust that the random number generator -probably won't produce a duplicate anytime soon. This is an -implementation decision that depends on the desired level of security -and the expected usage lifetime of a private key. I can't choose and -enforce one policy for this, so I've added the \var{K} parameter to the -\method{encrypt} and \method{sign} methods. You must choose \var{K} by -generating a string of random data; for ElGamal, when interpreted as a -big-endian number (with the most significant byte being the first byte -of the string), \var{K} must be relatively prime to \code{self.p-1}; any -size will do, but brute force searches would probably start with small -primes, so it's probably good to choose fairly large numbers. It might be -simplest to generate a prime number of a suitable length using the -\module{Crypto.Util.number} module. - - -\subsection{Security Notes for Public-key Algorithms} -Any of these algorithms can be trivially broken; for example, RSA can be -broken by factoring the modulus \emph{n} into its two prime factors. -This is easily done by the following code: - -\begin{verbatim} -for i in range(2, n): - if (n%i)==0: - print i, 'is a factor' - break -\end{verbatim} - -However, \emph{n} is usually a few hundred bits long, so this simple -program wouldn't find a solution before the universe comes to an end. -Smarter algorithms can factor numbers more quickly, but it's still -possible to choose keys so large that they can't be broken in a -reasonable amount of time. For ElGamal and DSA, discrete logarithms are -used instead of factoring, but the principle is the same. - -Safe key sizes depend on the current state of number theory and -computer technology. At the moment, one can roughly define three -levels of security: low-security commercial, high-security commercial, -and military-grade. For RSA, these three levels correspond roughly to -768, 1024, and 2048-bit keys. - - -%====================================================================== -\section{Crypto.Util: Odds and Ends} -This chapter contains all the modules that don't fit into any of the -other chapters. - -\subsection{Crypto.Util.number} - -This module contains various number-theoretic functions. - -\begin{funcdesc}{GCD}{x,y} -Return the greatest common divisor of \var{x} and \var{y}. -\end{funcdesc} - -\begin{funcdesc}{getPrime}{N, randfunc} -Return an \var{N}-bit random prime number, using random data obtained -from the function \var{randfunc}. \var{randfunc} must take a single -integer argument, and return a string of random data of the -corresponding length; the \method{get_bytes()} method of a -\class{RandomPool} object will serve the purpose nicely, as will the -\method{read()} method of an opened file such as \file{/dev/random}. -\end{funcdesc} - -\begin{funcdesc}{getRandomNumber}{N, randfunc} -Return an \var{N}-bit random number, using random data obtained from the -function \var{randfunc}. As usual, \var{randfunc} must take a single -integer argument and return a string of random data of the -corresponding length. -\end{funcdesc} - -\begin{funcdesc}{inverse}{u, v} -Return the inverse of \var{u} modulo \var{v}. -\end{funcdesc} - -\begin{funcdesc}{isPrime}{N} -Returns true if the number \var{N} is prime, as determined by a -Rabin-Miller test. -\end{funcdesc} - - -\subsection{Crypto.Util.randpool} - -For cryptographic purposes, ordinary random number generators are -frequently insufficient, because if some of their output is known, it -is frequently possible to derive the generator's future (or past) -output. Given the generator's state at some point in time, someone -could try to derive any keys generated using it. The solution is to -use strong encryption or hashing algorithms to generate successive -data; this makes breaking the generator as difficult as breaking the -algorithms used. - -Understanding the concept of \dfn{entropy} is important for using the -random number generator properly. In the sense we'll be using it, -entropy measures the amount of randomness; the usual unit is in bits. -So, a single random bit has an entropy of 1 bit; a random byte has an -entropy of 8 bits. Now consider a one-byte field in a database containing a -person's sex, represented as a single character \samp{M} or \samp{F}. -What's the entropy of this field? Since there are only two possible -values, it's not 8 bits, but one; if you were trying to guess the value, -you wouldn't have to bother trying \samp{Q} or \samp{@}. - -Now imagine running that single byte field through a hash function that -produces 128 bits of output. Is the entropy of the resulting hash value -128 bits? No, it's still just 1 bit. The entropy is a measure of how many -possible states of the data exist. For English -text, the entropy of a five-character string is not 40 bits; it's -somewhat less, because not all combinations would be seen. \samp{Guido} -is a possible string, as is \samp{In th}; \samp{zJwvb} is not. - -The relevance to random number generation? We want enough bits of -entropy to avoid making an attack on our generator possible. An -example: One computer system had a mechanism which generated nonsense -passwords for its users. This is a good idea, since it would prevent -people from choosing their own name or some other easily guessed string. -Unfortunately, the random number generator used only had 65536 states, -which meant only 65536 different passwords would ever be generated, and -it was easy to compute all the possible passwords and try them. The -entropy of the random passwords was far too low. By the same token, if -you generate an RSA key with only 32 bits of entropy available, there -are only about 4.2 billion keys you could have generated, and an -adversary could compute them all to find your private key. See \rfc{1750}, -"Randomness Recommendations for Security", for an interesting discussion -of the issues related to random number generation. - -The \module{randpool} module implements a strong random number generator -in the \class{RandomPool} class. The internal state consists of a string -of random data, which is returned as callers request it. The class -keeps track of the number of bits of entropy left, and provides a function to -add new random data; this data can be obtained in various ways, such as -by using the variance in a user's keystroke timings. - -\begin{classdesc}{RandomPool}{\optional{numbytes, cipher, hash} } -An object of the \code{RandomPool} class can be created without -parameters if desired. \var{numbytes} sets the number of bytes of -random data in the pool, and defaults to 160 (1280 bits). \var{hash} -can be a string containing the module name of the hash function to use -in stirring the random data, or a module object supporting the hashing -interface. The default action is to use SHA. - -The \var{cipher} argument is vestigial; it was removed from version -1.1 so RandomPool would work even in the limited exportable subset of -the code. I recommend passing \var{hash} using a keyword argument so -that someday I can safely delete the \var{cipher} argument - -\end{classdesc} - -\class{RandomPool} objects define the following variables and methods: - -\begin{methoddesc}{add_event}{time\optional{, string}} -Adds an event to the random pool. \var{time} should be set to the -current system time, measured at the highest resolution available. -\var{string} can be a string of data that will be XORed into the pool, -and can be used to increase the entropy of the pool. For example, if -you're encrypting a document, you might use the hash value of the -document; an adversary presumably won't have the plaintext of the -document, and thus won't be able to use this information to break the -generator. -\end{methoddesc} - -The return value is the value of \member{self.entropy} after the data has -been added. The function works in the following manner: the time -between successive calls to the \method{add_event()} method is determined, -and the entropy of the data is guessed; the larger the time between -calls, the better. The system time is then read and added to the pool, -along with the \var{string} parameter, if present. The hope is that the -low-order bits of the time are effectively random. In an application, -it is recommended that \method{add_event()} be called as frequently as -possible, with whatever random data can be found. - -\begin{memberdesc}{bits} -A constant integer value containing the number of bits of data in -the pool, equal to the \member{bytes} attribute multiplied by 8. -\end{memberdesc} - -\begin{memberdesc}{bytes} -A constant integer value containing the number of bytes of data in -the pool. -\end{memberdesc} - -\begin{memberdesc}{entropy} -An integer value containing the number of bits of entropy currently in -the pool. The value is incremented by the \method{add_event()} method, -and decreased by the \method{get_bytes()} method. -\end{memberdesc} - -\begin{methoddesc}{get_bytes}{num} -Returns a string containing \var{num} bytes of random data, and -decrements the amount of entropy available. It is not an error to -reduce the entropy to zero, or to call this function when the entropy -is zero. This simply means that, in theory, enough random information has been -extracted to derive the state of the generator. It is the caller's -responsibility to monitor the amount of entropy remaining and decide -whether it is sufficent for secure operation. -\end{methoddesc} - -\begin{methoddesc}{stir}{} -Scrambles the random pool using the previously chosen encryption and -hash function. An adversary may attempt to learn or alter the state -of the pool in order to affect its future output; this function -destroys the existing state of the pool in a non-reversible way. It -is recommended that \method{stir()} be called before and after using -the \class{RandomPool} object. Even better, several calls to -\method{stir()} can be interleaved with calls to \method{add_event()}. -\end{methoddesc} - -The \class{PersistentRandomPool} class is a subclass of \class{RandomPool} -that adds the capability to save and load the pool from a disk file. - -\begin{classdesc}{PersistentRandomPool}{filename, \optional{numbytes, cipher, hash}} -The path given in \var{filename} will be automatically opened, and an -existing random pool read; if no such file exists, the pool will be -initialized as usual. If omitted, the filename defaults to the empty -string, which will prevent it from being saved to a file. These -arguments are identical to those for the \class{RandomPool} -constructor. -\end{classdesc} - -\begin{methoddesc}{save}{} -Opens the file named by the \member{filename} attribute, and saves the -random data into the file using the \module{pickle} module. -\end{methoddesc} - -The \class{KeyboardRandomPool} class is a subclass of -\class{PersistentRandomPool} that provides a method to obtain random -data from the keyboard: - -\begin{methoddesc}{randomize}{} -(Unix systems only) Obtain random data from the keyboard. This works -by prompting the -user to hit keys at random, and then using the keystroke timings (and -also the actual keys pressed) to add entropy to the pool. This works -similarly to PGP's random pool mechanism. -\end{methoddesc} - - -\subsection{Crypto.Util.RFC1751} -The keys for private-key algorithms should be arbitrary binary data. -Many systems err by asking the user to enter a password, and then -using the password as the key. This limits the space of possible -keys, as each key byte is constrained within the range of possible -ASCII characters, 32-127, instead of the whole 0-255 range possible -with ASCII. Unfortunately, it's difficult for humans to remember 16 -or 32 hex digits. - -One solution is to request a lengthy passphrase from the user, and -then run it through a hash function such as SHA or MD5. Another -solution is discussed in RFC 1751, "A Convention for Human-Readable -128-bit Keys", by Daniel L. McDonald. Binary keys are transformed -into a list of short English words that should be easier to remember. -For example, the hex key EB33F77EE73D4053 is transformed to "TIDE ITCH -SLOW REIN RULE MOT". - -\begin{funcdesc}{key_to_english}{key} -Accepts a string of arbitrary data \var{key}, and returns a string -containing uppercase English words separated by spaces. \var{key}'s -length must be a multiple of 8. -\end{funcdesc} - -\begin{funcdesc}{english_to_key}{string} -Accepts \var{string} containing English words, and returns a string of -binary data representing the key. Words must be separated by -whitespace, and can be any mixture of uppercase and lowercase -characters. 6 words are required for 8 bytes of key data, so -the number of words in \var{string} must be a multiple of 6. -\end{funcdesc} - - -%====================================================================== -\section{Extending the Toolkit} - -Preserving the a common interface for cryptographic routines is a good -idea. This chapter explains how to write new modules for the Toolkit. - -The basic process is as follows: -\begin{enumerate} - -\item Add a new \file{.c} file containing an implementation of the new -algorithm. -This file must define 3 or 4 standard functions, -a few constants, and a C \code{struct} encapsulating the state variables required by the algorithm. - -\item Add the new algorithm to \file{setup.py}. - -\item Send a copy of the code to me, if you like; code for new -algorithms will be gratefully accepted. -\end{enumerate} - - -\subsection{Adding Hash Algorithms} - -The required constant definitions are as follows: - -\begin{verbatim} -#define MODULE_NAME MD2 /* Name of algorithm */ -#define DIGEST_SIZE 16 /* Size of resulting digest in bytes */ -\end{verbatim} - -The C structure must be named \ctype{hash_state}: - -\begin{verbatim} -typedef struct { - ... whatever state variables you need ... -} hash_state; -\end{verbatim} - -There are four functions that need to be written: to initialize the -algorithm's state, to hash a string into the algorithm's state, to get -a digest from the current state, and to copy a state. - -\begin{itemize} - \item \code{void hash_init(hash_state *self);} - \item \code{void hash_update(hash_state *self, unsigned char *buffer, int length);} - \item \code{PyObject *hash_digest(hash_state *self);} - \item \code{void hash_copy(hash_state *source, hash_state *dest);} -\end{itemize} - -Put \code{\#include "hash_template.c"} at the end of the file to -include the actual implementation of the module. - - -\subsection{Adding Block Encryption Algorithms} - -The required constant definitions are as follows: - -\begin{verbatim} -#define MODULE_NAME AES /* Name of algorithm */ -#define BLOCK_SIZE 16 /* Size of encryption block */ -#define KEY_SIZE 0 /* Size of key in bytes (0 if not fixed size) */ -\end{verbatim} - -The C structure must be named \ctype{block_state}: - -\begin{verbatim} -typedef struct { - ... whatever state variables you need ... -} block_state; -\end{verbatim} - -There are three functions that need to be written: to initialize the -algorithm's state, and to encrypt and decrypt a single block. - -\begin{itemize} - \item \code{void block_init(block_state *self, unsigned char *key, - int keylen);} - \item \code{void block_encrypt(block_state *self, unsigned char *in, - unsigned char *out);} - \item \code{void block_decrypt(block_state *self, unsigned char *in, - unsigned char *out);} -\end{itemize} - -Put \code{\#include "block_template.c"} at the end of the file to -include the actual implementation of the module. - - -\subsection{Adding Stream Encryption Algorithms} - -The required constant definitions are as follows: - -\begin{verbatim} -#define MODULE_NAME ARC4 /* Name of algorithm */ -#define BLOCK_SIZE 1 /* Will always be 1 for a stream cipher */ -#define KEY_SIZE 0 /* Size of key in bytes (0 if not fixed size) */ -\end{verbatim} - -The C structure must be named \ctype{stream_state}: - -\begin{verbatim} -typedef struct { - ... whatever state variables you need ... -} stream_state; -\end{verbatim} - -There are three functions that need to be written: to initialize the -algorithm's state, and to encrypt and decrypt a single block. - -\begin{itemize} - \item \code{void stream_init(stream_state *self, unsigned char *key, - int keylen);} - \item \code{void stream_encrypt(stream_state *self, unsigned char *block, - int length);} - \item \code{void stream_decrypt(stream_state *self, unsigned char *block, - int length);} -\end{itemize} - -Put \code{\#include "stream_template.c"} at the end of the file to -include the actual implementation of the module. - - -\end{document} diff --git a/Crypto/Hash/HMAC.py b/Crypto/Hash/HMAC.py deleted file mode 100644 index eeb57823..00000000 --- a/Crypto/Hash/HMAC.py +++ /dev/null @@ -1,108 +0,0 @@ -"""HMAC (Keyed-Hashing for Message Authentication) Python module. - -Implements the HMAC algorithm as described by RFC 2104. - -This is just a copy of the Python 2.2 HMAC module, modified to work when -used on versions of Python before 2.2. -""" - -__revision__ = "$Id: HMAC.py,v 1.5 2002/07/25 17:19:02 z3p Exp $" - -import string - -def _strxor(s1, s2): - """Utility method. XOR the two strings s1 and s2 (must have same length). - """ - return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), s1, s2)) - -# The size of the digests returned by HMAC depends on the underlying -# hashing module used. -digest_size = None - -class HMAC: - """RFC2104 HMAC class. - - This supports the API for Cryptographic Hash Functions (PEP 247). - """ - - def __init__(self, key, msg = None, digestmod = None): - """Create a new HMAC object. - - key: key for the keyed hash object. - msg: Initial input for the hash, if provided. - digestmod: A module supporting PEP 247. Defaults to the md5 module. - """ - if digestmod == None: - import md5 - digestmod = md5 - - self.digestmod = digestmod - self.outer = digestmod.new() - self.inner = digestmod.new() - try: - self.digest_size = digestmod.digest_size - except AttributeError: - self.digest_size = len(self.outer.digest()) - - blocksize = 64 - ipad = "\x36" * blocksize - opad = "\x5C" * blocksize - - if len(key) > blocksize: - key = digestmod.new(key).digest() - - key = key + chr(0) * (blocksize - len(key)) - self.outer.update(_strxor(key, opad)) - self.inner.update(_strxor(key, ipad)) - if (msg): - self.update(msg) - -## def clear(self): -## raise NotImplementedError, "clear() method not available in HMAC." - - def update(self, msg): - """Update this hashing object with the string msg. - """ - self.inner.update(msg) - - def copy(self): - """Return a separate copy of this hashing object. - - An update to this copy won't affect the original object. - """ - other = HMAC("") - other.digestmod = self.digestmod - other.inner = self.inner.copy() - other.outer = self.outer.copy() - return other - - def digest(self): - """Return the hash value of this hashing object. - - This returns a string containing 8-bit data. The object is - not altered in any way by this function; you can continue - updating the object after calling this function. - """ - h = self.outer.copy() - h.update(self.inner.digest()) - return h.digest() - - def hexdigest(self): - """Like digest(), but returns a string of hexadecimal digits instead. - """ - return "".join([string.zfill(hex(ord(x))[2:], 2) - for x in tuple(self.digest())]) - -def new(key, msg = None, digestmod = None): - """Create a new hashing object and return it. - - key: The starting key for the hash. - msg: if available, will immediately be hashed into the object's starting - state. - - You can now feed arbitrary strings into the object using its update() - method, and can ask for the hash value at any time by calling its digest() - method. - """ - return HMAC(key, msg, digestmod) - diff --git a/Crypto/Hash/MD5.py b/Crypto/Hash/MD5.py deleted file mode 100644 index b0eba394..00000000 --- a/Crypto/Hash/MD5.py +++ /dev/null @@ -1,13 +0,0 @@ - -# Just use the MD5 module from the Python standard library - -__revision__ = "$Id: MD5.py,v 1.4 2002/07/11 14:31:19 akuchling Exp $" - -from md5 import * - -import md5 -if hasattr(md5, 'digestsize'): - digest_size = digestsize - del digestsize -del md5 - diff --git a/Crypto/Hash/SHA.py b/Crypto/Hash/SHA.py deleted file mode 100644 index ea3c6a34..00000000 --- a/Crypto/Hash/SHA.py +++ /dev/null @@ -1,11 +0,0 @@ - -# Just use the SHA module from the Python standard library - -__revision__ = "$Id: SHA.py,v 1.4 2002/07/11 14:31:19 akuchling Exp $" - -from sha import * -import sha -if hasattr(sha, 'digestsize'): - digest_size = digestsize - del digestsize -del sha diff --git a/Crypto/Hash/__init__.py b/Crypto/Hash/__init__.py deleted file mode 100644 index 30cbe1b6..00000000 --- a/Crypto/Hash/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Hashing algorithms - -Hash functions take arbitrary strings as input, and produce an output -of fixed size that is dependent on the input; it should never be -possible to derive the input data given only the hash function's -output. Hash functions can be used simply as a checksum, or, in -association with a public-key algorithm, can be used to implement -digital signatures. - -The hashing modules here all support the interface described in PEP -247, "API for Cryptographic Hash Functions". - -Submodules: -Crypto.Hash.HMAC RFC 2104: Keyed-Hashing for Message Authentication -Crypto.Hash.MD2 -Crypto.Hash.MD4 -Crypto.Hash.MD5 -Crypto.Hash.RIPEMD -Crypto.Hash.SHA -""" - -__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'SHA', 'SHA256'] -__revision__ = "$Id: __init__.py,v 1.6 2003/12/19 14:24:25 akuchling Exp $" - diff --git a/Crypto/LICENSE b/Crypto/LICENSE deleted file mode 100644 index ad3ae419..00000000 --- a/Crypto/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -=================================================================== -Distribute and use freely; there are no restrictions on further -dissemination and usage except those imposed by the laws of your -country of residence. This software is provided "as is" without -warranty of fitness for use or suitability for any purpose, express -or implied. Use at your own risk or not at all. -=================================================================== - -Incorporating the code into commercial products is permitted; you do -not have to make source available or contribute your changes back -(though that would be nice). - ---amk (www.amk.ca) - - diff --git a/Crypto/MANIFEST b/Crypto/MANIFEST deleted file mode 100644 index d19134e2..00000000 --- a/Crypto/MANIFEST +++ /dev/null @@ -1,63 +0,0 @@ -ACKS -ChangeLog -Cipher/__init__.py -Doc/pycrypt.tex -Hash/HMAC.py -Hash/MD5.py -Hash/SHA.py -Hash/__init__.py -LICENSE -MANIFEST -Protocol/AllOrNothing.py -Protocol/Chaffing.py -Protocol/__init__.py -PublicKey/DSA.py -PublicKey/ElGamal.py -PublicKey/RSA.py -PublicKey/__init__.py -PublicKey/pubkey.py -PublicKey/qNEW.py -PublicKey/test/rsa_speed.py -README -TODO -Util/RFC1751.py -Util/__init__.py -Util/number.py -Util/randpool.py -Util/test.py -Util/test/prime_speed.py -__init__.py -setup.py -src/AES.c -src/ARC2.c -src/ARC4.c -src/Blowfish.c -src/CAST.c -src/DES.c -src/DES3.c -src/IDEA.c -src/MD2.c -src/MD4.c -src/RC5.c -src/RIPEMD.c -src/SHA256.c -src/XOR.c -src/block_template.c -src/cast5.c -src/hash_template.c -src/stream_template.c -src/winrand.c -src/_dsa.c -src/_fastmath.c -src/_rsa.c -test.py -test/template -test/test_allornothing.py -test/test_chaffing.py -test/test_hashes.py -test/test_hmac.py -test/test_number.py -test/test_publickey.py -test/test_randpool.py -test/test_rfc1751.py -test/testdata.py diff --git a/Crypto/PKG-INFO b/Crypto/PKG-INFO deleted file mode 100644 index 764da08a..00000000 --- a/Crypto/PKG-INFO +++ /dev/null @@ -1,18 +0,0 @@ -Metadata-Version: 1.0 -Name: pycrypto -Version: 2.0.1 -Summary: Cryptographic modules for Python. -Home-page: http://www.amk.ca/python/code/crypto -Author: A.M. Kuchling -Author-email: amk@amk.ca -License: UNKNOWN -Download-URL: http://www.amk.ca/files/python/crypto/pycrypto-2.0.1.tar.gz -Description: UNKNOWN -Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta -Classifier: License :: Public Domain -Classifier: Intended Audience :: Developers -Classifier: Operating System :: Unix -Classifier: Operating System :: Microsoft :: Windows -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Topic :: Security :: Cryptography diff --git a/Crypto/Protocol/AllOrNothing.py b/Crypto/Protocol/AllOrNothing.py deleted file mode 100644 index 5fc600d9..00000000 --- a/Crypto/Protocol/AllOrNothing.py +++ /dev/null @@ -1,295 +0,0 @@ -"""This file implements all-or-nothing package transformations. - -An all-or-nothing package transformation is one in which some text is -transformed into message blocks, such that all blocks must be obtained before -the reverse transformation can be applied. Thus, if any blocks are corrupted -or lost, the original message cannot be reproduced. - -An all-or-nothing package transformation is not encryption, although a block -cipher algorithm is used. The encryption key is randomly generated and is -extractable from the message blocks. - -This class implements the All-Or-Nothing package transformation algorithm -described in: - -Ronald L. Rivest. "All-Or-Nothing Encryption and The Package Transform" -http://theory.lcs.mit.edu/~rivest/fusion.pdf - -""" - -__revision__ = "$Id: AllOrNothing.py,v 1.8 2003/02/28 15:23:20 akuchling Exp $" - -import operator -import string -from allmydata.Crypto.Util.number import bytes_to_long, long_to_bytes - - - -class AllOrNothing: - """Class implementing the All-or-Nothing package transform. - - Methods for subclassing: - - _inventkey(key_size): - Returns a randomly generated key. Subclasses can use this to - implement better random key generating algorithms. The default - algorithm is probably not very cryptographically secure. - - """ - - def __init__(self, ciphermodule, mode=None, IV=None): - """AllOrNothing(ciphermodule, mode=None, IV=None) - - ciphermodule is a module implementing the cipher algorithm to - use. It must provide the PEP272 interface. - - Note that the encryption key is randomly generated - automatically when needed. Optional arguments mode and IV are - passed directly through to the ciphermodule.new() method; they - are the feedback mode and initialization vector to use. All - three arguments must be the same for the object used to create - the digest, and to undigest'ify the message blocks. - """ - - self.__ciphermodule = ciphermodule - self.__mode = mode - self.__IV = IV - self.__key_size = ciphermodule.key_size - if self.__key_size == 0: - self.__key_size = 16 - - __K0digit = chr(0x69) - - def digest(self, text): - """digest(text:string) : [string] - - Perform the All-or-Nothing package transform on the given - string. Output is a list of message blocks describing the - transformed text, where each block is a string of bit length equal - to the ciphermodule's block_size. - """ - - # generate a random session key and K0, the key used to encrypt the - # hash blocks. Rivest calls this a fixed, publically-known encryption - # key, but says nothing about the security implications of this key or - # how to choose it. - key = self._inventkey(self.__key_size) - K0 = self.__K0digit * self.__key_size - - # we need two cipher objects here, one that is used to encrypt the - # message blocks and one that is used to encrypt the hashes. The - # former uses the randomly generated key, while the latter uses the - # well-known key. - mcipher = self.__newcipher(key) - hcipher = self.__newcipher(K0) - - # Pad the text so that its length is a multiple of the cipher's - # block_size. Pad with trailing spaces, which will be eliminated in - # the undigest() step. - block_size = self.__ciphermodule.block_size - padbytes = block_size - (len(text) % block_size) - text = text + ' ' * padbytes - - # Run through the algorithm: - # s: number of message blocks (size of text / block_size) - # input sequence: m1, m2, ... ms - # random key K' (`key' in the code) - # Compute output sequence: m'1, m'2, ... m's' for s' = s + 1 - # Let m'i = mi ^ E(K', i) for i = 1, 2, 3, ..., s - # Let m's' = K' ^ h1 ^ h2 ^ ... hs - # where hi = E(K0, m'i ^ i) for i = 1, 2, ... s - # - # The one complication I add is that the last message block is hard - # coded to the number of padbytes added, so that these can be stripped - # during the undigest() step - s = len(text) / block_size - blocks = [] - hashes = [] - for i in range(1, s+1): - start = (i-1) * block_size - end = start + block_size - mi = text[start:end] - assert len(mi) == block_size - cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) - mticki = bytes_to_long(mi) ^ bytes_to_long(cipherblock) - blocks.append(mticki) - # calculate the hash block for this block - hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size)) - hashes.append(bytes_to_long(hi)) - - # Add the padbytes length as a message block - i = i + 1 - cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) - mticki = padbytes ^ bytes_to_long(cipherblock) - blocks.append(mticki) - - # calculate this block's hash - hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size)) - hashes.append(bytes_to_long(hi)) - - # Now calculate the last message block of the sequence 1..s'. This - # will contain the random session key XOR'd with all the hash blocks, - # so that for undigest(), once all the hash blocks are calculated, the - # session key can be trivially extracted. Calculating all the hash - # blocks requires that all the message blocks be received, thus the - # All-or-Nothing algorithm succeeds. - mtick_stick = bytes_to_long(key) ^ reduce(operator.xor, hashes) - blocks.append(mtick_stick) - - # we convert the blocks to strings since in Python, byte sequences are - # always represented as strings. This is more consistent with the - # model that encryption and hash algorithms always operate on strings. - return map(long_to_bytes, blocks) - - - def undigest(self, blocks): - """undigest(blocks : [string]) : string - - Perform the reverse package transformation on a list of message - blocks. Note that the ciphermodule used for both transformations - must be the same. blocks is a list of strings of bit length - equal to the ciphermodule's block_size. - """ - - # better have at least 2 blocks, for the padbytes package and the hash - # block accumulator - if len(blocks) < 2: - raise ValueError, "List must be at least length 2." - - # blocks is a list of strings. We need to deal with them as long - # integers - blocks = map(bytes_to_long, blocks) - - # Calculate the well-known key, to which the hash blocks are - # encrypted, and create the hash cipher. - K0 = self.__K0digit * self.__key_size - hcipher = self.__newcipher(K0) - - # Since we have all the blocks (or this method would have been called - # prematurely), we can calcualte all the hash blocks. - hashes = [] - for i in range(1, len(blocks)): - mticki = blocks[i-1] ^ i - hi = hcipher.encrypt(long_to_bytes(mticki)) - hashes.append(bytes_to_long(hi)) - - # now we can calculate K' (key). remember the last block contains - # m's' which we don't include here - key = blocks[-1] ^ reduce(operator.xor, hashes) - - # and now we can create the cipher object - mcipher = self.__newcipher(long_to_bytes(key)) - block_size = self.__ciphermodule.block_size - - # And we can now decode the original message blocks - parts = [] - for i in range(1, len(blocks)): - cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) - mi = blocks[i-1] ^ bytes_to_long(cipherblock) - parts.append(mi) - - # The last message block contains the number of pad bytes appended to - # the original text string, such that its length was an even multiple - # of the cipher's block_size. This number should be small enough that - # the conversion from long integer to integer should never overflow - padbytes = int(parts[-1]) - text = string.join(map(long_to_bytes, parts[:-1]), '') - return text[:-padbytes] - - def _inventkey(self, key_size): - # TBD: Not a very secure algorithm. Eventually, I'd like to use JHy's - # kernelrand module - import time - from allmydata.Crypto.Util import randpool - # TBD: key_size * 2 to work around possible bug in RandomPool? - pool = randpool.RandomPool(key_size * 2) - while key_size > pool.entropy: - pool.add_event() - - # we now have enough entropy in the pool to get a key_size'd key - return pool.get_bytes(key_size) - - def __newcipher(self, key): - if self.__mode is None and self.__IV is None: - return self.__ciphermodule.new(key) - elif self.__IV is None: - return self.__ciphermodule.new(key, self.__mode) - else: - return self.__ciphermodule.new(key, self.__mode, self.__IV) - - - -if __name__ == '__main__': - import sys - import getopt - import base64 - - usagemsg = '''\ -Test module usage: %(program)s [-c cipher] [-l] [-h] - -Where: - --cipher module - -c module - Cipher module to use. Default: %(ciphermodule)s - - --aslong - -l - Print the encoded message blocks as long integers instead of base64 - encoded strings - - --help - -h - Print this help message -''' - - ciphermodule = 'AES' - aslong = 0 - - def usage(code, msg=None): - if msg: - print msg - print usagemsg % {'program': sys.argv[0], - 'ciphermodule': ciphermodule} - sys.exit(code) - - try: - opts, args = getopt.getopt(sys.argv[1:], - 'c:l', ['cipher=', 'aslong']) - except getopt.error, msg: - usage(1, msg) - - if args: - usage(1, 'Too many arguments') - - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-c', '--cipher'): - ciphermodule = arg - elif opt in ('-l', '--aslong'): - aslong = 1 - - # ugly hack to force __import__ to give us the end-path module - module = __import__('allmydata.Crypto.Cipher.'+ciphermodule, None, None, ['new']) - - a = AllOrNothing(module) - print 'Original text:\n==========' - print __doc__ - print '==========' - msgblocks = a.digest(__doc__) - print 'message blocks:' - for i, blk in map(None, range(len(msgblocks)), msgblocks): - # base64 adds a trailing newline - print ' %3d' % i, - if aslong: - print bytes_to_long(blk) - else: - print base64.encodestring(blk)[:-1] - # - # get a new undigest-only object so there's no leakage - b = AllOrNothing(module) - text = b.undigest(msgblocks) - if text == __doc__: - print 'They match!' - else: - print 'They differ!' diff --git a/Crypto/Protocol/Chaffing.py b/Crypto/Protocol/Chaffing.py deleted file mode 100644 index 36215f55..00000000 --- a/Crypto/Protocol/Chaffing.py +++ /dev/null @@ -1,229 +0,0 @@ -"""This file implements the chaffing algorithm. - -Winnowing and chaffing is a technique for enhancing privacy without requiring -strong encryption. In short, the technique takes a set of authenticated -message blocks (the wheat) and adds a number of chaff blocks which have -randomly chosen data and MAC fields. This means that to an adversary, the -chaff blocks look as valid as the wheat blocks, and so the authentication -would have to be performed on every block. By tailoring the number of chaff -blocks added to the message, the sender can make breaking the message -computationally infeasible. There are many other interesting properties of -the winnow/chaff technique. - -For example, say Alice is sending a message to Bob. She packetizes the -message and performs an all-or-nothing transformation on the packets. Then -she authenticates each packet with a message authentication code (MAC). The -MAC is a hash of the data packet, and there is a secret key which she must -share with Bob (key distribution is an exercise left to the reader). She then -adds a serial number to each packet, and sends the packets to Bob. - -Bob receives the packets, and using the shared secret authentication key, -authenticates the MACs for each packet. Those packets that have bad MACs are -simply discarded. The remainder are sorted by serial number, and passed -through the reverse all-or-nothing transform. The transform means that an -eavesdropper (say Eve) must acquire all the packets before any of the data can -be read. If even one packet is missing, the data is useless. - -There's one twist: by adding chaff packets, Alice and Bob can make Eve's job -much harder, since Eve now has to break the shared secret key, or try every -combination of wheat and chaff packet to read any of the message. The cool -thing is that Bob doesn't need to add any additional code; the chaff packets -are already filtered out because their MACs don't match (in all likelihood -- -since the data and MACs for the chaff packets are randomly chosen it is -possible, but very unlikely that a chaff MAC will match the chaff data). And -Alice need not even be the party adding the chaff! She could be completely -unaware that a third party, say Charles, is adding chaff packets to her -messages as they are transmitted. - -For more information on winnowing and chaffing see this paper: - -Ronald L. Rivest, "Chaffing and Winnowing: Confidentiality without Encryption" -http://theory.lcs.mit.edu/~rivest/chaffing.txt - -""" - -__revision__ = "$Id: Chaffing.py,v 1.7 2003/02/28 15:23:21 akuchling Exp $" - -from allmydata.Crypto.Util.number import bytes_to_long - -class Chaff: - """Class implementing the chaff adding algorithm. - - Methods for subclasses: - - _randnum(size): - Returns a randomly generated number with a byte-length equal - to size. Subclasses can use this to implement better random - data and MAC generating algorithms. The default algorithm is - probably not very cryptographically secure. It is most - important that the chaff data does not contain any patterns - that can be used to discern it from wheat data without running - the MAC. - - """ - - def __init__(self, factor=1.0, blocksper=1): - """Chaff(factor:float, blocksper:int) - - factor is the number of message blocks to add chaff to, - expressed as a percentage between 0.0 and 1.0. blocksper is - the number of chaff blocks to include for each block being - chaffed. Thus the defaults add one chaff block to every - message block. By changing the defaults, you can adjust how - computationally difficult it could be for an adversary to - brute-force crack the message. The difficulty is expressed - as: - - pow(blocksper, int(factor * number-of-blocks)) - - For ease of implementation, when factor < 1.0, only the first - int(factor*number-of-blocks) message blocks are chaffed. - """ - - if not (0.0<=factor<=1.0): - raise ValueError, "'factor' must be between 0.0 and 1.0" - if blocksper < 0: - raise ValueError, "'blocksper' must be zero or more" - - self.__factor = factor - self.__blocksper = blocksper - - - def chaff(self, blocks): - """chaff( [(serial-number:int, data:string, MAC:string)] ) - : [(int, string, string)] - - Add chaff to message blocks. blocks is a list of 3-tuples of the - form (serial-number, data, MAC). - - Chaff is created by choosing a random number of the same - byte-length as data, and another random number of the same - byte-length as MAC. The message block's serial number is - placed on the chaff block and all the packet's chaff blocks - are randomly interspersed with the single wheat block. This - method then returns a list of 3-tuples of the same form. - Chaffed blocks will contain multiple instances of 3-tuples - with the same serial number, but the only way to figure out - which blocks are wheat and which are chaff is to perform the - MAC hash and compare values. - """ - - chaffedblocks = [] - - # count is the number of blocks to add chaff to. blocksper is the - # number of chaff blocks to add per message block that is being - # chaffed. - count = len(blocks) * self.__factor - blocksper = range(self.__blocksper) - for i, wheat in map(None, range(len(blocks)), blocks): - # it shouldn't matter which of the n blocks we add chaff to, so for - # ease of implementation, we'll just add them to the first count - # blocks - if i < count: - serial, data, mac = wheat - datasize = len(data) - macsize = len(mac) - addwheat = 1 - # add chaff to this block - for j in blocksper: - import sys - chaffdata = self._randnum(datasize) - chaffmac = self._randnum(macsize) - chaff = (serial, chaffdata, chaffmac) - # mix up the order, if the 5th bit is on then put the - # wheat on the list - if addwheat and bytes_to_long(self._randnum(16)) & 0x40: - chaffedblocks.append(wheat) - addwheat = 0 - chaffedblocks.append(chaff) - if addwheat: - chaffedblocks.append(wheat) - else: - # just add the wheat - chaffedblocks.append(wheat) - return chaffedblocks - - def _randnum(self, size): - # TBD: Not a very secure algorithm. - # TBD: size * 2 to work around possible bug in RandomPool - from allmydata.Crypto.Util import randpool - import time - pool = randpool.RandomPool(size * 2) - while size > pool.entropy: - pass - - # we now have enough entropy in the pool to get size bytes of random - # data... well, probably - return pool.get_bytes(size) - - - -if __name__ == '__main__': - text = """\ -We hold these truths to be self-evident, that all men are created equal, that -they are endowed by their Creator with certain unalienable Rights, that among -these are Life, Liberty, and the pursuit of Happiness. That to secure these -rights, Governments are instituted among Men, deriving their just powers from -the consent of the governed. That whenever any Form of Government becomes -destructive of these ends, it is the Right of the People to alter or to -abolish it, and to institute new Government, laying its foundation on such -principles and organizing its powers in such form, as to them shall seem most -likely to effect their Safety and Happiness. -""" - print 'Original text:\n==========' - print text - print '==========' - - # first transform the text into packets - blocks = [] ; size = 40 - for i in range(0, len(text), size): - blocks.append( text[i:i+size] ) - - # now get MACs for all the text blocks. The key is obvious... - print 'Calculating MACs...' - from allmydata.Crypto.Hash import HMAC, SHA - key = 'Jefferson' - macs = [HMAC.new(key, block, digestmod=SHA).digest() - for block in blocks] - - assert len(blocks) == len(macs) - - # put these into a form acceptable as input to the chaffing procedure - source = [] - m = map(None, range(len(blocks)), blocks, macs) - print m - for i, data, mac in m: - source.append((i, data, mac)) - - # now chaff these - print 'Adding chaff...' - c = Chaff(factor=0.5, blocksper=2) - chaffed = c.chaff(source) - - from base64 import encodestring - - # print the chaffed message blocks. meanwhile, separate the wheat from - # the chaff - - wheat = [] - print 'chaffed message blocks:' - for i, data, mac in chaffed: - # do the authentication - h = HMAC.new(key, data, digestmod=SHA) - pmac = h.digest() - if pmac == mac: - tag = '-->' - wheat.append(data) - else: - tag = ' ' - # base64 adds a trailing newline - print tag, '%3d' % i, \ - repr(data), encodestring(mac)[:-1] - - # now decode the message packets and check it against the original text - print 'Undigesting wheat...' - newtext = "".join(wheat) - if newtext == text: - print 'They match!' - else: - print 'They differ!' diff --git a/Crypto/Protocol/__init__.py b/Crypto/Protocol/__init__.py deleted file mode 100644 index a6d68bcf..00000000 --- a/Crypto/Protocol/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ - -"""Cryptographic protocols - -Implements various cryptographic protocols. (Don't expect to find -network protocols here.) - -Crypto.Protocol.AllOrNothing Transforms a message into a set of message - blocks, such that the blocks can be - recombined to get the message back. - -Crypto.Protocol.Chaffing Takes a set of authenticated message blocks - (the wheat) and adds a number of - randomly generated blocks (the chaff). -""" - -__all__ = ['AllOrNothing', 'Chaffing'] -__revision__ = "$Id: __init__.py,v 1.4 2003/02/28 15:23:21 akuchling Exp $" diff --git a/Crypto/PublicKey/DSA.py b/Crypto/PublicKey/DSA.py deleted file mode 100644 index 685842ea..00000000 --- a/Crypto/PublicKey/DSA.py +++ /dev/null @@ -1,238 +0,0 @@ - -# -# DSA.py : Digital Signature Algorithm -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: DSA.py,v 1.16 2004/05/06 12:52:54 akuchling Exp $" - -from allmydata.Crypto.PublicKey.pubkey import * -from allmydata.Crypto.Util import number -from allmydata.Crypto.Util.number import bytes_to_long, long_to_bytes -from allmydata.Crypto.Hash import SHA - -try: - from allmydata.Crypto.PublicKey import _fastmath -except ImportError: - _fastmath = None - -class error (Exception): - pass - -def generateQ(randfunc): - S=randfunc(20) - hash1=SHA.new(S).digest() - hash2=SHA.new(long_to_bytes(bytes_to_long(S)+1)).digest() - q = bignum(0) - for i in range(0,20): - c=ord(hash1[i])^ord(hash2[i]) - if i==0: - c=c | 128 - if i==19: - c= c | 1 - q=q*256+c - while (not isPrime(q)): - q=q+2 - if pow(2,159L) < q < pow(2,160L): - return S, q - raise error, 'Bad q value generated' - -def generate(bits, randfunc, progress_func=None): - """generate(bits:int, randfunc:callable, progress_func:callable) - - Generate a DSA key of length 'bits', using 'randfunc' to get - random data and 'progress_func', if present, to display - the progress of the key generation. - """ - - if bits<160: - raise error, 'Key length <160 bits' - obj=DSAobj() - # Generate string S and prime q - if progress_func: - progress_func('p,q\n') - while (1): - S, obj.q = generateQ(randfunc) - n=(bits-1)/160 - C, N, V = 0, 2, {} - b=(obj.q >> 5) & 15 - powb=pow(bignum(2), b) - powL1=pow(bignum(2), bits-1) - while C<4096: - for k in range(0, n+1): - V[k]=bytes_to_long(SHA.new(S+str(N)+str(k)).digest()) - W=V[n] % powb - for k in range(n-1, -1, -1): - W=(W<<160L)+V[k] - X=W+powL1 - p=X-(X%(2*obj.q)-1) - if powL1<=p and isPrime(p): - break - C, N = C+1, N+n+1 - if C<4096: - break - if progress_func: - progress_func('4096 multiples failed\n') - - obj.p = p - power=(p-1)/obj.q - if progress_func: - progress_func('h,g\n') - while (1): - h=bytes_to_long(randfunc(bits)) % (p-1) - g=pow(h, power, p) - if 11: - break - obj.g=g - if progress_func: - progress_func('x,y\n') - while (1): - x=bytes_to_long(randfunc(20)) - if 0 < x < obj.q: - break - obj.x, obj.y = x, pow(g, x, p) - return obj - -def construct(tuple): - """construct(tuple:(long,long,long,long)|(long,long,long,long,long)):DSAobj - Construct a DSA object from a 4- or 5-tuple of numbers. - """ - obj=DSAobj() - if len(tuple) not in [4,5]: - raise error, 'argument for construct() wrong length' - for i in range(len(tuple)): - field = obj.keydata[i] - setattr(obj, field, tuple[i]) - return obj - -class DSAobj(pubkey): - keydata=['y', 'g', 'p', 'q', 'x'] - - def _encrypt(self, s, Kstr): - raise error, 'DSA algorithm cannot encrypt data' - - def _decrypt(self, s): - raise error, 'DSA algorithm cannot decrypt data' - - def _sign(self, M, K): - if (K<2 or self.q<=K): - raise error, 'K is not between 2 and q' - r=pow(self.g, K, self.p) % self.q - s=(inverse(K, self.q)*(M+self.x*r)) % self.q - return (r,s) - - def _verify(self, M, sig): - r, s = sig - if r<=0 or r>=self.q or s<=0 or s>=self.q: - return 0 - w=inverse(s, self.q) - u1, u2 = (M*w) % self.q, (r*w) % self.q - v1 = pow(self.g, u1, self.p) - v2 = pow(self.y, u2, self.p) - v = ((v1*v2) % self.p) - v = v % self.q - if v==r: - return 1 - return 0 - - def size(self): - "Return the maximum number of bits that can be handled by this key." - return number.size(self.p) - 1 - - def has_private(self): - """Return a Boolean denoting whether the object contains - private components.""" - if hasattr(self, 'x'): - return 1 - else: - return 0 - - def can_sign(self): - """Return a Boolean value recording whether this algorithm can generate signatures.""" - return 1 - - def can_encrypt(self): - """Return a Boolean value recording whether this algorithm can encrypt data.""" - return 0 - - def publickey(self): - """Return a new key object containing only the public information.""" - return construct((self.y, self.g, self.p, self.q)) - -object=DSAobj - -generate_py = generate -construct_py = construct - -class DSAobj_c(pubkey): - keydata = ['y', 'g', 'p', 'q', 'x'] - - def __init__(self, key): - self.key = key - - def __getattr__(self, attr): - if attr in self.keydata: - return getattr(self.key, attr) - else: - if self.__dict__.has_key(attr): - self.__dict__[attr] - else: - raise AttributeError, '%s instance has no attribute %s' % (self.__class__, attr) - - def __getstate__(self): - d = {} - for k in self.keydata: - if hasattr(self.key, k): - d[k]=getattr(self.key, k) - return d - - def __setstate__(self, state): - y,g,p,q = state['y'], state['g'], state['p'], state['q'] - if not state.has_key('x'): - self.key = _fastmath.dsa_construct(y,g,p,q) - else: - x = state['x'] - self.key = _fastmath.dsa_construct(y,g,p,q,x) - - def _sign(self, M, K): - return self.key._sign(M, K) - - def _verify(self, M, (r, s)): - return self.key._verify(M, r, s) - - def size(self): - return self.key.size() - - def has_private(self): - return self.key.has_private() - - def publickey(self): - return construct_c((self.key.y, self.key.g, self.key.p, self.key.q)) - - def can_sign(self): - return 1 - - def can_encrypt(self): - return 0 - -def generate_c(bits, randfunc, progress_func=None): - obj = generate_py(bits, randfunc, progress_func) - y,g,p,q,x = obj.y, obj.g, obj.p, obj.q, obj.x - return construct_c((y,g,p,q,x)) - -def construct_c(tuple): - key = apply(_fastmath.dsa_construct, tuple) - return DSAobj_c(key) - -if _fastmath: - #print "using C version of DSA" - generate = generate_c - construct = construct_c - error = _fastmath.error diff --git a/Crypto/PublicKey/ElGamal.py b/Crypto/PublicKey/ElGamal.py deleted file mode 100644 index c919744b..00000000 --- a/Crypto/PublicKey/ElGamal.py +++ /dev/null @@ -1,132 +0,0 @@ -# -# ElGamal.py : ElGamal encryption/decryption and signatures -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: ElGamal.py,v 1.9 2003/04/04 19:44:26 akuchling Exp $" - -from allmydata.Crypto.PublicKey.pubkey import * -from allmydata.Crypto.Util import number - -class error (Exception): - pass - -# Generate an ElGamal key with N bits -def generate(bits, randfunc, progress_func=None): - """generate(bits:int, randfunc:callable, progress_func:callable) - - Generate an ElGamal key of length 'bits', using 'randfunc' to get - random data and 'progress_func', if present, to display - the progress of the key generation. - """ - obj=ElGamalobj() - # Generate prime p - if progress_func: - progress_func('p\n') - obj.p=bignum(getPrime(bits, randfunc)) - # Generate random number g - if progress_func: - progress_func('g\n') - size=bits-1-(ord(randfunc(1)) & 63) # g will be from 1--64 bits smaller than p - if size<1: - size=bits-1 - while (1): - obj.g=bignum(getPrime(size, randfunc)) - if obj.g < obj.p: - break - size=(size+1) % bits - if size==0: - size=4 - # Generate random number x - if progress_func: - progress_func('x\n') - while (1): - size=bits-1-ord(randfunc(1)) # x will be from 1 to 256 bits smaller than p - if size>2: - break - while (1): - obj.x=bignum(getPrime(size, randfunc)) - if obj.x < obj.p: - break - size = (size+1) % bits - if size==0: - size=4 - if progress_func: - progress_func('y\n') - obj.y = pow(obj.g, obj.x, obj.p) - return obj - -def construct(tuple): - """construct(tuple:(long,long,long,long)|(long,long,long,long,long))) - : ElGamalobj - Construct an ElGamal key from a 3- or 4-tuple of numbers. - """ - - obj=ElGamalobj() - if len(tuple) not in [3,4]: - raise error, 'argument for construct() wrong length' - for i in range(len(tuple)): - field = obj.keydata[i] - setattr(obj, field, tuple[i]) - return obj - -class ElGamalobj(pubkey): - keydata=['p', 'g', 'y', 'x'] - - def _encrypt(self, M, K): - a=pow(self.g, K, self.p) - b=( M*pow(self.y, K, self.p) ) % self.p - return ( a,b ) - - def _decrypt(self, M): - if (not hasattr(self, 'x')): - raise error, 'Private key not available in this object' - ax=pow(M[0], self.x, self.p) - plaintext=(M[1] * inverse(ax, self.p ) ) % self.p - return plaintext - - def _sign(self, M, K): - if (not hasattr(self, 'x')): - raise error, 'Private key not available in this object' - p1=self.p-1 - if (GCD(K, p1)!=1): - raise error, 'Bad K value: GCD(K,p-1)!=1' - a=pow(self.g, K, self.p) - t=(M-self.x*a) % p1 - while t<0: t=t+p1 - b=(t*inverse(K, p1)) % p1 - return (a, b) - - def _verify(self, M, sig): - v1=pow(self.y, sig[0], self.p) - v1=(v1*pow(sig[0], sig[1], self.p)) % self.p - v2=pow(self.g, M, self.p) - if v1==v2: - return 1 - return 0 - - def size(self): - "Return the maximum number of bits that can be handled by this key." - return number.size(self.p) - 1 - - def has_private(self): - """Return a Boolean denoting whether the object contains - private components.""" - if hasattr(self, 'x'): - return 1 - else: - return 0 - - def publickey(self): - """Return a new key object containing only the public information.""" - return construct((self.p, self.g, self.y)) - - -object=ElGamalobj diff --git a/Crypto/PublicKey/RSA.py b/Crypto/PublicKey/RSA.py deleted file mode 100644 index e43242f6..00000000 --- a/Crypto/PublicKey/RSA.py +++ /dev/null @@ -1,256 +0,0 @@ -# -# RSA.py : RSA encryption/decryption -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: RSA.py,v 1.20 2004/05/06 12:52:54 akuchling Exp $" - -from allmydata.Crypto.PublicKey import pubkey -from allmydata.Crypto.Util import number - -try: - from allmydata.Crypto.PublicKey import _fastmath -except ImportError: - _fastmath = None - -class error (Exception): - pass - -def generate(bits, randfunc, progress_func=None): - """generate(bits:int, randfunc:callable, progress_func:callable) - - Generate an RSA key of length 'bits', using 'randfunc' to get - random data and 'progress_func', if present, to display - the progress of the key generation. - """ - obj=RSAobj() - - # Generate the prime factors of n - if progress_func: - progress_func('p,q\n') - p = q = 1L - while number.size(p*q) < bits: - p = pubkey.getPrime(bits/2, randfunc) - q = pubkey.getPrime(bits/2, randfunc) - - # p shall be smaller than q (for calc of u) - if p > q: - (p, q)=(q, p) - obj.p = p - obj.q = q - - if progress_func: - progress_func('u\n') - obj.u = pubkey.inverse(obj.p, obj.q) - obj.n = obj.p*obj.q - - obj.e = 65537L - if progress_func: - progress_func('d\n') - obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1)) - - assert bits <= 1+obj.size(), "Generated key is too small" - - return obj - -def construct(tuple): - """construct(tuple:(long,) : RSAobj - Construct an RSA object from a 2-, 3-, 5-, or 6-tuple of numbers. - """ - - obj=RSAobj() - if len(tuple) not in [2,3,5,6]: - raise error, 'argument for construct() wrong length' - for i in range(len(tuple)): - field = obj.keydata[i] - setattr(obj, field, tuple[i]) - if len(tuple) >= 5: - # Ensure p is smaller than q - if obj.p>obj.q: - (obj.p, obj.q)=(obj.q, obj.p) - - if len(tuple) == 5: - # u not supplied, so we're going to have to compute it. - obj.u=pubkey.inverse(obj.p, obj.q) - - return obj - -class RSAobj(pubkey.pubkey): - keydata = ['n', 'e', 'd', 'p', 'q', 'u'] - def _encrypt(self, plaintext, K=''): - if self.n<=plaintext: - raise error, 'Plaintext too large' - return (pow(plaintext, self.e, self.n),) - - def _decrypt(self, ciphertext): - if (not hasattr(self, 'd')): - raise error, 'Private key not available in this object' - if self.n<=ciphertext[0]: - raise error, 'Ciphertext too large' - return pow(ciphertext[0], self.d, self.n) - - def _sign(self, M, K=''): - return (self._decrypt((M,)),) - - def _verify(self, M, sig): - m2=self._encrypt(sig[0]) - if m2[0]==M: - return 1 - else: return 0 - - def _blind(self, M, B): - tmp = pow(B, self.e, self.n) - return (M * tmp) % self.n - - def _unblind(self, M, B): - tmp = pubkey.inverse(B, self.n) - return (M * tmp) % self.n - - def can_blind (self): - """can_blind() : bool - Return a Boolean value recording whether this algorithm can - blind data. (This does not imply that this - particular key object has the private information required to - to blind a message.) - """ - return 1 - - def size(self): - """size() : int - Return the maximum number of bits that can be handled by this key. - """ - return number.size(self.n) - 1 - - def has_private(self): - """has_private() : bool - Return a Boolean denoting whether the object contains - private components. - """ - if hasattr(self, 'd'): - return 1 - else: return 0 - - def publickey(self): - """publickey(): RSAobj - Return a new key object containing only the public key information. - """ - return construct((self.n, self.e)) - -class RSAobj_c(pubkey.pubkey): - keydata = ['n', 'e', 'd', 'p', 'q', 'u'] - - def __init__(self, key): - self.key = key - - def __getattr__(self, attr): - if attr in self.keydata: - return getattr(self.key, attr) - else: - if self.__dict__.has_key(attr): - self.__dict__[attr] - else: - raise AttributeError, '%s instance has no attribute %s' % (self.__class__, attr) - - def __getstate__(self): - d = {} - for k in self.keydata: - if hasattr(self.key, k): - d[k]=getattr(self.key, k) - return d - - def __setstate__(self, state): - n,e = state['n'], state['e'] - if not state.has_key('d'): - self.key = _fastmath.rsa_construct(n,e) - else: - d = state['d'] - if not state.has_key('q'): - self.key = _fastmath.rsa_construct(n,e,d) - else: - p, q, u = state['p'], state['q'], state['u'] - self.key = _fastmath.rsa_construct(n,e,d,p,q,u) - - def _encrypt(self, plain, K): - return (self.key._encrypt(plain),) - - def _decrypt(self, cipher): - return self.key._decrypt(cipher[0]) - - def _sign(self, M, K): - return (self.key._sign(M),) - - def _verify(self, M, sig): - return self.key._verify(M, sig[0]) - - def _blind(self, M, B): - return self.key._blind(M, B) - - def _unblind(self, M, B): - return self.key._unblind(M, B) - - def can_blind (self): - return 1 - - def size(self): - return self.key.size() - - def has_private(self): - return self.key.has_private() - - def publickey(self): - return construct_c((self.key.n, self.key.e)) - -def generate_c(bits, randfunc, progress_func = None): - # Generate the prime factors of n - if progress_func: - progress_func('p,q\n') - - p = q = 1L - while number.size(p*q) < bits: - p = pubkey.getPrime(bits/2, randfunc) - q = pubkey.getPrime(bits/2, randfunc) - - # p shall be smaller than q (for calc of u) - if p > q: - (p, q)=(q, p) - if progress_func: - progress_func('u\n') - u=pubkey.inverse(p, q) - n=p*q - - e = 65537L - if progress_func: - progress_func('d\n') - d=pubkey.inverse(e, (p-1)*(q-1)) - key = _fastmath.rsa_construct(n,e,d,p,q,u) - obj = RSAobj_c(key) - -## print p -## print q -## print number.size(p), number.size(q), number.size(q*p), -## print obj.size(), bits - assert bits <= 1+obj.size(), "Generated key is too small" - return obj - - -def construct_c(tuple): - key = apply(_fastmath.rsa_construct, tuple) - return RSAobj_c(key) - -object = RSAobj - -generate_py = generate -construct_py = construct - -if _fastmath: - #print "using C version of RSA" - generate = generate_c - construct = construct_c - error = _fastmath.error diff --git a/Crypto/PublicKey/__init__.py b/Crypto/PublicKey/__init__.py deleted file mode 100644 index ad1c80ca..00000000 --- a/Crypto/PublicKey/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Public-key encryption and signature algorithms. - -Public-key encryption uses two different keys, one for encryption and -one for decryption. The encryption key can be made public, and the -decryption key is kept private. Many public-key algorithms can also -be used to sign messages, and some can *only* be used for signatures. - -Crypto.PublicKey.DSA Digital Signature Algorithm. (Signature only) -Crypto.PublicKey.ElGamal (Signing and encryption) -Crypto.PublicKey.RSA (Signing, encryption, and blinding) -Crypto.PublicKey.qNEW (Signature only) - -""" - -__all__ = ['RSA', 'DSA', 'ElGamal', 'qNEW'] -__revision__ = "$Id: __init__.py,v 1.4 2003/04/03 20:27:13 akuchling Exp $" - diff --git a/Crypto/PublicKey/pubkey.py b/Crypto/PublicKey/pubkey.py deleted file mode 100644 index 5597fb7a..00000000 --- a/Crypto/PublicKey/pubkey.py +++ /dev/null @@ -1,172 +0,0 @@ -# -# pubkey.py : Internal functions for public key operations -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: pubkey.py,v 1.11 2003/04/03 20:36:14 akuchling Exp $" - -import types, warnings -from allmydata.Crypto.Util.number import * - -# Basic public key class -class pubkey: - def __init__(self): - pass - - def __getstate__(self): - """To keep key objects platform-independent, the key data is - converted to standard Python long integers before being - written out. It will then be reconverted as necessary on - restoration.""" - d=self.__dict__ - for key in self.keydata: - if d.has_key(key): d[key]=long(d[key]) - return d - - def __setstate__(self, d): - """On unpickling a key object, the key data is converted to the big -number representation being used, whether that is Python long -integers, MPZ objects, or whatever.""" - for key in self.keydata: - if d.has_key(key): self.__dict__[key]=bignum(d[key]) - - def encrypt(self, plaintext, K): - """encrypt(plaintext:string|long, K:string|long) : tuple - Encrypt the string or integer plaintext. K is a random - parameter required by some algorithms. - """ - wasString=0 - if isinstance(plaintext, types.StringType): - plaintext=bytes_to_long(plaintext) ; wasString=1 - if isinstance(K, types.StringType): - K=bytes_to_long(K) - ciphertext=self._encrypt(plaintext, K) - if wasString: return tuple(map(long_to_bytes, ciphertext)) - else: return ciphertext - - def decrypt(self, ciphertext): - """decrypt(ciphertext:tuple|string|long): string - Decrypt 'ciphertext' using this key. - """ - wasString=0 - if not isinstance(ciphertext, types.TupleType): - ciphertext=(ciphertext,) - if isinstance(ciphertext[0], types.StringType): - ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1 - plaintext=self._decrypt(ciphertext) - if wasString: return long_to_bytes(plaintext) - else: return plaintext - - def sign(self, M, K): - """sign(M : string|long, K:string|long) : tuple - Return a tuple containing the signature for the message M. - K is a random parameter required by some algorithms. - """ - if (not self.has_private()): - raise error, 'Private key not available in this object' - if isinstance(M, types.StringType): M=bytes_to_long(M) - if isinstance(K, types.StringType): K=bytes_to_long(K) - return self._sign(M, K) - - def verify (self, M, signature): - """verify(M:string|long, signature:tuple) : bool - Verify that the signature is valid for the message M; - returns true if the signature checks out. - """ - if isinstance(M, types.StringType): M=bytes_to_long(M) - return self._verify(M, signature) - - # alias to compensate for the old validate() name - def validate (self, M, signature): - warnings.warn("validate() method name is obsolete; use verify()", - DeprecationWarning) - - def blind(self, M, B): - """blind(M : string|long, B : string|long) : string|long - Blind message M using blinding factor B. - """ - wasString=0 - if isinstance(M, types.StringType): - M=bytes_to_long(M) ; wasString=1 - if isinstance(B, types.StringType): B=bytes_to_long(B) - blindedmessage=self._blind(M, B) - if wasString: return long_to_bytes(blindedmessage) - else: return blindedmessage - - def unblind(self, M, B): - """unblind(M : string|long, B : string|long) : string|long - Unblind message M using blinding factor B. - """ - wasString=0 - if isinstance(M, types.StringType): - M=bytes_to_long(M) ; wasString=1 - if isinstance(B, types.StringType): B=bytes_to_long(B) - unblindedmessage=self._unblind(M, B) - if wasString: return long_to_bytes(unblindedmessage) - else: return unblindedmessage - - - # The following methods will usually be left alone, except for - # signature-only algorithms. They both return Boolean values - # recording whether this key's algorithm can sign and encrypt. - def can_sign (self): - """can_sign() : bool - Return a Boolean value recording whether this algorithm can - generate signatures. (This does not imply that this - particular key object has the private information required to - to generate a signature.) - """ - return 1 - - def can_encrypt (self): - """can_encrypt() : bool - Return a Boolean value recording whether this algorithm can - encrypt data. (This does not imply that this - particular key object has the private information required to - to decrypt a message.) - """ - return 1 - - def can_blind (self): - """can_blind() : bool - Return a Boolean value recording whether this algorithm can - blind data. (This does not imply that this - particular key object has the private information required to - to blind a message.) - """ - return 0 - - # The following methods will certainly be overridden by - # subclasses. - - def size (self): - """size() : int - Return the maximum number of bits that can be handled by this key. - """ - return 0 - - def has_private (self): - """has_private() : bool - Return a Boolean denoting whether the object contains - private components. - """ - return 0 - - def publickey (self): - """publickey(): object - Return a new key object containing only the public information. - """ - return self - - def __eq__ (self, other): - """__eq__(other): 0, 1 - Compare us to other for equality. - """ - return self.__getstate__() == other.__getstate__() diff --git a/Crypto/PublicKey/qNEW.py b/Crypto/PublicKey/qNEW.py deleted file mode 100644 index d8e98f18..00000000 --- a/Crypto/PublicKey/qNEW.py +++ /dev/null @@ -1,170 +0,0 @@ -# -# qNEW.py : The q-NEW signature algorithm. -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: qNEW.py,v 1.8 2003/04/04 15:13:35 akuchling Exp $" - -from allmydata.Crypto.PublicKey import pubkey -from allmydata.Crypto.Util.number import * -from allmydata.Crypto.Hash import SHA - -class error (Exception): - pass - -HASHBITS = 160 # Size of SHA digests - -def generate(bits, randfunc, progress_func=None): - """generate(bits:int, randfunc:callable, progress_func:callable) - - Generate a qNEW key of length 'bits', using 'randfunc' to get - random data and 'progress_func', if present, to display - the progress of the key generation. - """ - obj=qNEWobj() - - # Generate prime numbers p and q. q is a 160-bit prime - # number. p is another prime number (the modulus) whose bit - # size is chosen by the caller, and is generated so that p-1 - # is a multiple of q. - # - # Note that only a single seed is used to - # generate p and q; if someone generates a key for you, you can - # use the seed to duplicate the key generation. This can - # protect you from someone generating values of p,q that have - # some special form that's easy to break. - if progress_func: - progress_func('p,q\n') - while (1): - obj.q = getPrime(160, randfunc) - # assert pow(2, 159L)1. g is kept; h can be discarded. - if progress_func: - progress_func('h,g\n') - while (1): - h=bytes_to_long(randfunc(bits)) % (p-1) - g=pow(h, power, p) - if 11: - break - obj.g=g - - # x is the private key information, and is - # just a random number between 0 and q. - # y=g**x mod p, and is part of the public information. - if progress_func: - progress_func('x,y\n') - while (1): - x=bytes_to_long(randfunc(20)) - if 0 < x < obj.q: - break - obj.x, obj.y=x, pow(g, x, p) - - return obj - -# Construct a qNEW object -def construct(tuple): - """construct(tuple:(long,long,long,long)|(long,long,long,long,long) - Construct a qNEW object from a 4- or 5-tuple of numbers. - """ - obj=qNEWobj() - if len(tuple) not in [4,5]: - raise error, 'argument for construct() wrong length' - for i in range(len(tuple)): - field = obj.keydata[i] - setattr(obj, field, tuple[i]) - return obj - -class qNEWobj(pubkey.pubkey): - keydata=['p', 'q', 'g', 'y', 'x'] - - def _sign(self, M, K=''): - if (self.q<=K): - raise error, 'K is greater than q' - if M<0: - raise error, 'Illegal value of M (<0)' - if M>=pow(2,161L): - raise error, 'Illegal value of M (too large)' - r=pow(self.g, K, self.p) % self.q - s=(K- (r*M*self.x % self.q)) % self.q - return (r,s) - def _verify(self, M, sig): - r, s = sig - if r<=0 or r>=self.q or s<=0 or s>=self.q: - return 0 - if M<0: - raise error, 'Illegal value of M (<0)' - if M<=0 or M>=pow(2,161L): - return 0 - v1 = pow(self.g, s, self.p) - v2 = pow(self.y, M*r, self.p) - v = ((v1*v2) % self.p) - v = v % self.q - if v==r: - return 1 - return 0 - - def size(self): - "Return the maximum number of bits that can be handled by this key." - return 160 - - def has_private(self): - """Return a Boolean denoting whether the object contains - private components.""" - return hasattr(self, 'x') - - def can_sign(self): - """Return a Boolean value recording whether this algorithm can generate signatures.""" - return 1 - - def can_encrypt(self): - """Return a Boolean value recording whether this algorithm can encrypt data.""" - return 0 - - def publickey(self): - """Return a new key object containing only the public information.""" - return construct((self.p, self.q, self.g, self.y)) - -object = qNEWobj - diff --git a/Crypto/PublicKey/test/rsa_speed.py b/Crypto/PublicKey/test/rsa_speed.py deleted file mode 100644 index 00a13e82..00000000 --- a/Crypto/PublicKey/test/rsa_speed.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# Script to time fast and slow RSA operations -# Contributed by Joris Bontje. - -import time, pprint -from allmydata.Crypto.PublicKey import * -from allmydata.Crypto.Util.randpool import RandomPool -from allmydata.Crypto.Util import number - -pool = RandomPool() -pool.stir() - -KEYSIZE=2048 -COUNT=5 -fasttime=0 -slowtime=0 -for x in range(COUNT): - begintime=time.time() - rsa=RSA.generate(KEYSIZE, pool.get_bytes) - endtime=time.time() - print "Server: Generating %d bit RSA key: %f s" % (KEYSIZE, endtime-begintime) - rsa_slow=RSA.construct((rsa.n,rsa.e,rsa.d)) - - code=number.getRandomNumber(256, pool.get_bytes) - begintime=time.time() - signature=rsa.sign(code,None)[0] - endtime=time.time() - fast=(endtime-begintime) - fasttime=fasttime+fast - print "Fast signing took %f s" % fast - - begintime=time.time() - signature_slow=rsa_slow.sign(code,None)[0] - endtime=time.time() - slow=(endtime-begintime) - slowtime=slowtime+slow - print "Slow signing took %f s" % slow - - if rsa.verify(code,(signature,)) and signature==signature_slow: - print "Signature okay" - else: - print "Signature WRONG" - - print "faster: %f" % (slow/fast) - -print "Based on %d signatures with %d bits keys the optimized\n RSA decryption/signing algorithm is %f times faster" % (COUNT, KEYSIZE, (slowtime/fasttime)) - diff --git a/Crypto/README b/Crypto/README deleted file mode 100644 index c0a134f7..00000000 --- a/Crypto/README +++ /dev/null @@ -1,76 +0,0 @@ -Python Cryptography Toolkit (pycrypto) -====================================== - -This is a collection of both secure hash functions (such as MD5 and SHA), -and various encryption algorithms (AES, DES, IDEA, RSA, ElGamal, etc.). The -package is structured to make adding new modules easy. I consider this -section to be essentially complete, and the software interface will almost -certainly not change in an incompatible way in the future; all that remains -to be done is to fix any bugs that show up. If you encounter a bug, please -report it in the SourceForge bug tracker at - https://sourceforge.net/tracker/?group_id=20937&atid=120937 - -An example usage of the MD5 module is: ->>> from Crypto.Hash import MD5 ->>> hash=MD5.new() ->>> hash.update('message') ->>> hash.digest() -'x\xe71\x02}\x8f\xd5\x0e\xd6B4\x0b|\x9ac\xb3' - -An example usage of an encryption algorithm (AES, in this case) is: - ->>> from Crypto.Cipher import AES ->>> obj=AES.new('This is a key456', AES.MODE_ECB) ->>> message="The answer is no" ->>> ciphertext=obj.encrypt(message) ->>> ciphertext -'o\x1aq_{P+\xd0\x07\xce\x89\xd1=M\x989' ->>> obj2 = AES.new('This is a key456', AES.MODE_ECB) ->>> obj2.decrypt(ciphertext) -'The answer is no' - -One possible application of the modules is writing secure -administration tools. Another application is in writing daemons and -servers. Clients and servers can encrypt the data being exchanged and -mutually authenticate themselves; daemons can encrypt private data for -added security. Python also provides a pleasant framework for -prototyping and experimentation with cryptographic algorithms; thanks -to its arbitrary-length integers, public key algorithms are easily -implemented. - -Development of the toolkit can be discussed on the pct mailing list; -archives and instructions for subscribing at at -. - - -Installation -============ - -The toolkit is written and tested using Python 2.2, though it should -also work with Python 2.1. Python 1.5.2 is not supported, and the -setup.py script will abort if you run it with 1.5.2. - -The modules are packaged using the Distutils, so you can simply run -"python setup.py build" to build the package, and "python setup.py -install" to install it. - -If the setup.py script crashes with a DistutilsPlatformError -complaining that the file /usr/lib/python2.2/config/Makefile doesn't -exist, this means that the files needed for compiling new Python -modules aren't installed on your system. Red Hat users often run into -this because they don't have the python2-devel RPM installed. The fix -is to simply install the requisite RPM. - -To verify that everything is in order, run "python test.py". It will test -all the cryptographic modules, skipping ones that aren't available. If the -test script reports an error on your machine, please report the bug using -the bug tracker (URL given above). If possible, track down the bug and -include a patch that fixes it. - -To install the package under the site-packages directory of -your Python installation, run "python setup.py install". - -If you have any comments, corrections, or improvements for this package, -please send it to the 'pct' mailing list. Good luck! - ---amk (www.amk.ca) diff --git a/Crypto/TODO b/Crypto/TODO deleted file mode 100644 index a79ad719..00000000 --- a/Crypto/TODO +++ /dev/null @@ -1,31 +0,0 @@ - -* Add more tests for random pool code? - -* Manual and Web page: point to SF project for bug reports - -* Update documentation (mention dodgy status of PublicKey code) - -* Clean up markup in pycrypt.tex - -* Reformat all the code to MEMS Exchange style - -* Document the functions and macros for adding a new algorithm - Hash functions: - hash_init(), hash_copy(), DIGEST_SIZE, hash_update(), hash_digest() - Block functions: - ... - -* Provide drop-in support for extensions/drivers like -amkCrypto/mxCrypto. There should be some way to register these -drivers in your package, e.g. by defining a certain subdirectory -to be a place where pycrypto looks for these drivers at startup -time. - -* Add a secure PRNG (Yarrow, maybe?) - -* A secret sharing module should be added to Util or Protocols. - -Documentation: - Document chaff/winnow better - Add docstrings everywhere. - diff --git a/Crypto/Util/RFC1751.py b/Crypto/Util/RFC1751.py deleted file mode 100644 index 0a479524..00000000 --- a/Crypto/Util/RFC1751.py +++ /dev/null @@ -1,342 +0,0 @@ -#!/usr/local/bin/python -# rfc1751.py : Converts between 128-bit strings and a human-readable -# sequence of words, as defined in RFC1751: "A Convention for -# Human-Readable 128-bit Keys", by Daniel L. McDonald. - -__revision__ = "$Id: RFC1751.py,v 1.6 2003/04/04 15:15:10 akuchling Exp $" - - -import string, binascii - -binary={0:'0000', 1:'0001', 2:'0010', 3:'0011', 4:'0100', 5:'0101', - 6:'0110', 7:'0111', 8:'1000', 9:'1001', 10:'1010', 11:'1011', - 12:'1100', 13:'1101', 14:'1110', 15:'1111'} - -def _key2bin(s): - "Convert a key into a string of binary digits" - kl=map(lambda x: ord(x), s) - kl=map(lambda x: binary[x/16]+binary[x&15], kl) - return ''.join(kl) - -def _extract(key, start, length): - """Extract a bitstring from a string of binary digits, and return its - numeric value.""" - k=key[start:start+length] - return reduce(lambda x,y: x*2+ord(y)-48, k, 0) - -def key_to_english (key): - """key_to_english(key:string) : string - Transform an arbitrary key into a string containing English words. - The key length must be a multiple of 8. - """ - english='' - for index in range(0, len(key), 8): # Loop over 8-byte subkeys - subkey=key[index:index+8] - # Compute the parity of the key - skbin=_key2bin(subkey) ; p=0 - for i in range(0, 64, 2): p=p+_extract(skbin, i, 2) - # Append parity bits to the subkey - skbin=_key2bin(subkey+chr((p<<6) & 255)) - for i in range(0, 64, 11): - english=english+wordlist[_extract(skbin, i, 11)]+' ' - - return english[:-1] # Remove the trailing space - -def english_to_key (str): - """english_to_key(string):string - Transform a string into a corresponding key. - The string must contain words separated by whitespace; the number - of words must be a multiple of 6. - """ - - L=string.split(string.upper(str)) ; key='' - for index in range(0, len(L), 6): - sublist=L[index:index+6] ; char=9*[0] ; bits=0 - for i in sublist: - index = wordlist.index(i) - shift = (8-(bits+11)%8) %8 - y = index << shift - cl, cc, cr = (y>>16), (y>>8)&0xff, y & 0xff - if (shift>5): - char[bits/8] = char[bits/8] | cl - char[bits/8+1] = char[bits/8+1] | cc - char[bits/8+2] = char[bits/8+2] | cr - elif shift>-3: - char[bits/8] = char[bits/8] | cc - char[bits/8+1] = char[bits/8+1] | cr - else: char[bits/8] = char[bits/8] | cr - bits=bits+11 - subkey=reduce(lambda x,y:x+chr(y), char, '') - - # Check the parity of the resulting key - skbin=_key2bin(subkey) - p=0 - for i in range(0, 64, 2): p=p+_extract(skbin, i, 2) - if (p&3) != _extract(skbin, 64, 2): - raise ValueError, "Parity error in resulting key" - key=key+subkey[0:8] - return key - -wordlist=[ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", - "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", - "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", - "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", - "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", - "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", - "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", - "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", - "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", - "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", - "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", - "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", - "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", - "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", - "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", - "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW", - "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", - "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", - "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", - "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", - "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", - "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", - "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE", - "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", - "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", - "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", - "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", - "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", - "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", - "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", - "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", - "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", - "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", - "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", - "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", - "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", - "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", - "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", - "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", - "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", - "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", - "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", - "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", - "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", - "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", - "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", - "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", - "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", - "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", - "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", - "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", - "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", - "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", - "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", - "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", - "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", - "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", - "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", - "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", - "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", - "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", - "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", - "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW", - "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA", - "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM", - "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", - "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", - "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", - "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", - "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", - "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", - "BEAU", "BECK", "BEEF", "BEEN", "BEER", - "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", - "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", - "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", - "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", - "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", - "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", - "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", - "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", - "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", - "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", - "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", - "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", - "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", - "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL", - "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", - "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", - "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", - "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", - "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", - "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", - "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", - "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST", - "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", - "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", - "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", - "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN", - "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", - "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", - "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", - "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", - "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", - "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", - "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", - "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", - "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", - "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", - "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", - "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", - "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", - "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", - "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", - "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST", - "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", - "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", - "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", - "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", - "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", - "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", - "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", - "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", - "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", - "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH", - "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", - "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", - "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", - "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", - "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", - "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", - "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", - "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", - "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", - "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK", - "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", - "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", - "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", - "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", - "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", - "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", - "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", - "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", - "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", - "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", - "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", - "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", - "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", - "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", - "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", - "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", - "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", - "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", - "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", - "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", - "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", - "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", - "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", - "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", - "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", - "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST", - "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", - "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", - "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", - "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", - "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", - "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", - "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", - "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", - "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", - "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK", - "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", - "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", - "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", - "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", - "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", - "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", - "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", - "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", - "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", - "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", - "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", - "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", - "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", - "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", - "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", - "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", - "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", - "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", - "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", - "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", - "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", - "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", - "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA", - "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", - "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD", - "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", - "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", - "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", - "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", - "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", - "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", - "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", - "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", - "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS", - "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", - "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", - "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", - "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", - "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", - "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", - "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", - "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", - "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", - "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", - "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", - "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", - "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", - "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", - "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", - "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", - "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN", - "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", - "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY", - "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", - "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", - "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", - "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", - "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", - "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", - "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", - "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", - "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", - "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", - "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", - "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", - "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", - "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", - "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", - "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE", - "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", - "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", - "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", - "YELL", "YOGA", "YOKE" ] - -if __name__=='__main__': - data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', - 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', - 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] - - for key, words in data: - print 'Trying key', key - key=binascii.a2b_hex(key) - w2=key_to_english(key) - if w2!=words: - print 'key_to_english fails on key', repr(key), ', producing', str(w2) - k2=english_to_key(words) - if k2!=key: - print 'english_to_key fails on key', repr(key), ', producing', repr(k2) - - diff --git a/Crypto/Util/__init__.py b/Crypto/Util/__init__.py deleted file mode 100644 index 0d147681..00000000 --- a/Crypto/Util/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Miscellaneous modules - -Contains useful modules that don't belong into any of the -other Crypto.* subpackages. - -Crypto.Util.number Number-theoretic functions (primality testing, etc.) -Crypto.Util.randpool Random number generation -Crypto.Util.RFC1751 Converts between 128-bit keys and human-readable - strings of words. - -""" - -__all__ = ['randpool', 'RFC1751', 'number'] - -__revision__ = "$Id: __init__.py,v 1.4 2003/02/28 15:26:00 akuchling Exp $" - diff --git a/Crypto/Util/bench.py b/Crypto/Util/bench.py deleted file mode 100644 index a1682939..00000000 --- a/Crypto/Util/bench.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python - -from pyutil.assertutil import _assert, precondition, postcondition -from pyutil.randutil import insecurerandstr -from pyutil import benchutil - -from allmydata.Crypto.Cipher import AES - -MODE_CTR = AES.MODE_CTR # MODE_CTR is same value for all ciphers in pycrypto 2.0.1 - -class CipherRunner: - def __init__(self, ciph, mode): - if not ciph.key_size: ciph.key_size = 16 - self.ciph = ciph - self.mode = mode - self.counterstart = None - self.key = None - self.text = None - self.obj = None - self.obj2 = None - - def init(self, n): - precondition(self.ciph.key_size, self.ciph.key_size) - self.key = insecurerandstr(self.ciph.key_size) - if self.mode == MODE_CTR: - self.counterstart = insecurerandstr(self.ciph.block_size) - _assert(self.key, self.key) - self.text = insecurerandstr(n) - if self.mode == MODE_CTR: - self.obj = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) - else: - self.obj = self.ciph.new(self.key, self.mode) - if self.mode == MODE_CTR: - self.obj2 = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) - else: - self.obj2 = self.ciph.new(self.key, self.mode) - - def construct_then_encrypt(self, n): - assert len(self.text) == n - if self.mode == MODE_CTR: - self.obj = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) - else: - self.obj = self.ciph.new(self.key, self.mode) - return self.obj.encrypt(self.text) - - def encrypt(self, n): - assert len(self.text) == n - return self.obj.encrypt(self.text) - - def decrypt(self, n): - assert len(self.text) == n - return self.obj.decrypt(self.text) - - def encrypt_then_decrypt_then_compare(self, n): - assert len(self.text) == n - ciphertext = self.obj.encrypt(self.text) - decrypted = self.obj2.decrypt(ciphertext) - if decrypted != self.text: - raise "FAILURE! decrypted does match original plaintext, self.text[:64]: %r, decrypted[:64]: %r" % (self.text[:64], decrypted[:64],) - - def construct_then_encrypt_then_decrypt_then_compare(self, n): - assert len(self.text) == n - if self.mode == MODE_CTR: - self.obj = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) - else: - self.obj = self.ciph.new(self.key, self.mode) - if self.mode == MODE_CTR: - self.obj2 = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) - else: - self.obj2 = self.ciph.new(self.key, self.mode) - ciphertext = self.obj.encrypt(self.text) - decrypted = self.obj2.decrypt(ciphertext) - if decrypted != self.text: - raise "FAILURE! decrypted does match original plaintext, self.text[:64]: %r, decrypted[:64]: %r" % (self.text[:64], decrypted[:64],) - -from allmydata.Crypto.Cipher import * -def bench_aes_ctr(): - c = CipherRunner(AES, AES.MODE_CTR) - - for m in (c.construct_then_encrypt, c.encrypt, c.decrypt, c.encrypt_then_decrypt_then_compare, c.construct_then_encrypt_then_decrypt_then_compare,): - print m.__name__ - for BSIZE in (2**4, 2**8, 2**10, 2**14, 2**16,): - benchutil.rep_bench(m, BSIZE, initfunc=c.init, MAXREPS=2**14, MAXTIME=10.0) - diff --git a/Crypto/Util/number.py b/Crypto/Util/number.py deleted file mode 100644 index 7a5de7de..00000000 --- a/Crypto/Util/number.py +++ /dev/null @@ -1,201 +0,0 @@ -# -# number.py : Number-theoretic functions -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: number.py,v 1.13 2003/04/04 18:21:07 akuchling Exp $" - -bignum = long -try: - from allmydata.Crypto.PublicKey import _fastmath -except ImportError: - _fastmath = None - -# Commented out and replaced with faster versions below -## def long2str(n): -## s='' -## while n>0: -## s=chr(n & 255)+s -## n=n>>8 -## return s - -## import types -## def str2long(s): -## if type(s)!=types.StringType: return s # Integers will be left alone -## return reduce(lambda x,y : x*256+ord(y), s, 0L) - -def size (N): - """size(N:long) : int - Returns the size of the number N in bits. - """ - bits, power = 0,1L - while N >= power: - bits += 1 - power = power << 1 - return bits - -def getRandomNumber(N, randfunc): - """getRandomNumber(N:int, randfunc:callable):long - Return an N-bit random number.""" - - S = randfunc(N/8) - odd_bits = N % 8 - if odd_bits != 0: - char = ord(randfunc(1)) >> (8-odd_bits) - S = chr(char) + S - value = bytes_to_long(S) - value |= 2L ** (N-1) # Ensure high bit is set - assert size(value) >= N - return value - -def GCD(x,y): - """GCD(x:long, y:long): long - Return the GCD of x and y. - """ - x = abs(x) ; y = abs(y) - while x > 0: - x, y = y % x, x - return y - -def inverse(u, v): - """inverse(u:long, u:long):long - Return the inverse of u mod v. - """ - u3, v3 = long(u), long(v) - u1, v1 = 1L, 0L - while v3 > 0: - q=u3 / v3 - u1, v1 = v1, u1 - v1*q - u3, v3 = v3, u3 - v3*q - while u1<0: - u1 = u1 + v - return u1 - -# Given a number of bits to generate and a random generation function, -# find a prime number of the appropriate size. - -def getPrime(N, randfunc): - """getPrime(N:int, randfunc:callable):long - Return a random N-bit prime number. - """ - - number=getRandomNumber(N, randfunc) | 1 - while (not isPrime(number)): - number=number+2 - return number - -def isPrime(N): - """isPrime(N:long):bool - Return true if N is prime. - """ - if N == 1: - return 0 - if N in sieve: - return 1 - for i in sieve: - if (N % i)==0: - return 0 - - # Use the accelerator if available - if _fastmath is not None: - return _fastmath.isPrime(N) - - # Compute the highest bit that's set in N - N1 = N - 1L - n = 1L - while (n> 1L - - # Rabin-Miller test - for c in sieve[:7]: - a=long(c) ; d=1L ; t=n - while (t): # Iterate over the bits in N1 - x=(d*d) % N - if x==1L and d!=1L and d!=N1: - return 0 # Square root of 1 found - if N1 & t: - d=(x*a) % N - else: - d=x - t = t >> 1L - if d!=1L: - return 0 - return 1 - -# Small primes used for checking primality; these are all the primes -# less than 256. This should be enough to eliminate most of the odd -# numbers before needing to do a Rabin-Miller test at all. - -sieve=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, - 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, - 197, 199, 211, 223, 227, 229, 233, 239, 241, 251] - -# Improved conversion functions contributed by Barry Warsaw, after -# careful benchmarking - -import struct - -def long_to_bytes(n, blocksize=0): - """long_to_bytes(n:long, blocksize:int) : string - Convert a long integer to a byte string. - - If optional blocksize is given and greater than zero, pad the front of the - byte string with binary zeros so that the length is a multiple of - blocksize. - """ - # after much testing, this algorithm was deemed to be the fastest - s = '' - n = long(n) - pack = struct.pack - while n > 0: - s = pack('>I', n & 0xffffffffL) + s - n = n >> 32 - # strip off leading zeros - for i in range(len(s)): - if s[i] != '\000': - break - else: - # only happens when n == 0 - s = '\000' - i = 0 - s = s[i:] - # add back some pad bytes. this could be done more efficiently w.r.t. the - # de-padding being done above, but sigh... - if blocksize > 0 and len(s) % blocksize: - s = (blocksize - len(s) % blocksize) * '\000' + s - return s - -def bytes_to_long(s): - """bytes_to_long(string) : long - Convert a byte string to a long integer. - - This is (essentially) the inverse of long_to_bytes(). - """ - acc = 0L - unpack = struct.unpack - length = len(s) - if length % 4: - extra = (4 - length % 4) - s = '\000' * extra + s - length = length + extra - for i in range(0, length, 4): - acc = (acc << 32) + unpack('>I', s[i:i+4])[0] - return acc - -# For backwards compatibility... -import warnings -def long2str(n, blocksize=0): - warnings.warn("long2str() has been replaced by long_to_bytes()") - return long_to_bytes(n, blocksize) -def str2long(s): - warnings.warn("str2long() has been replaced by bytes_to_long()") - return bytes_to_long(s) diff --git a/Crypto/Util/randpool.py b/Crypto/Util/randpool.py deleted file mode 100644 index fb15ed69..00000000 --- a/Crypto/Util/randpool.py +++ /dev/null @@ -1,421 +0,0 @@ -# -# randpool.py : Cryptographically strong random number generation -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: randpool.py,v 1.14 2004/05/06 12:56:54 akuchling Exp $" - -import time, array, types, warnings, os.path -from allmydata.Crypto.Util.number import long_to_bytes -try: - import allmydata.Crypto.Util.winrandom as winrandom -except: - winrandom = None - -STIRNUM = 3 - -class RandomPool: - """randpool.py : Cryptographically strong random number generation. - - The implementation here is similar to the one in PGP. To be - cryptographically strong, it must be difficult to determine the RNG's - output, whether in the future or the past. This is done by using - a cryptographic hash function to "stir" the random data. - - Entropy is gathered in the same fashion as PGP; the highest-resolution - clock around is read and the data is added to the random number pool. - A conservative estimate of the entropy is then kept. - - If a cryptographically secure random source is available (/dev/urandom - on many Unixes, Windows CryptGenRandom on most Windows), then use - it. - - Instance Attributes: - bits : int - Maximum size of pool in bits - bytes : int - Maximum size of pool in bytes - entropy : int - Number of bits of entropy in this pool. - - Methods: - add_event([s]) : add some entropy to the pool - get_bytes(int) : get N bytes of random data - randomize([N]) : get N bytes of randomness from external source - """ - - - def __init__(self, numbytes = 160, cipher=None, hash=None): - if hash is None: - from allmydata.Crypto.Hash import SHA as hash - - # The cipher argument is vestigial; it was removed from - # version 1.1 so RandomPool would work even in the limited - # exportable subset of the code - if cipher is not None: - warnings.warn("'cipher' parameter is no longer used") - - if isinstance(hash, types.StringType): - # ugly hack to force __import__ to give us the end-path module - hash = __import__('allmydata.Crypto.Hash.'+hash, - None, None, ['new']) - warnings.warn("'hash' parameter should now be a hashing module") - - self.bytes = numbytes - self.bits = self.bytes*8 - self.entropy = 0 - self._hash = hash - - # Construct an array to hold the random pool, - # initializing it to 0. - self._randpool = array.array('B', [0]*self.bytes) - - self._event1 = self._event2 = 0 - self._addPos = 0 - self._getPos = hash.digest_size - self._lastcounter=time.time() - self.__counter = 0 - - self._measureTickSize() # Estimate timer resolution - self._randomize() - - def _updateEntropyEstimate(self, nbits): - self.entropy += nbits - if self.entropy < 0: - self.entropy = 0 - elif self.entropy > self.bits: - self.entropy = self.bits - - def _randomize(self, N = 0, devname = '/dev/urandom'): - """_randomize(N, DEVNAME:device-filepath) - collects N bits of randomness from some entropy source (e.g., - /dev/urandom on Unixes that have it, Windows CryptoAPI - CryptGenRandom, etc) - DEVNAME is optional, defaults to /dev/urandom. You can change it - to /dev/random if you want to block till you get enough - entropy. - """ - data = '' - if N <= 0: - nbytes = int((self.bits - self.entropy)/8+0.5) - else: - nbytes = int(N/8+0.5) - if winrandom: - # Windows CryptGenRandom provides random data. - data = winrandom.new().get_bytes(nbytes) - elif os.path.exists(devname): - # Many OSes support a /dev/urandom device - try: - f=open(devname) - data=f.read(nbytes) - f.close() - except IOError, (num, msg): - if num!=2: raise IOError, (num, msg) - # If the file wasn't found, ignore the error - if data: - self._addBytes(data) - # Entropy estimate: The number of bits of - # data obtained from the random source. - self._updateEntropyEstimate(8*len(data)) - self.stir_n() # Wash the random pool - - def randomize(self, N=0): - """randomize(N:int) - use the class entropy source to get some entropy data. - This is overridden by KeyboardRandomize(). - """ - return self._randomize(N) - - def stir_n(self, N = STIRNUM): - """stir_n(N) - stirs the random pool N times - """ - for i in xrange(N): - self.stir() - - def stir (self, s = ''): - """stir(s:string) - Mix up the randomness pool. This will call add_event() twice, - but out of paranoia the entropy attribute will not be - increased. The optional 's' parameter is a string that will - be hashed with the randomness pool. - """ - - entropy=self.entropy # Save inital entropy value - self.add_event() - - # Loop over the randomness pool: hash its contents - # along with a counter, and add the resulting digest - # back into the pool. - for i in range(self.bytes / self._hash.digest_size): - h = self._hash.new(self._randpool) - h.update(str(self.__counter) + str(i) + str(self._addPos) + s) - self._addBytes( h.digest() ) - self.__counter = (self.__counter + 1) & 0xFFFFffffL - - self._addPos, self._getPos = 0, self._hash.digest_size - self.add_event() - - # Restore the old value of the entropy. - self.entropy=entropy - - - def get_bytes (self, N): - """get_bytes(N:int) : string - Return N bytes of random data. - """ - - s='' - i, pool = self._getPos, self._randpool - h=self._hash.new() - dsize = self._hash.digest_size - num = N - while num > 0: - h.update( self._randpool[i:i+dsize] ) - s = s + h.digest() - num = num - dsize - i = (i + dsize) % self.bytes - if i>1, bits+1 - if bits>8: bits=8 - - self._event1, self._event2 = event, self._event1 - - self._updateEntropyEstimate(bits) - return bits - - # Private functions - def _noise(self): - # Adds a bit of noise to the random pool, by adding in the - # current time and CPU usage of this process. - # The difference from the previous call to _noise() is taken - # in an effort to estimate the entropy. - t=time.time() - delta = (t - self._lastcounter)/self._ticksize*1e6 - self._lastcounter = t - self._addBytes(long_to_bytes(long(1000*time.time()))) - self._addBytes(long_to_bytes(long(1000*time.clock()))) - self._addBytes(long_to_bytes(long(1000*time.time()))) - self._addBytes(long_to_bytes(long(delta))) - - # Reduce delta to a maximum of 8 bits so we don't add too much - # entropy as a result of this call. - delta=delta % 0xff - return int(delta) - - - def _measureTickSize(self): - # _measureTickSize() tries to estimate a rough average of the - # resolution of time that you can see from Python. It does - # this by measuring the time 100 times, computing the delay - # between measurements, and taking the median of the resulting - # list. (We also hash all the times and add them to the pool) - interval = [None] * 100 - h = self._hash.new(`(id(self),id(interval))`) - - # Compute 100 differences - t=time.time() - h.update(`t`) - i = 0 - j = 0 - while i < 100: - t2=time.time() - h.update(`(i,j,t2)`) - j += 1 - delta=int((t2-t)*1e6) - if delta: - interval[i] = delta - i += 1 - t=t2 - - # Take the median of the array of intervals - interval.sort() - self._ticksize=interval[len(interval)/2] - h.update(`(interval,self._ticksize)`) - # mix in the measurement times and wash the random pool - self.stir(h.digest()) - - def _addBytes(self, s): - "XOR the contents of the string S into the random pool" - i, pool = self._addPos, self._randpool - for j in range(0, len(s)): - pool[i]=pool[i] ^ ord(s[j]) - i=(i+1) % self.bytes - self._addPos = i - - # Deprecated method names: remove in PCT 2.1 or later. - def getBytes(self, N): - warnings.warn("getBytes() method replaced by get_bytes()", - DeprecationWarning) - return self.get_bytes(N) - - def addEvent (self, event, s=""): - warnings.warn("addEvent() method replaced by add_event()", - DeprecationWarning) - return self.add_event(s + str(event)) - -class PersistentRandomPool (RandomPool): - def __init__ (self, filename=None, *args, **kwargs): - RandomPool.__init__(self, *args, **kwargs) - self.filename = filename - if filename: - try: - # the time taken to open and read the file might have - # a little disk variability, modulo disk/kernel caching... - f=open(filename, 'rb') - self.add_event() - data = f.read() - self.add_event() - # mix in the data from the file and wash the random pool - self.stir(data) - f.close() - except IOError: - # Oh, well; the file doesn't exist or is unreadable, so - # we'll just ignore it. - pass - - def save(self): - if self.filename == "": - raise ValueError, "No filename set for this object" - # wash the random pool before save, provides some forward secrecy for - # old values of the pool. - self.stir_n() - f=open(self.filename, 'wb') - self.add_event() - f.write(self._randpool.tostring()) - f.close() - self.add_event() - # wash the pool again, provide some protection for future values - self.stir() - -# non-echoing Windows keyboard entry -_kb = 0 -if not _kb: - try: - import msvcrt - class KeyboardEntry: - def getch(self): - c = msvcrt.getch() - if c in ('\000', '\xe0'): - # function key - c += msvcrt.getch() - return c - def close(self, delay = 0): - if delay: - time.sleep(delay) - while msvcrt.kbhit(): - msvcrt.getch() - _kb = 1 - except: - pass - -# non-echoing Posix keyboard entry -if not _kb: - try: - import termios - class KeyboardEntry: - def __init__(self, fd = 0): - self._fd = fd - self._old = termios.tcgetattr(fd) - new = termios.tcgetattr(fd) - new[3]=new[3] & ~termios.ICANON & ~termios.ECHO - termios.tcsetattr(fd, termios.TCSANOW, new) - def getch(self): - termios.tcflush(0, termios.TCIFLUSH) # XXX Leave this in? - return os.read(self._fd, 1) - def close(self, delay = 0): - if delay: - time.sleep(delay) - termios.tcflush(self._fd, termios.TCIFLUSH) - termios.tcsetattr(self._fd, termios.TCSAFLUSH, self._old) - _kb = 1 - except: - pass - -class KeyboardRandomPool (PersistentRandomPool): - def __init__(self, *args, **kwargs): - PersistentRandomPool.__init__(self, *args, **kwargs) - - def randomize(self, N = 0): - "Adds N bits of entropy to random pool. If N is 0, fill up pool." - import os, string, time - if N <= 0: - bits = self.bits - self.entropy - else: - bits = N*8 - if bits == 0: - return - print bits,'bits of entropy are now required. Please type on the keyboard' - print 'until enough randomness has been accumulated.' - kb = KeyboardEntry() - s='' # We'll save the characters typed and add them to the pool. - hash = self._hash - e = 0 - try: - while e < bits: - temp=str(bits-e).rjust(6) - os.write(1, temp) - s=s+kb.getch() - e += self.add_event(s) - os.write(1, 6*chr(8)) - self.add_event(s+hash.new(s).digest() ) - finally: - kb.close() - print '\n\007 Enough. Please wait a moment.\n' - self.stir_n() # wash the random pool. - kb.close(4) - -if __name__ == '__main__': - pool = RandomPool() - print 'random pool entropy', pool.entropy, 'bits' - pool.add_event('something') - print `pool.get_bytes(100)` - import tempfile, os - fname = tempfile.mktemp() - pool = KeyboardRandomPool(filename=fname) - print 'keyboard random pool entropy', pool.entropy, 'bits' - pool.randomize() - print 'keyboard random pool entropy', pool.entropy, 'bits' - pool.randomize(128) - pool.save() - saved = open(fname, 'rb').read() - print 'saved', `saved` - print 'pool ', `pool._randpool.tostring()` - newpool = PersistentRandomPool(fname) - print 'persistent random pool entropy', pool.entropy, 'bits' - os.remove(fname) diff --git a/Crypto/Util/test.py b/Crypto/Util/test.py deleted file mode 100644 index b4a3c143..00000000 --- a/Crypto/Util/test.py +++ /dev/null @@ -1,495 +0,0 @@ -# -# test.py : Functions used for testing the modules -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -__revision__ = "$Id: test.py,v 1.16 2004/08/13 22:24:18 akuchling Exp $" - -import binascii -import random -import string -import testdata - -from allmydata.Crypto.Cipher import * -from allmydata.Crypto.Util.number import long_to_bytes - -def die(string): - import sys - print '***ERROR: ', string -# sys.exit(0) # Will default to continuing onward... - -def print_timing (size, delta, verbose): - if verbose: - if delta == 0: - print 'Unable to measure time -- elapsed time too small' - else: - print '%.2f K/sec' % (size/delta) - -def exerciseBlockCipher(cipher, verbose): - import string, time - try: - ciph = eval(cipher) - except NameError: - print cipher, 'module not available' - return None - print cipher+ ':' - str='1' # Build 128K of test data - for i in xrange(0, 17): - str=str+str - if ciph.key_size==0: ciph.key_size=16 - password = 'password12345678Extra text for password'[0:ciph.key_size] - IV = 'Test IV Test IV Test IV Test'[0:ciph.block_size] - - if verbose: print ' ECB mode:', - obj=ciph.new(password, ciph.MODE_ECB) - if obj.block_size != ciph.block_size: - die("Module and cipher object block_size don't match") - - text='1234567812345678'[0:ciph.block_size] - c=obj.encrypt(text) - if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"') - text='KuchlingKuchling'[0:ciph.block_size] - c=obj.encrypt(text) - if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"') - text='NotTodayNotEver!'[0:ciph.block_size] - c=obj.encrypt(text) - if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"') - - start=time.time() - s=obj.encrypt(str) - s2=obj.decrypt(s) - end=time.time() - if (str!=s2): - die('Error in resulting plaintext from ECB mode') - print_timing(256, end-start, verbose) - del obj - - if verbose: print ' CFB mode:', - obj1=ciph.new(password, ciph.MODE_CFB, IV) - obj2=ciph.new(password, ciph.MODE_CFB, IV) - start=time.time() - ciphertext=obj1.encrypt(str[0:65536]) - plaintext=obj2.decrypt(ciphertext) - end=time.time() - if (plaintext!=str[0:65536]): - die('Error in resulting plaintext from CFB mode') - print_timing(64, end-start, verbose) - del obj1, obj2 - - if verbose: print ' CBC mode:', - obj1=ciph.new(password, ciph.MODE_CBC, IV) - obj2=ciph.new(password, ciph.MODE_CBC, IV) - start=time.time() - ciphertext=obj1.encrypt(str) - plaintext=obj2.decrypt(ciphertext) - end=time.time() - if (plaintext!=str): - die('Error in resulting plaintext from CBC mode') - print_timing(256, end-start, verbose) - del obj1, obj2 - - if verbose: print ' PGP mode:', - obj1=ciph.new(password, ciph.MODE_PGP, IV) - obj2=ciph.new(password, ciph.MODE_PGP, IV) - start=time.time() - ciphertext=obj1.encrypt(str) - plaintext=obj2.decrypt(ciphertext) - end=time.time() - if (plaintext!=str): - die('Error in resulting plaintext from PGP mode') - print_timing(256, end-start, verbose) - del obj1, obj2 - - if verbose: print ' OFB mode:', - obj1=ciph.new(password, ciph.MODE_OFB, IV) - obj2=ciph.new(password, ciph.MODE_OFB, IV) - start=time.time() - ciphertext=obj1.encrypt(str) - plaintext=obj2.decrypt(ciphertext) - end=time.time() - if (plaintext!=str): - die('Error in resulting plaintext from OFB mode') - print_timing(256, end-start, verbose) - del obj1, obj2 - - startctr = random.randrange(0, 2**(ciph.block_size * 8)) - - if verbose: print ' CTR mode:', - obj1=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) - obj2=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) - start=time.time() - ciphertext=obj1.encrypt(str) - plaintext=obj2.decrypt(ciphertext) - end=time.time() - if (plaintext!=str): - die('Error in resulting plaintext from CTR mode') - print_timing(256, end-start, verbose) - del obj1, obj2 - - if verbose: print ' CTR mode, variable length:', - strv = str[:-1] - obj1=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) - obj2=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) - start=time.time() - ciphertext=obj1.encrypt(strv) - plaintext=obj2.decrypt(ciphertext) - end=time.time() - if (plaintext!=strv): - die('Error in resulting plaintext from CTR mode, variable length') - print_timing(256, end-start, verbose) - del obj1, obj2 - - if verbose: print ' CTR mode, variable length, restart:', - strv = str[:-1] - obj1=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) - obj2=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) - start=time.time() - tempstrv = strv - ciphertexta = [] - while tempstrv: - chunksiz = random.randrange(1, len(tempstrv)+1) - ciphertexta.append(obj1.encrypt(tempstrv[:chunksiz])) - tempstrv = tempstrv[chunksiz:] - ciphertext = ''.join(ciphertexta) - plaintext=obj2.decrypt(ciphertext) - end=time.time() - if (len(plaintext)!=len(strv)): - die('Error in resulting plaintext from CTR mode, variable length, restart, lenofplaintext: %s, lenofstrv: %r' % (len(plaintext), len(strv),)) - - if (plaintext!=strv): - die('Error in resulting plaintext from CTR mode, variable length, restart, plaintext: %r, strv: %r' % (plaintext, strv,)) - print_timing(256, end-start, verbose) - del obj1, obj2 - - # Test the IV handling - if verbose: print ' Testing IV handling' - obj1=ciph.new(password, ciph.MODE_CBC, IV) - plaintext='Test'*(ciph.block_size/4)*3 - ciphertext1=obj1.encrypt(plaintext) - obj1.IV=IV - ciphertext2=obj1.encrypt(plaintext) - if ciphertext1!=ciphertext2: - die('Error in setting IV') - - # Test keyword arguments - obj1=ciph.new(key=password) - obj1=ciph.new(password, mode=ciph.MODE_CBC) - obj1=ciph.new(mode=ciph.MODE_CBC, key=password) - obj1=ciph.new(IV=IV, mode=ciph.MODE_CBC, key=password) - - return ciph - -def exerciseStreamCipher(cipher, verbose): - import string, time - try: - ciph = eval(cipher) - except (NameError): - print cipher, 'module not available' - return None - print cipher + ':', - str='1' # Build 128K of test data - for i in xrange(0, 17): - str=str+str - key_size = ciph.key_size or 16 - password = 'password12345678Extra text for password'[0:key_size] - - obj1=ciph.new(password) - obj2=ciph.new(password) - if obj1.block_size != ciph.block_size: - die("Module and cipher object block_size don't match") - if obj1.key_size != ciph.key_size: - die("Module and cipher object key_size don't match") - - text='1234567812345678Python' - c=obj1.encrypt(text) - if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"') - text='B1FF I2 A R3A11Y |<00L D00D!!!!!' - c=obj1.encrypt(text) - if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"') - c=obj1.encrypt(text) - if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"') - - start=time.time() - s=obj1.encrypt(str) - str=obj2.decrypt(s) - end=time.time() - print_timing(256, end-start, verbose) - del obj1, obj2 - - return ciph - -def TestStreamModules(args=['arc4', 'XOR'], verbose=1): - import sys, string - args=map(string.lower, args) - - if 'arc4' in args: - # Test ARC4 stream cipher - arc4=exerciseStreamCipher('ARC4', verbose) - if (arc4!=None): - for entry in testdata.arc4: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=arc4.new(key) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('ARC4 failed on entry '+`entry`) - - if 'xor' in args: - # Test XOR stream cipher - XOR=exerciseStreamCipher('XOR', verbose) - if (XOR!=None): - for entry in testdata.xor: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=XOR.new(key) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('XOR failed on entry '+`entry`) - - -def TestBlockModules(args=['aes', 'arc2', 'des', 'blowfish', 'cast', 'des3'], - verbose=1): - import string - args=map(string.lower, args) - if 'aes' in args: - ciph=exerciseBlockCipher('AES', verbose) # AES - if (ciph!=None): - if verbose: print ' Verifying against test suite...' - for entry in testdata.aes: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=ciph.new(key, ciph.MODE_ECB) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('AES failed on entry '+`entry`) - for i in ciphertext: - if verbose: print hex(ord(i)), - if verbose: print - - for entry in testdata.aes_modes: - mode, key, plain, cipher, kw = entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - try: - obj=ciph.new(key, mode, **kw) - obj2=ciph.new(key, mode, **kw) - except: - print 'AES contruction got exception on entry '+`entry` - raise - try: - ciphertext=obj.encrypt(plain) - except: - print 'AES encrypt got exception on entry '+`entry` - raise - if (ciphertext!=cipher): - die('AES encrypt failed on entry '+`entry`) - for i in ciphertext: - if verbose: print hex(ord(i)), - if verbose: print - - plain2=obj2.decrypt(ciphertext) - if plain2!=plain: - die('AES decrypt failed on entry '+`entry`) - for i in plain2: - if verbose: print hex(ord(i)), - if verbose: print - - - if 'arc2' in args: - ciph=exerciseBlockCipher('ARC2', verbose) # Alleged RC2 - if (ciph!=None): - if verbose: print ' Verifying against test suite...' - for entry in testdata.arc2: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=ciph.new(key, ciph.MODE_ECB) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('ARC2 failed on entry '+`entry`) - for i in ciphertext: - if verbose: print hex(ord(i)), - print - - if 'blowfish' in args: - ciph=exerciseBlockCipher('Blowfish',verbose)# Bruce Schneier's Blowfish cipher - if (ciph!=None): - if verbose: print ' Verifying against test suite...' - for entry in testdata.blowfish: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=ciph.new(key, ciph.MODE_ECB) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('Blowfish failed on entry '+`entry`) - for i in ciphertext: - if verbose: print hex(ord(i)), - if verbose: print - - if 'cast' in args: - ciph=exerciseBlockCipher('CAST', verbose) # CAST-128 - if (ciph!=None): - if verbose: print ' Verifying against test suite...' - for entry in testdata.cast: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=ciph.new(key, ciph.MODE_ECB) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('CAST failed on entry '+`entry`) - for i in ciphertext: - if verbose: print hex(ord(i)), - if verbose: print - - if 0: - # The full-maintenance test; it requires 4 million encryptions, - # and correspondingly is quite time-consuming. I've disabled - # it; it's faster to compile block/cast.c with -DTEST and run - # the resulting program. - a = b = '\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45\x67\x89\x34\x56\x78\x9A' - - for i in range(0, 1000000): - obj = cast.new(b, cast.MODE_ECB) - a = obj.encrypt(a[:8]) + obj.encrypt(a[-8:]) - obj = cast.new(a, cast.MODE_ECB) - b = obj.encrypt(b[:8]) + obj.encrypt(b[-8:]) - - if a!="\xEE\xA9\xD0\xA2\x49\xFD\x3B\xA6\xB3\x43\x6F\xB8\x9D\x6D\xCA\x92": - if verbose: print 'CAST test failed: value of "a" doesn\'t match' - if b!="\xB2\xC9\x5E\xB0\x0C\x31\xAD\x71\x80\xAC\x05\xB8\xE8\x3D\x69\x6E": - if verbose: print 'CAST test failed: value of "b" doesn\'t match' - - if 'des' in args: - # Test/benchmark DES block cipher - des=exerciseBlockCipher('DES', verbose) - if (des!=None): - # Various tests taken from the DES library packaged with Kerberos V4 - obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_ECB) - s=obj.encrypt('Now is t') - if (s!=binascii.a2b_hex('3fa40e8a984d4815')): - die('DES fails test 1') - obj=des.new(binascii.a2b_hex('08192a3b4c5d6e7f'), des.MODE_ECB) - s=obj.encrypt('\000\000\000\000\000\000\000\000') - if (s!=binascii.a2b_hex('25ddac3e96176467')): - die('DES fails test 2') - obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC, - binascii.a2b_hex('1234567890abcdef')) - s=obj.encrypt("Now is the time for all ") - if (s!=binascii.a2b_hex('e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6')): - die('DES fails test 3') - obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC, - binascii.a2b_hex('fedcba9876543210')) - s=obj.encrypt("7654321 Now is the time for \000\000\000\000") - if (s!=binascii.a2b_hex("ccd173ffab2039f4acd8aefddfd8a1eb468e91157888ba681d269397f7fe62b4")): - die('DES fails test 4') - del obj,s - - # R. Rivest's test: see http://theory.lcs.mit.edu/~rivest/destest.txt - x=binascii.a2b_hex('9474B8E8C73BCA7D') - for i in range(0, 16): - obj=des.new(x, des.MODE_ECB) - if (i & 1): x=obj.decrypt(x) - else: x=obj.encrypt(x) - if x!=binascii.a2b_hex('1B1A2DDB4C642438'): - die("DES fails Rivest's test") - - if verbose: print ' Verifying against test suite...' - for entry in testdata.des: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=des.new(key, des.MODE_ECB) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('DES failed on entry '+`entry`) - for entry in testdata.des_cbc: - key, iv, plain, cipher=entry - key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher) - obj1=des.new(key, des.MODE_CBC, iv) - obj2=des.new(key, des.MODE_CBC, iv) - ciphertext=obj1.encrypt(plain) - if (ciphertext!=cipher): - die('DES CBC mode failed on entry '+`entry`) - - if 'des3' in args: - ciph=exerciseBlockCipher('DES3', verbose) # Triple DES - if (ciph!=None): - if verbose: print ' Verifying against test suite...' - for entry in testdata.des3: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=ciph.new(key, ciph.MODE_ECB) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('DES3 failed on entry '+`entry`) - for i in ciphertext: - if verbose: print hex(ord(i)), - if verbose: print - for entry in testdata.des3_cbc: - key, iv, plain, cipher=entry - key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher) - obj1=ciph.new(key, ciph.MODE_CBC, iv) - obj2=ciph.new(key, ciph.MODE_CBC, iv) - ciphertext=obj1.encrypt(plain) - if (ciphertext!=cipher): - die('DES3 CBC mode failed on entry '+`entry`) - - if 'idea' in args: - ciph=exerciseBlockCipher('IDEA', verbose) # IDEA block cipher - if (ciph!=None): - if verbose: print ' Verifying against test suite...' - for entry in testdata.idea: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=ciph.new(key, ciph.MODE_ECB) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('IDEA failed on entry '+`entry`) - - if 'rc5' in args: - # Ronald Rivest's RC5 algorithm - ciph=exerciseBlockCipher('RC5', verbose) - if (ciph!=None): - if verbose: print ' Verifying against test suite...' - for entry in testdata.rc5: - key,plain,cipher=entry - key=binascii.a2b_hex(key) - plain=binascii.a2b_hex(plain) - cipher=binascii.a2b_hex(cipher) - obj=ciph.new(key[4:], ciph.MODE_ECB, - version =ord(key[0]), - word_size=ord(key[1]), - rounds =ord(key[2]) ) - ciphertext=obj.encrypt(plain) - if (ciphertext!=cipher): - die('RC5 failed on entry '+`entry`) - for i in ciphertext: - if verbose: print hex(ord(i)), - if verbose: print - - - diff --git a/Crypto/Util/test/prime_speed.py b/Crypto/Util/test/prime_speed.py deleted file mode 100644 index 672bd970..00000000 --- a/Crypto/Util/test/prime_speed.py +++ /dev/null @@ -1,24 +0,0 @@ - -import time -from allmydata.Crypto.Util import number - -# Test of prime-generation speed - -# This randfunc is deterministic, so we should always find the same primes. -chars = ''.join(map(chr, range(255, 0, -1))) -def randfunc (N): - s = '' - while len(s) Mon, 5 Jun 2006 16:45:58 -0700 - -python-crypto (2.0.1+dfsg1-1) unstable; urgency=low - - * Acknowlegde NMUs (closes: #318055, #318012). - * Packaged new upstream version (closes: #325517). - - 2.0.1 includes fix for AMD64, presumingly also closes: #297516. - - -- Andreas Rottmann Tue, 4 Oct 2005 00:10:40 +0200 - -python-crypto (2.0+dp1-2.3) unstable; urgency=low - - * NMU. - * Add python2.4-crypto package, drop python2.1 and python2.2 packages - (closes: #313349). - - -- Matthias Klose Mon, 29 Aug 2005 07:18:38 +0000 - -python-crypto (2.0+dp1-2.2) unstable; urgency=low - - * NMU to fix build failures on some architectures - * Remove -O3 gcc option on m68k architecture to fix FTBFS due to an - internal compiler error - * Standards version 3.6.2 (no changes required) - * Relax the versioned build dependency of libgmp3-dev to 4.1.4-8 - instead of -9. Some architectures only have -8 at this point - which is sufficient. - - -- Bastian Kleineidam Fri, 12 Aug 2005 11:04:21 +0200 - -python-crypto (2.0+dp1-2.1) unstable; urgency=low - - * NMU to make package installable again - * Added missing build dependency on (versioned) libgmp3-dev, otherwise - the _fastmath module won't be compiled. - * Recompile against libgmp3c2 (Closes: #318055) - - -- Bastian Kleineidam Tue, 9 Aug 2005 10:54:41 +0200 - -python-crypto (2.0+dp1-2) unstable; urgency=medium - - * Added missing build-dependency on tetex-bin and tetex-extra (closes: - #288602). - - -- Andreas Rottmann Tue, 4 Jan 2005 17:47:27 +0100 - -python-crypto (2.0+dp1-1) unstable; urgency=medium - - * Again remove problematic code from orig tarball, which the NMU did - miss (not to mention that the orig tarball from the NMU wasn't - pristine and contained .pyc files). Urgency medium, so sarge won't end - up with problematic code. - * Include the manual in binary packages (closes: #273622). - * Switch to CDBS. - * Lowercase description synopsis, as suggested by lintian/developer's - reference. - * Advertice the newly-included (since 2.0) SHA256 module in the - description. - - -- Andreas Rottmann Sat, 1 Jan 2005 14:47:12 +0100 - -python-crypto (2.0-1) unstable; urgency=medium - - * NMU. - * New upstream version. - - -- Matthias Klose Tue, 17 Aug 2004 23:44:24 +0200 - -python-crypto (1.9a6+dp2-1) unstable; urgency=low - - * Transitioned to Python 2.3. - * Removed accidential junk form .orig.tar.gz. - - -- Andreas Rottmann Sat, 9 Aug 2003 12:41:23 +0200 - -python-crypto (1.9a6+dp1-2) unstable; urgency=low - - * Fixed Section (python instead of interpreters). - - -- Andreas Rottmann Sun, 20 Jul 2003 15:21:37 +0200 - -python-crypto (1.9a6+dp1-1) unstable; urgency=low - - * New upstream release. - * Bump Standards-Version to 3.6.0 (no changes). - - -- Andreas Rottmann Sun, 13 Jul 2003 18:26:54 +0200 - -python-crypto (1.9a4+dp1-4) unstable; urgency=low - - * Use dh_python. - + Build-depend on debhelper >= 4.1.29. - + Build-depend on python. - * Bump Standards-Version to 3.5.8. - - -- Andreas Rottmann Thu, 20 Feb 2003 14:55:12 +0100 - -python-crypto (1.9a4+dp1-3) unstable; urgency=low - - * Cipher/__init__.py: Remove 'RC5' and 'IDEA' from __all__. - - -- Andreas Rottmann Fri, 14 Feb 2003 01:10:26 +0100 - -python-crypto (1.9a4+dp1-2) unstable; urgency=low - - * debian/control: Added python2.x dependencies to binary packages. - * debian/control: Fixed 'Cryptpgraphic' typo (closes: #162884). - - -- Andreas Rottmann Thu, 7 Nov 2002 22:05:27 +0100 - -python-crypto (1.9a4+dp1-1) unstable; urgency=low - - * Removed problematic algorithms from source code. - + Added README.Debian with details. - + Updated package descriptions. - * Include docs in all pythonX.Y-crypto packages. - - -- Andreas Rottmann Wed, 11 Sep 2002 13:15:45 +0200 - -python-crypto (1.9a4-1) unstable; urgency=low - - * Initial Release (closes: #159717) - - -- Andreas Rottmann Thu, 5 Sep 2002 14:53:33 +0200 - diff --git a/Crypto/debian/compat b/Crypto/debian/compat deleted file mode 100644 index b8626c4c..00000000 --- a/Crypto/debian/compat +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/Crypto/debian/control b/Crypto/debian/control deleted file mode 100644 index 1e6f4e1a..00000000 --- a/Crypto/debian/control +++ /dev/null @@ -1,60 +0,0 @@ -Source: python-amdcrypto -Section: python -Priority: optional -Maintainer: Andreas Rottmann -Build-Depends: cdbs, debhelper (>= 4.2), python, python2.3-dev, python2.4-dev, ed, tetex-bin, tetex-extra, libgmp3-dev (>= 4.1.4-10) -Standards-Version: 3.6.2 - -Package: python-amdcrypto -Architecture: any -Depends: ${python:Depends} -Conflicts: python-crypto -Provides: python-crypto -Description: cryptographic algorithms and protocols for Python - A collection of cryptographic algorithms and protocols, implemented - for use from Python. Among the contents of the package: - . - * Hash functions: MD2, MD4. - * Block encryption algorithms: AES, ARC2, Blowfish, CAST, DES, Triple-DES. - * Stream encryption algorithms: ARC4, simple XOR. - * Public-key algorithms: RSA, DSA, ElGamal, qNEW. - * Protocols: All-or-nothing transforms, chaffing/winnowing. - * Miscellaneous: RFC1751 module for converting 128-key keys - into a set of English words, primality testing. - . - This is an empty dummy package that always depends on a package built - for Debian's default Python version. - -Package: python2.3-amdcrypto -Architecture: any -Depends: ${shlibs:Depends}, python2.3 -Conflicts: python2.3-crypto -Provides: python2.3-crypto -Description: cryptographic algorithms and protocols for Python - A collection of cryptographic algorithms and protocols, implemented - for use from Python. Among the contents of the package: - . - * Hash functions: MD2, MD4, SHA256. - * Block encryption algorithms: AES, ARC2, Blowfish, CAST, DES, Triple-DES. - * Stream encryption algorithms: ARC4, simple XOR. - * Public-key algorithms: RSA, DSA, ElGamal, qNEW. - * Protocols: All-or-nothing transforms, chaffing/winnowing. - * Miscellaneous: RFC1751 module for converting 128-key keys - into a set of English words, primality testing. - -Package: python2.4-amdcrypto -Architecture: any -Depends: ${shlibs:Depends}, python2.4 -Conflicts: python2.4-crypto -Provides: python2.4-crypto -Description: cryptographic algorithms and protocols for Python - A collection of cryptographic algorithms and protocols, implemented - for use from Python. Among the contents of the package: - . - * Hash functions: MD2, MD4. - * Block encryption algorithms: AES, ARC2, Blowfish, CAST, DES, Triple-DES. - * Stream encryption algorithms: ARC4, simple XOR. - * Public-key algorithms: RSA, DSA, ElGamal, qNEW. - * Protocols: All-or-nothing transforms, chaffing/winnowing. - * Miscellaneous: RFC1751 module for converting 128-key keys - into a set of English words, primality testing. diff --git a/Crypto/debian/copyright b/Crypto/debian/copyright deleted file mode 100644 index 7f39a182..00000000 --- a/Crypto/debian/copyright +++ /dev/null @@ -1,20 +0,0 @@ -This package was debianized by Andreas Rottmann on -Thu, 5 Sep 2002 14:53:33 +0200. - -It was downloaded from http://www.amk.ca/python/code/crypto.html - -Upstream Author: A.M. Kuchling - -Copyright: - -=================================================================== -Distribute and use freely; there are no restrictions on further -dissemination and usage except those imposed by the laws of your -country of residence. This software is provided "as is" without -warranty of fitness for use or suitability for any purpose, express -or implied. Use at your own risk or not at all. -=================================================================== - -Incorporating the code into commercial products is permitted; you do -not have to make source available or contribute your changes back -(though that would be nice). diff --git a/Crypto/debian/dirs b/Crypto/debian/dirs deleted file mode 100644 index ca882bbb..00000000 --- a/Crypto/debian/dirs +++ /dev/null @@ -1,2 +0,0 @@ -usr/bin -usr/sbin diff --git a/Crypto/debian/pathmangle.sh b/Crypto/debian/pathmangle.sh deleted file mode 100644 index 32bf8ced..00000000 --- a/Crypto/debian/pathmangle.sh +++ /dev/null @@ -1,17 +0,0 @@ -#! /bin/sh -# -# This script is used to mangle things like /usr/local/bin/python into -# something more in line with Debian's Python policy. - -set -e - -CMD=$1 -DIR=$2 - -grep -E -l -r '/usr/local(/bin)?/python' "$DIR" | - while read f; do - printf ",s:/usr/local\\\\(/bin\\\\)\\\\?/python:$CMD:g\nw\n" | ed -s "$f" - if [ "$(head -c2 $f)" = "#!" ]; then - chmod 755 "$f" - fi - done diff --git a/Crypto/debian/python2.3-amdcrypto.docs b/Crypto/debian/python2.3-amdcrypto.docs deleted file mode 100644 index 9b472891..00000000 --- a/Crypto/debian/python2.3-amdcrypto.docs +++ /dev/null @@ -1,4 +0,0 @@ -README -TODO -debian/README.Debian -Doc/pycrypt.ps diff --git a/Crypto/debian/python2.4-amdcrypto.docs b/Crypto/debian/python2.4-amdcrypto.docs deleted file mode 100644 index 9b472891..00000000 --- a/Crypto/debian/python2.4-amdcrypto.docs +++ /dev/null @@ -1,4 +0,0 @@ -README -TODO -debian/README.Debian -Doc/pycrypt.ps diff --git a/Crypto/debian/rules b/Crypto/debian/rules deleted file mode 100644 index 6520a8ff..00000000 --- a/Crypto/debian/rules +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/make -f - -include /usr/share/cdbs/1/rules/buildcore.mk -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/python-distutils.mk - -MKHOWTO = /usr/lib/python2.3/doc/tools/mkhowto - -common-build-arch:: - cd Doc && $(MKHOWTO) --ps - -$(patsubst %,binary-post-install/%,$(DEB_PYTHON_REAL_LIB_PACKAGES)):: - sh -e debian/pathmangle.sh /usr/bin/$(shell echo $(cdbs_curpkg) | sed 's,-crypto$$,,') debian/$(cdbs_curpkg) - -clean:: - rm -rf build - rm -f Doc/*.ps diff --git a/Crypto/setup.py b/Crypto/setup.py deleted file mode 100644 index 94f7a08e..00000000 --- a/Crypto/setup.py +++ /dev/null @@ -1,193 +0,0 @@ -#! /usr/bin/env python - -__revision__ = "$Id: setup.py,v 1.30 2005/06/14 01:20:22 akuchling Exp $" - -from distutils import core -from distutils.core import Extension -from distutils.command.build_ext import build_ext -import os, sys - -if sys.version[0:1] == '1': - raise RuntimeError, ("The Python Cryptography Toolkit requires " - "Python 2.x to build.") - -debug_build_kw = {} - -DEBUG_BUILD=False -# DEBUG_BUILD=True -if DEBUG_BUILD: - debug_build_kw.update({ - 'extra_compile_args': ['-O0', '-g',], - 'extra_link_args': ['-g',], - 'undef_macros': ['NDEBUG',], }) - -if sys.platform == 'win32': - HTONS_LIBS = ['ws2_32'] - plat_ext = [ - Extension("Crypto.Util.winrandom", - libraries = HTONS_LIBS + ['advapi32'], - include_dirs=['src/'], - extra_compile_args=['-O0 -g',], - extra_link_args=['-g',], - undef_macros=['NDEBUG',], - sources=["src/winrand.c"], - **debug_build_kw) - ] -else: - HTONS_LIBS = [] - plat_ext = [] - -# Functions for finding libraries and files, copied from Python's setup.py. - -def find_file(filename, std_dirs, paths): - """Searches for the directory where a given file is located, - and returns a possibly-empty list of additional directories, or None - if the file couldn't be found at all. - - 'filename' is the name of a file, such as readline.h or libcrypto.a. - 'std_dirs' is the list of standard system directories; if the - file is found in one of them, no additional directives are needed. - 'paths' is a list of additional locations to check; if the file is - found in one of them, the resulting list will contain the directory. - """ - - # Check the standard locations - for dir in std_dirs: - f = os.path.join(dir, filename) - if os.path.exists(f): return [] - - # Check the additional directories - for dir in paths: - f = os.path.join(dir, filename) - if os.path.exists(f): - return [dir] - - # Not found anywhere - return None - -def find_library_file(compiler, libname, std_dirs, paths): - filename = compiler.library_filename(libname, lib_type='shared') - result = find_file(filename, std_dirs, paths) - if result is not None: return result - - filename = compiler.library_filename(libname, lib_type='static') - result = find_file(filename, std_dirs, paths) - return result - - -def cc_remove_option (compiler, option): - """ - Remove option from Unix-style compiler. - """ - for optlist in (compiler.compiler, compiler.compiler_so): - if option in optlist: - optlist.remove(option) - - -class PCTBuildExt (build_ext): - def build_extensions(self): - self.extensions += [ - # Hash functions - Extension("Crypto.Hash.MD4", - include_dirs=['src/'], - sources=["src/MD4.c"], - **debug_build_kw), - Extension("Crypto.Hash.SHA256", - include_dirs=['src/'], - sources=["src/SHA256.c"], - **debug_build_kw), - - # Block encryption algorithms - Extension("Crypto.Cipher.AES", - include_dirs=['src/'], - sources=["src/AES.c"], - **debug_build_kw), - Extension("Crypto.Cipher.ARC2", - include_dirs=['src/'], - sources=["src/ARC2.c"], - **debug_build_kw), - Extension("Crypto.Cipher.Blowfish", - include_dirs=['src/'], - sources=["src/Blowfish.c"], - **debug_build_kw), - Extension("Crypto.Cipher.CAST", - include_dirs=['src/'], - sources=["src/CAST.c"], - **debug_build_kw), - Extension("Crypto.Cipher.DES", - include_dirs=['src/'], - sources=["src/DES.c"], - **debug_build_kw), - Extension("Crypto.Cipher.DES3", - include_dirs=['src/'], - sources=["src/DES3.c"], - **debug_build_kw), - - # Stream ciphers - Extension("Crypto.Cipher.ARC4", - include_dirs=['src/'], - sources=["src/ARC4.c"], - **debug_build_kw), - Extension("Crypto.Cipher.XOR", - include_dirs=['src/'], - sources=["src/XOR.c"], - **debug_build_kw), - ] - - # Detect which modules should be compiled - self.detect_modules() - if self.compiler.compiler_type == 'unix': - if os.uname()[4] == 'm68k': - # work around ICE on m68k machines in gcc 4.0.1 - cc_remove_option(self.compiler, "-O3") - build_ext.build_extensions(self) - - def detect_modules (self): - lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib'] - inc_dirs = self.compiler.include_dirs + ['/usr/include'] - exts = [] - if (self.compiler.find_library_file(lib_dirs, 'gmp')): - exts.append(Extension("Crypto.PublicKey._fastmath", - include_dirs=['src/'], - libraries=['gmp'], - sources=["src/_fastmath.c"])) - self.extensions += exts - - -kw = {'name':"pycrypto", - 'version':"2.0.1", - 'description':"Cryptographic modules for Python.", - 'author':"A.M. Kuchling", - 'author_email':"amk@amk.ca", - 'url':"http://www.amk.ca/python/code/crypto", - - 'cmdclass' : {'build_ext':PCTBuildExt}, - 'packages' : ["Crypto", "Crypto.Hash", "Crypto.Cipher", "Crypto.Util", - "Crypto.Protocol", "Crypto.PublicKey"], - 'package_dir' : { "Crypto":"." }, - # One module is defined here, because build_ext won't be - # called unless there's at least one extension module defined. - 'ext_modules':[Extension("Crypto.Hash.MD2", - include_dirs=['src/'], - sources=["src/MD2.c"], - **debug_build_kw)] - } - -# If we're running Python 2.3, add extra information -if hasattr(core, 'setup_keywords'): - if 'classifiers' in core.setup_keywords: - kw['classifiers'] = [ - 'Development Status :: 4 - Beta', - 'License :: Public Domain', - 'Intended Audience :: Developers', - 'Operating System :: Unix', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: MacOS :: MacOS X', - 'Topic :: Security :: Cryptography', - ] - if 'download_url' in core.setup_keywords: - kw['download_url'] = ('http://www.amk.ca/files/python/crypto/' - '%s-%s.tar.gz' % (kw['name'], kw['version']) ) - -core.setup(**kw) - diff --git a/Crypto/src/AES.c b/Crypto/src/AES.c deleted file mode 100644 index cf9bba9f..00000000 --- a/Crypto/src/AES.c +++ /dev/null @@ -1,1459 +0,0 @@ -/** - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. - */ - -#include -#include -#include "Python.h" - -#define MODULE_NAME AES -#define BLOCK_SIZE 16 -#define KEY_SIZE 0 - -#define MAXKC (256/32) -#define MAXKB (256/8) -#define MAXNR 14 - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; - -typedef struct { - u32 ek[ 4*(MAXNR+1) ]; - u32 dk[ 4*(MAXNR+1) ]; - int rounds; -} block_state; - -void rijndaelEncrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]); -void rijndaelDecrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]); - -#ifdef INTERMEDIATE_VALUE_KAT -void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); -void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); -#endif /* INTERMEDIATE_VALUE_KAT */ - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -static const u32 Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; -static const u32 Te1[256] = { - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; -static const u32 Te2[256] = { - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; -static const u32 Te3[256] = { - - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; -static const u32 Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; -static const u32 Td0[256] = { - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; -static const u32 Td1[256] = { - 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, - 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, - 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, - 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, - 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, - 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, - 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, - 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, - 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, - 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, - 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, - 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, - 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, - 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, - 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, - 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, - 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, - 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, - 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, - 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, - 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, - 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, - 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, - 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, - 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, - 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, - 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, - 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, - 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, - 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, - 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, - 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, - 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, - 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, - 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, - 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, - 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, - 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, - 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, - 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, - 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, - 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, - 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, - 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, - 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, - 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, - 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, - 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, - 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, - 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, - 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, - 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, - 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, - 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, - 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, - 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, - 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, - 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, - 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, - 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, - 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, - 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, - 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, - 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, -}; -static const u32 Td2[256] = { - 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, - 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, - 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, - 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, - 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, - 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, - 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, - 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, - 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, - 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, - 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, - 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, - 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, - 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, - 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, - 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, - 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, - 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, - 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, - 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, - 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, - 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, - 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, - 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, - 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, - 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, - 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, - 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, - 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, - 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, - 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, - 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, - 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, - 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, - 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, - 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, - 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, - 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, - 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, - 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, - 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, - 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, - 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, - 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, - 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, - 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, - 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, - 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, - 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, - 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, - 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, - 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, - 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, - 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, - 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, - 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, - 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, - 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, - 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, - 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, - 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, - 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, - 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, -}; -static const u32 Td3[256] = { - 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, - 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, - 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, - 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, - 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, - 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, - 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, - 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, - 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, - 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, - 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, - 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, - 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, - 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, - 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, - 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, - 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, - 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, - 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, - 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, - 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, - 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, - 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, - 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, - 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, - 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, - 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, - 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, - 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, - 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, - 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, - 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, - 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, - 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, - 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, - 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, - 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, - 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, - 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, - 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, - 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, - 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, - 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, - 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, - 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, - 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, - 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, - 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, - 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, - 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, - 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, - 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, - 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, - 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, - 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, - 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, - 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, - 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, - 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, - 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, - 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, - 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, - 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, - 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}; -static const u32 Td4[256] = { - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, -}; -static const u32 rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; - -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) - -#ifdef _MSC_VER -#define GETU32(p) SWAP(*((u32 *)(p))) -#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } -#else -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } -#endif - -/** - * Expand the cipher key into the encryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ - -int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { - int i = 0; - u32 temp; - - rk[0] = GETU32(cipherKey ); - rk[1] = GETU32(cipherKey + 4); - rk[2] = GETU32(cipherKey + 8); - rk[3] = GETU32(cipherKey + 12); - if (keyBits == 128) { - for (;;) { - temp = rk[3]; - rk[4] = rk[0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) { - return 10; - } - rk += 4; - } - } - rk[4] = GETU32(cipherKey + 16); - rk[5] = GETU32(cipherKey + 20); - if (keyBits == 192) { - for (;;) { - temp = rk[ 5]; - rk[ 6] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 7] = rk[ 1] ^ rk[ 6]; - rk[ 8] = rk[ 2] ^ rk[ 7]; - rk[ 9] = rk[ 3] ^ rk[ 8]; - if (++i == 8) { - return 12; - } - rk[10] = rk[ 4] ^ rk[ 9]; - rk[11] = rk[ 5] ^ rk[10]; - rk += 6; - } - } - rk[6] = GETU32(cipherKey + 24); - rk[7] = GETU32(cipherKey + 28); - if (keyBits == 256) { - for (;;) { - temp = rk[ 7]; - rk[ 8] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 9] = rk[ 1] ^ rk[ 8]; - rk[10] = rk[ 2] ^ rk[ 9]; - rk[11] = rk[ 3] ^ rk[10]; - if (++i == 7) { - return 14; - } - temp = rk[11]; - rk[12] = rk[ 4] ^ - (Te4[(temp >> 24) ] & 0xff000000) ^ - (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(temp ) & 0xff] & 0x000000ff); - rk[13] = rk[ 5] ^ rk[12]; - rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; - - rk += 8; - } - } - return 0; -} - -/** - * Expand the cipher key into the decryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { - int Nr, i, j; - u32 temp; - - /* expand the cipher key: */ - Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); - /* invert the order of the round keys: */ - for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - for (i = 1; i < Nr; i++) { - rk += 4; - rk[0] = - Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[0] ) & 0xff] & 0xff]; - rk[1] = - Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[1] ) & 0xff] & 0xff]; - rk[2] = - Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[2] ) & 0xff] & 0xff]; - rk[3] = - Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[3] ) & 0xff] & 0xff]; - } - return Nr; -} - -void rijndaelEncrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { - u32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(pt ) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; - if (Nr > 10) { - /* round 10: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; - /* round 11: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; - if (Nr > 12) { - /* round 12: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; - /* round 13: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; - } - } - rk += Nr << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - for (;;) { - t0 = - Te0[(s0 >> 24) ] ^ - Te1[(s1 >> 16) & 0xff] ^ - Te2[(s2 >> 8) & 0xff] ^ - Te3[(s3 ) & 0xff] ^ - rk[4]; - t1 = - Te0[(s1 >> 24) ] ^ - Te1[(s2 >> 16) & 0xff] ^ - Te2[(s3 >> 8) & 0xff] ^ - Te3[(s0 ) & 0xff] ^ - rk[5]; - t2 = - Te0[(s2 >> 24) ] ^ - Te1[(s3 >> 16) & 0xff] ^ - Te2[(s0 >> 8) & 0xff] ^ - Te3[(s1 ) & 0xff] ^ - rk[6]; - t3 = - Te0[(s3 >> 24) ] ^ - Te1[(s0 >> 16) & 0xff] ^ - Te2[(s1 >> 8) & 0xff] ^ - Te3[(s2 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Te0[(t0 >> 24) ] ^ - Te1[(t1 >> 16) & 0xff] ^ - Te2[(t2 >> 8) & 0xff] ^ - Te3[(t3 ) & 0xff] ^ - rk[0]; - s1 = - Te0[(t1 >> 24) ] ^ - Te1[(t2 >> 16) & 0xff] ^ - Te2[(t3 >> 8) & 0xff] ^ - Te3[(t0 ) & 0xff] ^ - rk[1]; - s2 = - Te0[(t2 >> 24) ] ^ - Te1[(t3 >> 16) & 0xff] ^ - Te2[(t0 >> 8) & 0xff] ^ - Te3[(t1 ) & 0xff] ^ - rk[2]; - s3 = - Te0[(t3 >> 24) ] ^ - Te1[(t0 >> 16) & 0xff] ^ - Te2[(t1 >> 8) & 0xff] ^ - Te3[(t2 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Te4[(t0 >> 24) ] & 0xff000000) ^ - (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(ct , s0); - s1 = - (Te4[(t1 >> 24) ] & 0xff000000) ^ - (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(ct + 4, s1); - s2 = - (Te4[(t2 >> 24) ] & 0xff000000) ^ - (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(ct + 8, s2); - s3 = - (Te4[(t3 >> 24) ] & 0xff000000) ^ - (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(ct + 12, s3); -} - -void rijndaelDecrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { - u32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(ct ) ^ rk[0]; - s1 = GETU32(ct + 4) ^ rk[1]; - s2 = GETU32(ct + 8) ^ rk[2]; - s3 = GETU32(ct + 12) ^ rk[3]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; - if (Nr > 10) { - /* round 10: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; - /* round 11: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; - if (Nr > 12) { - /* round 12: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; - /* round 13: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; - } - } - rk += Nr << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - for (;;) { - t0 = - Td0[(s0 >> 24) ] ^ - Td1[(s3 >> 16) & 0xff] ^ - Td2[(s2 >> 8) & 0xff] ^ - Td3[(s1 ) & 0xff] ^ - rk[4]; - t1 = - Td0[(s1 >> 24) ] ^ - Td1[(s0 >> 16) & 0xff] ^ - Td2[(s3 >> 8) & 0xff] ^ - Td3[(s2 ) & 0xff] ^ - rk[5]; - t2 = - Td0[(s2 >> 24) ] ^ - Td1[(s1 >> 16) & 0xff] ^ - Td2[(s0 >> 8) & 0xff] ^ - Td3[(s3 ) & 0xff] ^ - rk[6]; - t3 = - Td0[(s3 >> 24) ] ^ - Td1[(s2 >> 16) & 0xff] ^ - Td2[(s1 >> 8) & 0xff] ^ - Td3[(s0 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Td0[(t0 >> 24) ] ^ - Td1[(t3 >> 16) & 0xff] ^ - Td2[(t2 >> 8) & 0xff] ^ - Td3[(t1 ) & 0xff] ^ - rk[0]; - s1 = - Td0[(t1 >> 24) ] ^ - Td1[(t0 >> 16) & 0xff] ^ - Td2[(t3 >> 8) & 0xff] ^ - Td3[(t2 ) & 0xff] ^ - rk[1]; - s2 = - Td0[(t2 >> 24) ] ^ - Td1[(t1 >> 16) & 0xff] ^ - Td2[(t0 >> 8) & 0xff] ^ - Td3[(t3 ) & 0xff] ^ - rk[2]; - s3 = - Td0[(t3 >> 24) ] ^ - Td1[(t2 >> 16) & 0xff] ^ - Td2[(t1 >> 8) & 0xff] ^ - Td3[(t0 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Td4[(t0 >> 24) ] & 0xff000000) ^ - (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(pt , s0); - s1 = - (Td4[(t1 >> 24) ] & 0xff000000) ^ - (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(pt + 4, s1); - s2 = - (Td4[(t2 >> 24) ] & 0xff000000) ^ - (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(pt + 8, s2); - s3 = - (Td4[(t3 >> 24) ] & 0xff000000) ^ - (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(pt + 12, s3); -} - -#ifdef INTERMEDIATE_VALUE_KAT - -void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { - int r; - u32 s0, s1, s2, s3, t0, t1, t2, t3; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(block ) ^ rk[0]; - s1 = GETU32(block + 4) ^ rk[1]; - s2 = GETU32(block + 8) ^ rk[2]; - s3 = GETU32(block + 12) ^ rk[3]; - rk += 4; - - /* - * Nr - 1 full rounds: - */ - for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) { - t0 = - Te0[(s0 >> 24) ] ^ - Te1[(s1 >> 16) & 0xff] ^ - Te2[(s2 >> 8) & 0xff] ^ - Te3[(s3 ) & 0xff] ^ - rk[0]; - t1 = - Te0[(s1 >> 24) ] ^ - Te1[(s2 >> 16) & 0xff] ^ - Te2[(s3 >> 8) & 0xff] ^ - Te3[(s0 ) & 0xff] ^ - rk[1]; - t2 = - Te0[(s2 >> 24) ] ^ - Te1[(s3 >> 16) & 0xff] ^ - Te2[(s0 >> 8) & 0xff] ^ - Te3[(s1 ) & 0xff] ^ - rk[2]; - t3 = - Te0[(s3 >> 24) ] ^ - Te1[(s0 >> 16) & 0xff] ^ - Te2[(s1 >> 8) & 0xff] ^ - Te3[(s2 ) & 0xff] ^ - rk[3]; - - s0 = t0; - s1 = t1; - s2 = t2; - s3 = t3; - rk += 4; - - } - - /* - * apply last round and - * map cipher state to byte array block: - */ - if (rounds == Nr) { - t0 = - (Te4[(s0 >> 24) ] & 0xff000000) ^ - (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(s3 ) & 0xff] & 0x000000ff) ^ - rk[0]; - t1 = - (Te4[(s1 >> 24) ] & 0xff000000) ^ - (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(s0 ) & 0xff] & 0x000000ff) ^ - rk[1]; - t2 = - (Te4[(s2 >> 24) ] & 0xff000000) ^ - (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(s1 ) & 0xff] & 0x000000ff) ^ - rk[2]; - t3 = - (Te4[(s3 >> 24) ] & 0xff000000) ^ - (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(s2 ) & 0xff] & 0x000000ff) ^ - rk[3]; - - s0 = t0; - s1 = t1; - s2 = t2; - s3 = t3; - } - - PUTU32(block , s0); - PUTU32(block + 4, s1); - PUTU32(block + 8, s2); - PUTU32(block + 12, s3); -} - -void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { - int r; - u32 s0, s1, s2, s3, t0, t1, t2, t3; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(block ) ^ rk[0]; - s1 = GETU32(block + 4) ^ rk[1]; - s2 = GETU32(block + 8) ^ rk[2]; - s3 = GETU32(block + 12) ^ rk[3]; - rk += 4; - - /* - * Nr - 1 full rounds: - */ - for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) { - t0 = - Td0[(s0 >> 24) ] ^ - Td1[(s3 >> 16) & 0xff] ^ - Td2[(s2 >> 8) & 0xff] ^ - Td3[(s1 ) & 0xff] ^ - rk[0]; - t1 = - Td0[(s1 >> 24) ] ^ - Td1[(s0 >> 16) & 0xff] ^ - Td2[(s3 >> 8) & 0xff] ^ - Td3[(s2 ) & 0xff] ^ - rk[1]; - t2 = - Td0[(s2 >> 24) ] ^ - Td1[(s1 >> 16) & 0xff] ^ - Td2[(s0 >> 8) & 0xff] ^ - Td3[(s3 ) & 0xff] ^ - rk[2]; - t3 = - Td0[(s3 >> 24) ] ^ - Td1[(s2 >> 16) & 0xff] ^ - Td2[(s1 >> 8) & 0xff] ^ - Td3[(s0 ) & 0xff] ^ - rk[3]; - - s0 = t0; - s1 = t1; - s2 = t2; - s3 = t3; - rk += 4; - - } - - /* - * complete the last round and - * map cipher state to byte array block: - */ - t0 = - (Td4[(s0 >> 24) ] & 0xff000000) ^ - (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(s1 ) & 0xff] & 0x000000ff); - t1 = - (Td4[(s1 >> 24) ] & 0xff000000) ^ - (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(s2 ) & 0xff] & 0x000000ff); - t2 = - (Td4[(s2 >> 24) ] & 0xff000000) ^ - (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(s3 ) & 0xff] & 0x000000ff); - t3 = - (Td4[(s3 >> 24) ] & 0xff000000) ^ - (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(s0 ) & 0xff] & 0x000000ff); - - if (rounds == Nr) { - t0 ^= rk[0]; - t1 ^= rk[1]; - t2 ^= rk[2]; - t3 ^= rk[3]; - } - - PUTU32(block , t0); - PUTU32(block + 4, t1); - PUTU32(block + 8, t2); - PUTU32(block + 12, t3); -} - -#endif /* INTERMEDIATE_VALUE_KAT */ - -static void block_init(block_state *state, unsigned char *key, - int keylen) -{ - int Nr = 0; - - if (keylen != 16 && keylen != 24 && keylen != 32) { - PyErr_SetString(PyExc_ValueError, - "AES key must be either 16, 24, or 32 bytes long"); - return; - } - switch (keylen) { - case(16): Nr = 10; break; - case(24): Nr = 12; break; - case(32): Nr = 14; break; - } - state->rounds = Nr; - rijndaelKeySetupEnc(state->ek, key, keylen*8); - rijndaelKeySetupDec(state->dk, key, keylen*8); -} - -static void block_encrypt(block_state *self, u8 *in, u8 *out) -{ - rijndaelEncrypt(self->ek, self->rounds, in, out); -} - -static void block_decrypt(block_state *self, u8 *in, u8 *out) -{ - rijndaelDecrypt(self->dk, self->rounds, in, out); -} - -#include "block_template.c" diff --git a/Crypto/src/ARC2.c b/Crypto/src/ARC2.c deleted file mode 100644 index f1292e82..00000000 --- a/Crypto/src/ARC2.c +++ /dev/null @@ -1,185 +0,0 @@ - -/* - * rc2.c : Source code for the RC2 block cipher - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -#include - -#define MODULE_NAME ARC2 -#define BLOCK_SIZE 8 -#define KEY_SIZE 0 - -typedef unsigned int U32; -typedef unsigned short U16; -typedef unsigned char U8; - -typedef struct -{ - U16 xkey[64]; -} block_state; - -static void -block_encrypt(block_state *self, U8 *in, U8 *out) -{ - U16 x76, x54, x32, x10; - int i; - - x76 = (in[7] << 8) + in[6]; - x54 = (in[5] << 8) + in[4]; - x32 = (in[3] << 8) + in[2]; - x10 = (in[1] << 8) + in[0]; - - for (i = 0; i < 16; i++) - { - x10 += (x32 & ~x76) + (x54 & x76) + self->xkey[4*i+0]; - x10 = (x10 << 1) + (x10 >> 15 & 1); - - x32 += (x54 & ~x10) + (x76 & x10) + self->xkey[4*i+1]; - x32 = (x32 << 2) + (x32 >> 14 & 3); - - x54 += (x76 & ~x32) + (x10 & x32) + self->xkey[4*i+2]; - x54 = (x54 << 3) + (x54 >> 13 & 7); - - x76 += (x10 & ~x54) + (x32 & x54) + self->xkey[4*i+3]; - x76 = (x76 << 5) + (x76 >> 11 & 31); - - if (i == 4 || i == 10) { - x10 += self->xkey[x76 & 63]; - x32 += self->xkey[x10 & 63]; - x54 += self->xkey[x32 & 63]; - x76 += self->xkey[x54 & 63]; - } - } - - out[0] = (U8)x10; - out[1] = (U8)(x10 >> 8); - out[2] = (U8)x32; - out[3] = (U8)(x32 >> 8); - out[4] = (U8)x54; - out[5] = (U8)(x54 >> 8); - out[6] = (U8)x76; - out[7] = (U8)(x76 >> 8); -} - - -static void -block_decrypt(block_state *self, U8 *in, U8 *out) -{ - U16 x76, x54, x32, x10; - int i; - - x76 = (in[7] << 8) + in[6]; - x54 = (in[5] << 8) + in[4]; - x32 = (in[3] << 8) + in[2]; - x10 = (in[1] << 8) + in[0]; - - i = 15; - do { - x76 &= 65535; - x76 = (x76 << 11) + (x76 >> 5); - x76 -= (x10 & ~x54) + (x32 & x54) + self->xkey[4*i+3]; - - x54 &= 65535; - x54 = (x54 << 13) + (x54 >> 3); - x54 -= (x76 & ~x32) + (x10 & x32) + self->xkey[4*i+2]; - - x32 &= 65535; - x32 = (x32 << 14) + (x32 >> 2); - x32 -= (x54 & ~x10) + (x76 & x10) + self->xkey[4*i+1]; - - x10 &= 65535; - x10 = (x10 << 15) + (x10 >> 1); - x10 -= (x32 & ~x76) + (x54 & x76) + self->xkey[4*i+0]; - - if (i == 5 || i == 11) { - x76 -= self->xkey[x54 & 63]; - x54 -= self->xkey[x32 & 63]; - x32 -= self->xkey[x10 & 63]; - x10 -= self->xkey[x76 & 63]; - } - } while (i--); - - out[0] = (U8)x10; - out[1] = (U8)(x10 >> 8); - out[2] = (U8)x32; - out[3] = (U8)(x32 >> 8); - out[4] = (U8)x54; - out[5] = (U8)(x54 >> 8); - out[6] = (U8)x76; - out[7] = (U8)(x76 >> 8); -} - - -static void -block_init(block_state *self, U8 *key, int keylength) -{ - U8 x; - U16 i; - /* 256-entry permutation table, probably derived somehow from pi */ - static const U8 permute[256] = { - 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, - 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, - 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, - 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, - 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, - 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, - 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, - 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, - 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, - 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, - 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, - 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, - 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, - 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, - 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, - 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 - }; - - /* The "bits" value may be some sort of export control weakening. - We'll hardwire it to 1024. */ -#define bits 1024 - - memcpy(self->xkey, key, keylength); - - /* Phase 1: Expand input key to 128 bytes */ - if (keylength < 128) { - i = 0; - x = ((U8 *)self->xkey)[keylength-1]; - do { - x = permute[(x + ((U8 *)self->xkey)[i++]) & 255]; - ((U8 *)self->xkey)[keylength++] = x; - } while (keylength < 128); - } - - /* Phase 2 - reduce effective key size to "bits" */ - keylength = (bits+7) >> 3; - i = 128-keylength; - x = permute[((U8 *)self->xkey)[i] & (255 >> - (7 & - ((bits %8 ) ? 8-(bits%8): 0)) - )]; - ((U8 *)self->xkey)[i] = x; - - while (i--) { - x = permute[ x ^ ((U8 *)self->xkey)[i+keylength] ]; - ((U8 *)self->xkey)[i] = x; - } - - /* Phase 3 - copy to self->xkey in little-endian order */ - i = 63; - do { - self->xkey[i] = ((U8 *)self->xkey)[2*i] + - (((U8 *)self->xkey)[2*i+1] << 8); - } while (i--); -} - -#undef bits - -#include "block_template.c" diff --git a/Crypto/src/ARC4.c b/Crypto/src/ARC4.c deleted file mode 100644 index 71df6fe7..00000000 --- a/Crypto/src/ARC4.c +++ /dev/null @@ -1,72 +0,0 @@ - -/* - * arc4.c : Implementation for the Alleged-RC4 stream cipher - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -#define MODULE_NAME ARC4 -#define BLOCK_SIZE 1 -#define KEY_SIZE 0 - -typedef struct -{ - unsigned char state[256]; - unsigned char x,y; -} stream_state; - -/* Encryption and decryption are symmetric */ -#define stream_decrypt stream_encrypt - -static void stream_encrypt(stream_state *self, unsigned char *block, - int len) -{ - register int i, x=self->x, y=self->y; - - for (i=0; istate[x]) % 256; - { - register int t; /* Exchange state[x] and state[y] */ - t = self->state[x]; - self->state[x] = self->state[y]; - self->state[y] = t; - } - { - register int xorIndex; /* XOR the data with the stream data */ - xorIndex=(self->state[x]+self->state[y]) % 256; - block[i] ^= self->state[xorIndex]; - } - } - self->x=x; - self->y=y; -} - - -static void stream_init(stream_state *self, unsigned char *key, int keylen) -{ - register int i, index1, index2; - - for(i=0; i<256; i++) self->state[i]=i; - self->x=0; self->y=0; - index1=0; index2=0; - for(i=0; i<256; i++) - { - register int t; - index2 = ( key[index1] + self->state[i] + index2) % 256; - t = self->state[i]; - self->state[i] = self->state[index2]; - self->state[index2] = t; - index1 = (index1 + 1) % keylen; - } -} - -#include "stream_template.c" - - diff --git a/Crypto/src/Blowfish.c b/Crypto/src/Blowfish.c deleted file mode 100644 index df69afad..00000000 --- a/Crypto/src/Blowfish.c +++ /dev/null @@ -1,499 +0,0 @@ - -/* - * blowfish.c : Source code for the Blowfish block cipher - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -/*************************************************************************/ -/* File: bf.c - Blowfish cipher by Bruce Schneier, - Code by Bryan Olson, based partly on Schneier's. -*/ - -#include "Python.h" - -#define MODULE_NAME Blowfish -#define BLOCK_SIZE 8 -#define KEY_SIZE 0 - -/* Define IntU32 to be an unsigned in 32 bits long */ -typedef unsigned int IntU32 ; -typedef unsigned char IntU8 ; -#define NROUNDS 16 - - - -/* Define IntP to be an integer which - is the same size as a pointer. */ -typedef unsigned long IntP ; - - -typedef struct -{ - IntU32 p[2][NROUNDS+2], - sbox[4][256] ; -} BFkey_type ; - -typedef struct -{ - BFkey_type bfkey; -} block_state; - -/* File bfinit.h - Data to initialize P and S in BlowFish. -*/ - -static IntU32 p_init[NROUNDS+2] = -{ - 608135816UL, 2242054355UL, 320440878UL, 57701188UL, - 2752067618UL, 698298832UL, 137296536UL, 3964562569UL, - 1160258022UL, 953160567UL, 3193202383UL, 887688300UL, - 3232508343UL, 3380367581UL, 1065670069UL, 3041331479UL, - 2450970073UL, 2306472731UL -} ; - -static IntU32 s_init[4][256] = { - {3509652390UL, 2564797868UL, 805139163UL, 3491422135UL, - 3101798381UL, 1780907670UL, 3128725573UL, 4046225305UL, - 614570311UL, 3012652279UL, 134345442UL, 2240740374UL, - 1667834072UL, 1901547113UL, 2757295779UL, 4103290238UL, - 227898511UL, 1921955416UL, 1904987480UL, 2182433518UL, - 2069144605UL, 3260701109UL, 2620446009UL, 720527379UL, - 3318853667UL, 677414384UL, 3393288472UL, 3101374703UL, - 2390351024UL, 1614419982UL, 1822297739UL, 2954791486UL, - 3608508353UL, 3174124327UL, 2024746970UL, 1432378464UL, - 3864339955UL, 2857741204UL, 1464375394UL, 1676153920UL, - 1439316330UL, 715854006UL, 3033291828UL, 289532110UL, - 2706671279UL, 2087905683UL, 3018724369UL, 1668267050UL, - 732546397UL, 1947742710UL, 3462151702UL, 2609353502UL, - 2950085171UL, 1814351708UL, 2050118529UL, 680887927UL, - 999245976UL, 1800124847UL, 3300911131UL, 1713906067UL, - 1641548236UL, 4213287313UL, 1216130144UL, 1575780402UL, - 4018429277UL, 3917837745UL, 3693486850UL, 3949271944UL, - 596196993UL, 3549867205UL, 258830323UL, 2213823033UL, - 772490370UL, 2760122372UL, 1774776394UL, 2652871518UL, - 566650946UL, 4142492826UL, 1728879713UL, 2882767088UL, - 1783734482UL, 3629395816UL, 2517608232UL, 2874225571UL, - 1861159788UL, 326777828UL, 3124490320UL, 2130389656UL, - 2716951837UL, 967770486UL, 1724537150UL, 2185432712UL, - 2364442137UL, 1164943284UL, 2105845187UL, 998989502UL, - 3765401048UL, 2244026483UL, 1075463327UL, 1455516326UL, - 1322494562UL, 910128902UL, 469688178UL, 1117454909UL, - 936433444UL, 3490320968UL, 3675253459UL, 1240580251UL, - 122909385UL, 2157517691UL, 634681816UL, 4142456567UL, - 3825094682UL, 3061402683UL, 2540495037UL, 79693498UL, - 3249098678UL, 1084186820UL, 1583128258UL, 426386531UL, - 1761308591UL, 1047286709UL, 322548459UL, 995290223UL, - 1845252383UL, 2603652396UL, 3431023940UL, 2942221577UL, - 3202600964UL, 3727903485UL, 1712269319UL, 422464435UL, - 3234572375UL, 1170764815UL, 3523960633UL, 3117677531UL, - 1434042557UL, 442511882UL, 3600875718UL, 1076654713UL, - 1738483198UL, 4213154764UL, 2393238008UL, 3677496056UL, - 1014306527UL, 4251020053UL, 793779912UL, 2902807211UL, - 842905082UL, 4246964064UL, 1395751752UL, 1040244610UL, - 2656851899UL, 3396308128UL, 445077038UL, 3742853595UL, - 3577915638UL, 679411651UL, 2892444358UL, 2354009459UL, - 1767581616UL, 3150600392UL, 3791627101UL, 3102740896UL, - 284835224UL, 4246832056UL, 1258075500UL, 768725851UL, - 2589189241UL, 3069724005UL, 3532540348UL, 1274779536UL, - 3789419226UL, 2764799539UL, 1660621633UL, 3471099624UL, - 4011903706UL, 913787905UL, 3497959166UL, 737222580UL, - 2514213453UL, 2928710040UL, 3937242737UL, 1804850592UL, - 3499020752UL, 2949064160UL, 2386320175UL, 2390070455UL, - 2415321851UL, 4061277028UL, 2290661394UL, 2416832540UL, - 1336762016UL, 1754252060UL, 3520065937UL, 3014181293UL, - 791618072UL, 3188594551UL, 3933548030UL, 2332172193UL, - 3852520463UL, 3043980520UL, 413987798UL, 3465142937UL, - 3030929376UL, 4245938359UL, 2093235073UL, 3534596313UL, - 375366246UL, 2157278981UL, 2479649556UL, 555357303UL, - 3870105701UL, 2008414854UL, 3344188149UL, 4221384143UL, - 3956125452UL, 2067696032UL, 3594591187UL, 2921233993UL, - 2428461UL, 544322398UL, 577241275UL, 1471733935UL, - 610547355UL, 4027169054UL, 1432588573UL, 1507829418UL, - 2025931657UL, 3646575487UL, 545086370UL, 48609733UL, - 2200306550UL, 1653985193UL, 298326376UL, 1316178497UL, - 3007786442UL, 2064951626UL, 458293330UL, 2589141269UL, - 3591329599UL, 3164325604UL, 727753846UL, 2179363840UL, - 146436021UL, 1461446943UL, 4069977195UL, 705550613UL, - 3059967265UL, 3887724982UL, 4281599278UL, 3313849956UL, - 1404054877UL, 2845806497UL, 146425753UL, 1854211946UL}, - - { 1266315497UL, 3048417604UL, 3681880366UL, 3289982499UL, - 2909710000UL, 1235738493UL, 2632868024UL, 2414719590UL, - 3970600049UL, 1771706367UL, 1449415276UL, 3266420449UL, - 422970021UL, 1963543593UL, 2690192192UL, 3826793022UL, - 1062508698UL, 1531092325UL, 1804592342UL, 2583117782UL, - 2714934279UL, 4024971509UL, 1294809318UL, 4028980673UL, - 1289560198UL, 2221992742UL, 1669523910UL, 35572830UL, - 157838143UL, 1052438473UL, 1016535060UL, 1802137761UL, - 1753167236UL, 1386275462UL, 3080475397UL, 2857371447UL, - 1040679964UL, 2145300060UL, 2390574316UL, 1461121720UL, - 2956646967UL, 4031777805UL, 4028374788UL, 33600511UL, - 2920084762UL, 1018524850UL, 629373528UL, 3691585981UL, - 3515945977UL, 2091462646UL, 2486323059UL, 586499841UL, - 988145025UL, 935516892UL, 3367335476UL, 2599673255UL, - 2839830854UL, 265290510UL, 3972581182UL, 2759138881UL, - 3795373465UL, 1005194799UL, 847297441UL, 406762289UL, - 1314163512UL, 1332590856UL, 1866599683UL, 4127851711UL, - 750260880UL, 613907577UL, 1450815602UL, 3165620655UL, - 3734664991UL, 3650291728UL, 3012275730UL, 3704569646UL, - 1427272223UL, 778793252UL, 1343938022UL, 2676280711UL, - 2052605720UL, 1946737175UL, 3164576444UL, 3914038668UL, - 3967478842UL, 3682934266UL, 1661551462UL, 3294938066UL, - 4011595847UL, 840292616UL, 3712170807UL, 616741398UL, - 312560963UL, 711312465UL, 1351876610UL, 322626781UL, - 1910503582UL, 271666773UL, 2175563734UL, 1594956187UL, - 70604529UL, 3617834859UL, 1007753275UL, 1495573769UL, - 4069517037UL, 2549218298UL, 2663038764UL, 504708206UL, - 2263041392UL, 3941167025UL, 2249088522UL, 1514023603UL, - 1998579484UL, 1312622330UL, 694541497UL, 2582060303UL, - 2151582166UL, 1382467621UL, 776784248UL, 2618340202UL, - 3323268794UL, 2497899128UL, 2784771155UL, 503983604UL, - 4076293799UL, 907881277UL, 423175695UL, 432175456UL, - 1378068232UL, 4145222326UL, 3954048622UL, 3938656102UL, - 3820766613UL, 2793130115UL, 2977904593UL, 26017576UL, - 3274890735UL, 3194772133UL, 1700274565UL, 1756076034UL, - 4006520079UL, 3677328699UL, 720338349UL, 1533947780UL, - 354530856UL, 688349552UL, 3973924725UL, 1637815568UL, - 332179504UL, 3949051286UL, 53804574UL, 2852348879UL, - 3044236432UL, 1282449977UL, 3583942155UL, 3416972820UL, - 4006381244UL, 1617046695UL, 2628476075UL, 3002303598UL, - 1686838959UL, 431878346UL, 2686675385UL, 1700445008UL, - 1080580658UL, 1009431731UL, 832498133UL, 3223435511UL, - 2605976345UL, 2271191193UL, 2516031870UL, 1648197032UL, - 4164389018UL, 2548247927UL, 300782431UL, 375919233UL, - 238389289UL, 3353747414UL, 2531188641UL, 2019080857UL, - 1475708069UL, 455242339UL, 2609103871UL, 448939670UL, - 3451063019UL, 1395535956UL, 2413381860UL, 1841049896UL, - 1491858159UL, 885456874UL, 4264095073UL, 4001119347UL, - 1565136089UL, 3898914787UL, 1108368660UL, 540939232UL, - 1173283510UL, 2745871338UL, 3681308437UL, 4207628240UL, - 3343053890UL, 4016749493UL, 1699691293UL, 1103962373UL, - 3625875870UL, 2256883143UL, 3830138730UL, 1031889488UL, - 3479347698UL, 1535977030UL, 4236805024UL, 3251091107UL, - 2132092099UL, 1774941330UL, 1199868427UL, 1452454533UL, - 157007616UL, 2904115357UL, 342012276UL, 595725824UL, - 1480756522UL, 206960106UL, 497939518UL, 591360097UL, - 863170706UL, 2375253569UL, 3596610801UL, 1814182875UL, - 2094937945UL, 3421402208UL, 1082520231UL, 3463918190UL, - 2785509508UL, 435703966UL, 3908032597UL, 1641649973UL, - 2842273706UL, 3305899714UL, 1510255612UL, 2148256476UL, - 2655287854UL, 3276092548UL, 4258621189UL, 236887753UL, - 3681803219UL, 274041037UL, 1734335097UL, 3815195456UL, - 3317970021UL, 1899903192UL, 1026095262UL, 4050517792UL, - 356393447UL, 2410691914UL, 3873677099UL, 3682840055UL}, - - { 3913112168UL, 2491498743UL, 4132185628UL, 2489919796UL, - 1091903735UL, 1979897079UL, 3170134830UL, 3567386728UL, - 3557303409UL, 857797738UL, 1136121015UL, 1342202287UL, - 507115054UL, 2535736646UL, 337727348UL, 3213592640UL, - 1301675037UL, 2528481711UL, 1895095763UL, 1721773893UL, - 3216771564UL, 62756741UL, 2142006736UL, 835421444UL, - 2531993523UL, 1442658625UL, 3659876326UL, 2882144922UL, - 676362277UL, 1392781812UL, 170690266UL, 3921047035UL, - 1759253602UL, 3611846912UL, 1745797284UL, 664899054UL, - 1329594018UL, 3901205900UL, 3045908486UL, 2062866102UL, - 2865634940UL, 3543621612UL, 3464012697UL, 1080764994UL, - 553557557UL, 3656615353UL, 3996768171UL, 991055499UL, - 499776247UL, 1265440854UL, 648242737UL, 3940784050UL, - 980351604UL, 3713745714UL, 1749149687UL, 3396870395UL, - 4211799374UL, 3640570775UL, 1161844396UL, 3125318951UL, - 1431517754UL, 545492359UL, 4268468663UL, 3499529547UL, - 1437099964UL, 2702547544UL, 3433638243UL, 2581715763UL, - 2787789398UL, 1060185593UL, 1593081372UL, 2418618748UL, - 4260947970UL, 69676912UL, 2159744348UL, 86519011UL, - 2512459080UL, 3838209314UL, 1220612927UL, 3339683548UL, - 133810670UL, 1090789135UL, 1078426020UL, 1569222167UL, - 845107691UL, 3583754449UL, 4072456591UL, 1091646820UL, - 628848692UL, 1613405280UL, 3757631651UL, 526609435UL, - 236106946UL, 48312990UL, 2942717905UL, 3402727701UL, - 1797494240UL, 859738849UL, 992217954UL, 4005476642UL, - 2243076622UL, 3870952857UL, 3732016268UL, 765654824UL, - 3490871365UL, 2511836413UL, 1685915746UL, 3888969200UL, - 1414112111UL, 2273134842UL, 3281911079UL, 4080962846UL, - 172450625UL, 2569994100UL, 980381355UL, 4109958455UL, - 2819808352UL, 2716589560UL, 2568741196UL, 3681446669UL, - 3329971472UL, 1835478071UL, 660984891UL, 3704678404UL, - 4045999559UL, 3422617507UL, 3040415634UL, 1762651403UL, - 1719377915UL, 3470491036UL, 2693910283UL, 3642056355UL, - 3138596744UL, 1364962596UL, 2073328063UL, 1983633131UL, - 926494387UL, 3423689081UL, 2150032023UL, 4096667949UL, - 1749200295UL, 3328846651UL, 309677260UL, 2016342300UL, - 1779581495UL, 3079819751UL, 111262694UL, 1274766160UL, - 443224088UL, 298511866UL, 1025883608UL, 3806446537UL, - 1145181785UL, 168956806UL, 3641502830UL, 3584813610UL, - 1689216846UL, 3666258015UL, 3200248200UL, 1692713982UL, - 2646376535UL, 4042768518UL, 1618508792UL, 1610833997UL, - 3523052358UL, 4130873264UL, 2001055236UL, 3610705100UL, - 2202168115UL, 4028541809UL, 2961195399UL, 1006657119UL, - 2006996926UL, 3186142756UL, 1430667929UL, 3210227297UL, - 1314452623UL, 4074634658UL, 4101304120UL, 2273951170UL, - 1399257539UL, 3367210612UL, 3027628629UL, 1190975929UL, - 2062231137UL, 2333990788UL, 2221543033UL, 2438960610UL, - 1181637006UL, 548689776UL, 2362791313UL, 3372408396UL, - 3104550113UL, 3145860560UL, 296247880UL, 1970579870UL, - 3078560182UL, 3769228297UL, 1714227617UL, 3291629107UL, - 3898220290UL, 166772364UL, 1251581989UL, 493813264UL, - 448347421UL, 195405023UL, 2709975567UL, 677966185UL, - 3703036547UL, 1463355134UL, 2715995803UL, 1338867538UL, - 1343315457UL, 2802222074UL, 2684532164UL, 233230375UL, - 2599980071UL, 2000651841UL, 3277868038UL, 1638401717UL, - 4028070440UL, 3237316320UL, 6314154UL, 819756386UL, - 300326615UL, 590932579UL, 1405279636UL, 3267499572UL, - 3150704214UL, 2428286686UL, 3959192993UL, 3461946742UL, - 1862657033UL, 1266418056UL, 963775037UL, 2089974820UL, - 2263052895UL, 1917689273UL, 448879540UL, 3550394620UL, - 3981727096UL, 150775221UL, 3627908307UL, 1303187396UL, - 508620638UL, 2975983352UL, 2726630617UL, 1817252668UL, - 1876281319UL, 1457606340UL, 908771278UL, 3720792119UL, - 3617206836UL, 2455994898UL, 1729034894UL, 1080033504UL}, - - { 976866871UL, 3556439503UL, 2881648439UL, 1522871579UL, - 1555064734UL, 1336096578UL, 3548522304UL, 2579274686UL, - 3574697629UL, 3205460757UL, 3593280638UL, 3338716283UL, - 3079412587UL, 564236357UL, 2993598910UL, 1781952180UL, - 1464380207UL, 3163844217UL, 3332601554UL, 1699332808UL, - 1393555694UL, 1183702653UL, 3581086237UL, 1288719814UL, - 691649499UL, 2847557200UL, 2895455976UL, 3193889540UL, - 2717570544UL, 1781354906UL, 1676643554UL, 2592534050UL, - 3230253752UL, 1126444790UL, 2770207658UL, 2633158820UL, - 2210423226UL, 2615765581UL, 2414155088UL, 3127139286UL, - 673620729UL, 2805611233UL, 1269405062UL, 4015350505UL, - 3341807571UL, 4149409754UL, 1057255273UL, 2012875353UL, - 2162469141UL, 2276492801UL, 2601117357UL, 993977747UL, - 3918593370UL, 2654263191UL, 753973209UL, 36408145UL, - 2530585658UL, 25011837UL, 3520020182UL, 2088578344UL, - 530523599UL, 2918365339UL, 1524020338UL, 1518925132UL, - 3760827505UL, 3759777254UL, 1202760957UL, 3985898139UL, - 3906192525UL, 674977740UL, 4174734889UL, 2031300136UL, - 2019492241UL, 3983892565UL, 4153806404UL, 3822280332UL, - 352677332UL, 2297720250UL, 60907813UL, 90501309UL, - 3286998549UL, 1016092578UL, 2535922412UL, 2839152426UL, - 457141659UL, 509813237UL, 4120667899UL, 652014361UL, - 1966332200UL, 2975202805UL, 55981186UL, 2327461051UL, - 676427537UL, 3255491064UL, 2882294119UL, 3433927263UL, - 1307055953UL, 942726286UL, 933058658UL, 2468411793UL, - 3933900994UL, 4215176142UL, 1361170020UL, 2001714738UL, - 2830558078UL, 3274259782UL, 1222529897UL, 1679025792UL, - 2729314320UL, 3714953764UL, 1770335741UL, 151462246UL, - 3013232138UL, 1682292957UL, 1483529935UL, 471910574UL, - 1539241949UL, 458788160UL, 3436315007UL, 1807016891UL, - 3718408830UL, 978976581UL, 1043663428UL, 3165965781UL, - 1927990952UL, 4200891579UL, 2372276910UL, 3208408903UL, - 3533431907UL, 1412390302UL, 2931980059UL, 4132332400UL, - 1947078029UL, 3881505623UL, 4168226417UL, 2941484381UL, - 1077988104UL, 1320477388UL, 886195818UL, 18198404UL, - 3786409000UL, 2509781533UL, 112762804UL, 3463356488UL, - 1866414978UL, 891333506UL, 18488651UL, 661792760UL, - 1628790961UL, 3885187036UL, 3141171499UL, 876946877UL, - 2693282273UL, 1372485963UL, 791857591UL, 2686433993UL, - 3759982718UL, 3167212022UL, 3472953795UL, 2716379847UL, - 445679433UL, 3561995674UL, 3504004811UL, 3574258232UL, - 54117162UL, 3331405415UL, 2381918588UL, 3769707343UL, - 4154350007UL, 1140177722UL, 4074052095UL, 668550556UL, - 3214352940UL, 367459370UL, 261225585UL, 2610173221UL, - 4209349473UL, 3468074219UL, 3265815641UL, 314222801UL, - 3066103646UL, 3808782860UL, 282218597UL, 3406013506UL, - 3773591054UL, 379116347UL, 1285071038UL, 846784868UL, - 2669647154UL, 3771962079UL, 3550491691UL, 2305946142UL, - 453669953UL, 1268987020UL, 3317592352UL, 3279303384UL, - 3744833421UL, 2610507566UL, 3859509063UL, 266596637UL, - 3847019092UL, 517658769UL, 3462560207UL, 3443424879UL, - 370717030UL, 4247526661UL, 2224018117UL, 4143653529UL, - 4112773975UL, 2788324899UL, 2477274417UL, 1456262402UL, - 2901442914UL, 1517677493UL, 1846949527UL, 2295493580UL, - 3734397586UL, 2176403920UL, 1280348187UL, 1908823572UL, - 3871786941UL, 846861322UL, 1172426758UL, 3287448474UL, - 3383383037UL, 1655181056UL, 3139813346UL, 901632758UL, - 1897031941UL, 2986607138UL, 3066810236UL, 3447102507UL, - 1393639104UL, 373351379UL, 950779232UL, 625454576UL, - 3124240540UL, 4148612726UL, 2007998917UL, 544563296UL, - 2244738638UL, 2330496472UL, 2058025392UL, 1291430526UL, - 424198748UL, 50039436UL, 29584100UL, 3605783033UL, - 2429876329UL, 2791104160UL, 1057563949UL, 3255363231UL, - 3075367218UL, 3463963227UL, 1469046755UL, 985887462UL} -} ; - -/* sLb(s,n) allows us to subsript s by byte offsets, which - allows us to avoid a subscript scaling. -*/ -#define sub(s,n) *((IntU32 *)((IntP)s+(n))) - -/* Below is one BlowFish round including the F function -*/ -#define bf_round(l,r,n) \ - l ^= P[n]; \ - r ^= ( (sub(S[0],l>>22 & 0x3fc) + sub(S[1],l>>14 & 0x3fc)) \ - ^ sub(S[2],l>>6 & 0x3fc) ) +S[3][l & 0xff] - - - -/* This function requires the block to be two 32 bit integers, in -whatever endian form the machine uses. On little endian machines -use crypt_8bytes() on user data. make_bfkey should call crypt_block -on either endian machine. Pass direction 0 to encrypt, 1 to decrypt. -*/ -static void crypt_block(IntU32 block[2], BFkey_type *bfkey, int direction) -{ - register IntU32 left, right, - (*S)[256], - *P ; - - left = block[0] ; right = block[1] ; - - S = bfkey->sbox ; - P = bfkey->p[direction] ; - - bf_round( left, right, 0 ) ; bf_round( right, left, 1 ) ; - bf_round( left, right, 2 ) ; bf_round( right, left, 3 ) ; - bf_round( left, right, 4 ) ; bf_round( right, left, 5 ) ; - bf_round( left, right, 6 ) ; bf_round( right, left, 7 ) ; - bf_round( left, right, 8 ) ; bf_round( right, left, 9 ) ; - bf_round( left, right, 10 ) ; bf_round( right, left, 11 ) ; - bf_round( left, right, 12 ) ; bf_round( right, left, 13 ) ; - bf_round( left, right, 14 ) ; bf_round( right, left, 15 ) ; - - left = left ^ P[NROUNDS] ; - right = right ^ P[NROUNDS+1] ; - block[0] = right ; - block[1] = left ; -} - -/* The following should be allignment and endian independent. - I have not tested it on a little-endian machine. - It takes the input block from source, and puts the output - in dest. They can be the same. It takes the same direction - parameter as crypt_block(). -*/ -static void crypt_8bytes(IntU8 *source, IntU8 *dest, BFkey_type *bfkey, - int direction) -{ - IntU32 block[2] ; - - block[0] = source[3] | source[2]<<8 | source[1]<<16 | source[0]<<24 ; - block[1] = source[7] | source[6]<<8 | source[5]<<16 | source[4]<<24 ; - - crypt_block( block, bfkey, direction ) ; - - dest[0]= block[0]>>24 ; - dest[1]= block[0]>>16 & 0xff ; - dest[2]= block[0]>>8 & 0xff ; - dest[3]= block[0] & 0xff ; - dest[4]= block[1]>>24 ; - dest[5]= block[1]>>16 & 0xff ; - dest[6]= block[1]>> 8 & 0xff ; - dest[7]= block[1] & 0xff ; -} - -/* make_bfkey() takes the address of the key data as a char*, - and the length of the key in bytes. It generates and returns - a pointer to an object of BFkey_type, which can be passed - to the crypt functions. It does some simple testing of the - init data and crypt routine, and returns 0 on error. -*/ -static void make_bfkey(unsigned char *key_string, int keylength, - BFkey_type *bfkey) -{ - int i, j, k ; - IntU32 dspace[2], - checksum=0 ; - - /* Copy constant initial data to P vector */ - for( i=0 ; ip[0][i] = p_init[i] ; - bfkey->p[1][NROUNDS+1-i] = p_init[i] ; - checksum = (checksum<<1 | checksum>>31)+p_init[i] ; - } - - /* Copy constant initial data to sboxes */ - for( i=0 ; i<4 ; ++i ) - for( j=0 ; j<256 ; ++j ) - { - bfkey->sbox[i][j] = s_init[i][j] ; - checksum = ((checksum*13)<<11 | (checksum*13)>>21) - + s_init[i][j] ; - } - - /* Test init data. */ - if( checksum != 0x55861a61 ) - { - PyErr_SetString(PyExc_SystemError, - "Blowfish: Bad initialization data"); - return; - } - - dspace[0] = 0 ; - dspace[1] = 0 ; - - /* Test the crypt_block() routine. */ - for( i=0 ; i<10 ; ++i ) - crypt_block( dspace, bfkey, 0 ) ; - checksum = dspace[0] ; - for( i=0 ; i<10 ; ++i ) - crypt_block( dspace, bfkey, 1 ) ; - if( (checksum!=0xaafe4ebd) || dspace[0] || dspace[1] ) - { - PyErr_SetString(PyExc_SystemError, - "Blowfish: Error in crypt_block routine"); - return; - } - - - /* Xor key string into encryption key vector */ - j = 0 ; - for (i=0 ; ip)[0][i] ^= data; - } - - - for (i = 0 ; ip[0][i] = dspace[0] ; - bfkey->p[1][NROUNDS+1-i] = dspace[0] ; - bfkey->p[0][i+1] = dspace[1] ; - bfkey->p[1][NROUNDS-i] = dspace[1] ; - } - - for ( i=0 ; i<4 ; ++i ) - for ( j=0 ; j<256 ; j+=2 ) - { - crypt_block( dspace, bfkey, 0 ) ; - bfkey->sbox[i][j] = dspace[0] ; - bfkey->sbox[i][j+1] = dspace[1] ; - } -} - - -static void -block_encrypt(block_state *self, unsigned char *in, unsigned char *out) -{ - crypt_8bytes(in, out, &(self->bfkey), 0); -} - - -static void -block_decrypt(block_state *self, unsigned char *in, unsigned char *out) -{ - crypt_8bytes(in, out, &(self->bfkey), 1); -} - -static void -block_init(block_state *self, unsigned char *key, int keylength) -{ - make_bfkey(key, keylength, &(self->bfkey)); -} - -#include "block_template.c" diff --git a/Crypto/src/CAST.c b/Crypto/src/CAST.c deleted file mode 100644 index 395318db..00000000 --- a/Crypto/src/CAST.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - cast.c -- implementation of CAST-128 (aka CAST5) as described in RFC2144 - - compile -DTEST to include main() which performs the tests - specified in RFC2144 - - Written by Wim Lewis based entirely on RFC2144. This code - is in the public domain. Consult your local laws for possible restrictions - on use, distribution, and import/export. RFC2144 states that this - algorithm "is available worldwide on a royalty-free basis for commercial - and non-commercial uses". - - This code is a pretty straightforward transliteration of the RFC into C. - It has not been optimized much at all: byte-order-independent arithmetic - operations are used where order-dependent pointer ops or unions might be - faster; the code could be rearranged to give the optimizer a better - chance to speed things up; etc. - - This code requires a vaguely ANSI-ish compiler. - - Tested with gcc 2.5.8 on i486, i586, i686, hp pa-risc, mc68040, sparc; - also with gcc 2.7.2 and (with minor changes) native Sun compiler on sparc - - History: - 21 Jul 1997: wiml : first working version & Python module -*/ - -#include "Python.h" - -#define MODULE_NAME CAST -#define BLOCK_SIZE 8 -#define KEY_SIZE 0 - -/* adjust these according to your compiler/platform. On some machines - uint32 will have to be a long. It's OK if uint32 is more than 32 bits. */ -typedef unsigned int uint32; -typedef unsigned char uint8; - -/* this struct probably belongs in cast.h */ -typedef struct { - /* masking and rotate keys */ - uint32 Km[16]; - uint8 Kr[16]; - /* number of rounds (depends on original unpadded keylength) */ - int rounds; -} block_state; - -/* these are the eight 32*256 S-boxes */ -#include "cast5.c" - -/* fetch a uint32 from an array of uint8s (with a given offset) */ -#define fetch(ptr, base) (((((( ptr[base]<< 8 ) | ptr[base+1] )<< 8 ) | ptr[base+2] )<< 8 ) | ptr[base+3]) - -/* this is the round function f(D, Km, Kr) */ -static uint32 castfunc(uint32 D, uint32 Kmi, uint8 Kri, int type) -{ - uint32 I, f; - short Ia, Ib, Ic, Id; - - switch(type) { - case 0: - I = (Kmi + D) ; - break; - case 1: - I = (Kmi ^ D) ; - break; - default: - case 2: - I = (Kmi - D) ; - break; - } - - I &= 0xFFFFFFFF; - I = ( I << Kri ) | ( I >> ( 32-Kri ) ); - Ia = ( I >> 24 ) & 0xFF; - Ib = ( I >> 16 ) & 0xFF; - Ic = ( I >> 8 ) & 0xFF; - Id = ( I ) & 0xFF; - - switch(type) { - case 0: - f = ((S1[Ia] ^ S2[Ib]) - S3[Ic]) + S4[Id]; - break; - case 1: - f = ((S1[Ia] - S2[Ib]) + S3[Ic]) ^ S4[Id]; - break; - default: - case 2: - f = ((S1[Ia] + S2[Ib]) ^ S3[Ic]) - S4[Id]; - break; - } - - return f; -} - -/* encrypts/decrypts one block of data according to the key schedule - pointed to by `key'. Encrypts if decrypt=0, otherwise decrypts. */ -static void castcrypt(block_state *key, uint8 *block, int decrypt) -{ - uint32 L, R, tmp, f; - uint32 Kmi; - uint8 Kri; - short functype, round; - - L = fetch(block, 0); - R = fetch(block, 4); - -/* printf("L0 = %08x R0 = %08x\n", L, R); */ - - for(round = 0; round < key->rounds; round ++) { - - if (!decrypt) { - Kmi = key->Km[round]; - Kri = key->Kr[round]; - functype = round % 3; - } else { - Kmi = key->Km[(key->rounds) - round - 1]; - Kri = key->Kr[(key->rounds) - round - 1]; - functype = (((key->rounds) - round - 1) % 3); - } - - f = castfunc(R, Kmi, Kri, functype); - - tmp = L; - L = R; - R = tmp ^ f; - -/* printf("L%d = %08x R%d = %08x\n", round+1, L, round+1, R); */ - } - - block[0] = ( R & 0xFF000000 ) >> 24; - block[1] = ( R & 0x00FF0000 ) >> 16; - block[2] = ( R & 0x0000FF00 ) >> 8; - block[3] = ( R & 0x000000FF ); - block[4] = ( L & 0xFF000000 ) >> 24; - block[5] = ( L & 0x00FF0000 ) >> 16; - block[6] = ( L & 0x0000FF00 ) >> 8; - block[7] = ( L & 0x000000FF ); -} - -/* fetch a uint8 from an array of uint32s */ -#define b(a,n) (((a)[n/4] >> (24-((n&3)*8))) & 0xFF) - -/* key schedule round functions */ - -#define XZRound(T, F, ki1, ki2, ki3, ki4, \ - si11, si12, si13, si14, si15,\ - si25,\ - si35,\ - si45 ) \ - T[0] = F[ki1] ^ S5[si11 ] ^ S6[si12 ] ^ S7[si13 ] ^ S8[si14 ] ^ S7[si15];\ - T[1] = F[ki2] ^ S5[b(T, 0)] ^ S6[b(T,2)] ^ S7[b(T, 1)] ^ S8[b(T,3)] ^ S8[si25];\ - T[2] = F[ki3] ^ S5[b(T, 7)] ^ S6[b(T,6)] ^ S7[b(T, 5)] ^ S8[b(T,4)] ^ S5[si35];\ - T[3] = F[ki4] ^ S5[b(T,10)] ^ S6[b(T,9)] ^ S7[b(T,11)] ^ S8[b(T,8)] ^ S6[si45]; - -#define zxround() XZRound(z, x, 0, 2, 3, 1, \ - b(x,13), b(x,15), b(x,12), b(x,14),\ - b(x, 8), b(x,10), b(x, 9), b(x,11)) - -#define xzround() XZRound(x, z, 2, 0, 1, 3, \ - b(z,5), b(z,7), b(z,4), b(z,6), \ - b(z,0), b(z,2), b(z,1), b(z,3)) - -#define Kround(T, base, F,\ - i11, i12, i13, i14, i15,\ - i21, i22, i23, i24, i25,\ - i31, i32, i33, i34, i35,\ - i41, i42, i43, i44, i45)\ - T[base+0] = S5[b(F,i11)] ^ S6[b(F,i12)] ^ S7[b(F,i13)] ^ S8[b(F,i14)] ^ S5[b(F,i15)];\ - T[base+1] = S5[b(F,i21)] ^ S6[b(F,i22)] ^ S7[b(F,i23)] ^ S8[b(F,i24)] ^ S6[b(F,i25)];\ - T[base+2] = S5[b(F,i31)] ^ S6[b(F,i32)] ^ S7[b(F,i33)] ^ S8[b(F,i34)] ^ S7[b(F,i35)];\ - T[base+3] = S5[b(F,i41)] ^ S6[b(F,i42)] ^ S7[b(F,i43)] ^ S8[b(F,i44)] ^ S8[b(F,i45)]; - -/* generates sixteen 32-bit subkeys based on a 4x32-bit input key; - modifies the input key *in as well. */ -static void schedulekeys_half(uint32 *in, uint32 *keys) -{ - uint32 x[4], z[4]; - - x[0] = in[0]; - x[1] = in[1]; - x[2] = in[2]; - x[3] = in[3]; - - zxround(); - Kround(keys, 0, z, - 8, 9, 7, 6, 2, - 10, 11, 5, 4, 6, - 12, 13, 3, 2, 9, - 14, 15, 1, 0, 12); - xzround(); - Kround(keys, 4, x, - 3, 2, 12, 13, 8, - 1, 0, 14, 15, 13, - 7, 6, 8, 9, 3, - 5, 4, 10, 11, 7); - zxround(); - Kround(keys, 8, z, - 3, 2, 12, 13, 9, - 1, 0, 14, 15, 12, - 7, 6, 8, 9, 2, - 5, 4, 10, 11, 6); - xzround(); - Kround(keys, 12, x, - 8, 9, 7, 6, 3, - 10, 11, 5, 4, 7, - 12, 13, 3, 2, 8, - 14, 15, 1, 0, 13); - - in[0] = x[0]; - in[1] = x[1]; - in[2] = x[2]; - in[3] = x[3]; -} - -/* generates a key schedule from an input key */ -static void castschedulekeys(block_state *schedule, uint8 *key, int keybytes) -{ - uint32 x[4]; - uint8 paddedkey[16]; - uint32 Kr_wide[16]; - int i; - - for(i = 0; i < keybytes; i++) - paddedkey[i] = key[i]; - for( ; i < 16 ; i++) - paddedkey[i] = 0; - - if (keybytes <= 10) - schedule->rounds = 12; - else - schedule->rounds = 16; - - x[0] = fetch(paddedkey, 0); - x[1] = fetch(paddedkey, 4); - x[2] = fetch(paddedkey, 8); - x[3] = fetch(paddedkey, 12); - - schedulekeys_half(x, schedule->Km); - schedulekeys_half(x, Kr_wide); - - for(i = 0; i < 16; i ++) { - /* The Kr[] subkeys are used for 32-bit circular shifts, - so we only need to keep them modulo 32 */ - schedule->Kr[i] = (uint8)(Kr_wide[i] & 0x1F); - } -} - -#ifdef TEST - -/* This performs a variety of encryptions and verifies that the results - match those specified in RFC2144 appendix B. Also verifies that - decryption restores the original data. */ - -#include - -static block_state sched; - -void encrypt(key, keylen, in, out) - uint8 *key; - int keylen; - uint8 *in, *out; -{ - int i; - uint8 k[16]; - - castschedulekeys(&sched, key, keylen); - - for(i = 0; i < 8; i++) - out[i] = in[i]; - castcrypt(&sched, out, 0); -} - -void tst(key, keylen, data, result) - uint8 *key; - int keylen; - uint8 *data, *result; -{ - uint8 d[8]; - int i; - - encrypt(key, keylen, data, d); - - for(i = 0; i < 8; i++) - if (d[i] != result[i]) - break; - - if (i == 8) { - printf("-- test ok (encrypt)\n"); - } else { - for(i = 0; i < 8; i++) - printf(" %02x", d[i]); - printf(" (computed)\n"); - for(i = 0; i < 8; i++) - printf(" %02x", result[i]); - printf(" (expected)\n"); - } - - /* uses key schedule already set up */ - castcrypt(&sched, d, 1); - if (bcmp(d, data, 8)) - printf(" test FAILED (decrypt)\n"); - else - printf(" test ok (decrypt)\n"); - -} - -uint8 key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, - 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; -uint8 data[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; - -/* expected results of encrypting the above with 128, 80, and 40 - bits of key length */ -uint8 out1[8] = { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; -uint8 out2[8] = { 0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B }; -uint8 out3[8] = { 0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E }; - -/* expected results of the "full maintenance test" */ -uint8 afinal[16] = { 0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6, - 0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92 }; -uint8 bfinal[16] = { 0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71, - 0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E }; - -main() -{ - /* Appendix B.1 : Single Plaintext-Key-Ciphertext Sets */ - tst(key, 16, data, out1); - tst(key, 10, data, out2); - tst(key, 5, data, out3); - - /* Appendix B.2 : Full Maintenance Test */ - { - uint8 abuf[16]; - uint8 bbuf[16]; - int i; - - bcopy(key, abuf, 16); - bcopy(key, bbuf, 16); - - printf("\nrunning full maintenance test...\n"); - - for(i = 0; i < 1000000; i++) { - castschedulekeys(&sched, bbuf, 16); - castcrypt(&sched, abuf, 0); - castcrypt(&sched, abuf+8, 0); - - castschedulekeys(&sched, abuf, 16); - castcrypt(&sched, bbuf, 0); - castcrypt(&sched, bbuf+8, 0); - - if (!(i % 10000)) { - fprintf(stdout, "\r%d%% ", i / 10000); - fflush(stdout); - } - } - - printf("\r \r"); - - for(i = 0; i < 16; i ++) - if (abuf[i] != afinal[i] || bbuf[i] != bfinal[i]) - break; - - if(i == 16) { - printf("-- full maintenance test ok\n"); - } else { - for(i = 0; i < 16; i++) - printf(" %02x", abuf[i]); - printf("\n"); - for(i = 0; i < 16; i++) - printf(" %02x", bbuf[i]); - printf("\n"); - } - - printf("running maintenance test in reverse...\n"); - for(i = 0; i < 1000000; i++) { - castschedulekeys(&sched, abuf, 16); - castcrypt(&sched, bbuf+8, 1); - castcrypt(&sched, bbuf, 1); - - castschedulekeys(&sched, bbuf, 16); - castcrypt(&sched, abuf+8, 1); - castcrypt(&sched, abuf, 1); - - if (!(i % 10000)) { - fprintf(stdout, "\r%d%% ", i / 10000); - fflush(stdout); - } - } - - printf("\r \r"); - if (bcmp(abuf, key, 16) || bcmp(bbuf, key, 16)) - printf("-- reverse maintenance test FAILED\n"); - else - printf("-- reverse maintenance test ok\n"); - } -} - -#endif - -static void -block_init(block_state *self, unsigned char *key, int keylength) -{ - /* presumably this will optimize out */ - if (sizeof(uint32) < 4 || sizeof(uint8) != 1) { - PyErr_SetString(PyExc_SystemError, - "CAST module compiled with bad typedefs!"); - } - - /* make sure the key length is within bounds */ - if (keylength < 5 || keylength > 16) { - PyErr_SetString(PyExc_ValueError, "CAST key must be " - "at least 5 bytes and no more than 16 bytes long"); - return; - } - - /* do the actual key schedule setup */ - castschedulekeys(self, key, keylength); -} - -static void -block_encrypt(block_state *self, unsigned char *in, - unsigned char *out) -{ - memcpy(out, in, 8); - castcrypt(self, out, 0); -} - -static void block_decrypt(block_state *self, - unsigned char *in, - unsigned char *out) -{ - memcpy(out, in, 8); - castcrypt(self, out, 1); -} - -#include "block_template.c" diff --git a/Crypto/src/DES.c b/Crypto/src/DES.c deleted file mode 100644 index e35699f5..00000000 --- a/Crypto/src/DES.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * des.c : Source code for the DES block cipher - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -#include "Python.h" - -/* des.c */ -/* Copyright (C) 1993 Eric Young */ -/* Integrated into the PCT by A.M. Kuchling, November 1994 */ - -#define MODULE_NAME DES -#define BLOCK_SIZE 8 -#define KEY_SIZE 8 - - -typedef unsigned char des_cblock[8]; - -/* ecb_enc.c */ -/* Copyright (C) 1993 Eric Young - see README for more details */ - -#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ - l|=((unsigned long)(*((c)++)))<< 8, \ - l|=((unsigned long)(*((c)++)))<<16, \ - l|=((unsigned long)(*((c)++)))<<24) - -/* NOTE - c is not incremented as per c2l */ -#define c2ln(c,l1,l2,n) { \ - c+=n; \ - l1=l2=0; \ - switch (n) { \ - case 8: l2|=((unsigned long)(*(--(c))))<<24; \ - case 7: l2|=((unsigned long)(*(--(c))))<<16; \ - case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ - case 5: l2|=((unsigned long)(*(--(c)))); \ - case 4: l1|=((unsigned long)(*(--(c))))<<24; \ - case 3: l1|=((unsigned long)(*(--(c))))<<16; \ - case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ - case 1: l1|=((unsigned long)(*(--(c)))); \ - } \ - } - -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff)) - -/* replacements for htonl and ntohl since I have no idea what to do - * when faced with machines with 8 byte longs. */ -#define HDRSIZE 4 - -#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ - l|=((unsigned long)(*((c)++)))<<16, \ - l|=((unsigned long)(*((c)++)))<< 8, \ - l|=((unsigned long)(*((c)++)))) - -#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - -/* NOTE - c is not incremented as per l2c */ -#define l2cn(l1,l2,c,n) { \ - c+=n; \ - switch (n) { \ - case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ - case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ - } \ - } - -#define D_ENCRYPT(L,R,S) \ - u=(R^s[S ]); \ - t=R^s[S+1]; \ - t=((t>>4)+(t<<28)); \ - L^= des_SPtrans[1][(t )&0x3f]| \ - des_SPtrans[3][(t>> 8)&0x3f]| \ - des_SPtrans[5][(t>>16)&0x3f]| \ - des_SPtrans[7][(t>>24)&0x3f]| \ - des_SPtrans[0][(u )&0x3f]| \ - des_SPtrans[2][(u>> 8)&0x3f]| \ - des_SPtrans[4][(u>>16)&0x3f]| \ - des_SPtrans[6][(u>>24)&0x3f]; - - /* IP and FP - * The problem is more of a geometric problem that random bit fiddling. - 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 - 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 - 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 - 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 - - 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 - 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 - 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 - 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 - - The output has been subject to swaps of the form - 0 1 -> 3 1 but the odd and even bits have been put into - 2 3 2 0 - different words. The main trick is to remember that - t=((l>>size)^r)&(mask); - r^=t; - l^=(t<>(n))^(b))&(m)),\ - (b)^=(t),\ - (a)^=((t)<<(n))) - - - -/* spr.h */ -/* Copyright (C) 1993 Eric Young - see README for more details */ -static unsigned long des_SPtrans[8][64]={ -/* nibble 0 */ - {0x00820200, 0x00020000, 0x80800000, 0x80820200, - 0x00800000, 0x80020200, 0x80020000, 0x80800000, - 0x80020200, 0x00820200, 0x00820000, 0x80000200, - 0x80800200, 0x00800000, 0x00000000, 0x80020000, - 0x00020000, 0x80000000, 0x00800200, 0x00020200, - 0x80820200, 0x00820000, 0x80000200, 0x00800200, - 0x80000000, 0x00000200, 0x00020200, 0x80820000, - 0x00000200, 0x80800200, 0x80820000, 0x00000000, - 0x00000000, 0x80820200, 0x00800200, 0x80020000, - 0x00820200, 0x00020000, 0x80000200, 0x00800200, - 0x80820000, 0x00000200, 0x00020200, 0x80800000, - 0x80020200, 0x80000000, 0x80800000, 0x00820000, - 0x80820200, 0x00020200, 0x00820000, 0x80800200, - 0x00800000, 0x80000200, 0x80020000, 0x00000000, - 0x00020000, 0x00800000, 0x80800200, 0x00820200, - 0x80000000, 0x80820000, 0x00000200, 0x80020200}, - -/* nibble 1 */ - {0x10042004, 0x00000000, 0x00042000, 0x10040000, - 0x10000004, 0x00002004, 0x10002000, 0x00042000, - 0x00002000, 0x10040004, 0x00000004, 0x10002000, - 0x00040004, 0x10042000, 0x10040000, 0x00000004, - 0x00040000, 0x10002004, 0x10040004, 0x00002000, - 0x00042004, 0x10000000, 0x00000000, 0x00040004, - 0x10002004, 0x00042004, 0x10042000, 0x10000004, - 0x10000000, 0x00040000, 0x00002004, 0x10042004, - 0x00040004, 0x10042000, 0x10002000, 0x00042004, - 0x10042004, 0x00040004, 0x10000004, 0x00000000, - 0x10000000, 0x00002004, 0x00040000, 0x10040004, - 0x00002000, 0x10000000, 0x00042004, 0x10002004, - 0x10042000, 0x00002000, 0x00000000, 0x10000004, - 0x00000004, 0x10042004, 0x00042000, 0x10040000, - 0x10040004, 0x00040000, 0x00002004, 0x10002000, - 0x10002004, 0x00000004, 0x10040000, 0x00042000}, - -/* nibble 2 */ - {0x41000000, 0x01010040, 0x00000040, 0x41000040, - 0x40010000, 0x01000000, 0x41000040, 0x00010040, - 0x01000040, 0x00010000, 0x01010000, 0x40000000, - 0x41010040, 0x40000040, 0x40000000, 0x41010000, - 0x00000000, 0x40010000, 0x01010040, 0x00000040, - 0x40000040, 0x41010040, 0x00010000, 0x41000000, - 0x41010000, 0x01000040, 0x40010040, 0x01010000, - 0x00010040, 0x00000000, 0x01000000, 0x40010040, - 0x01010040, 0x00000040, 0x40000000, 0x00010000, - 0x40000040, 0x40010000, 0x01010000, 0x41000040, - 0x00000000, 0x01010040, 0x00010040, 0x41010000, - 0x40010000, 0x01000000, 0x41010040, 0x40000000, - 0x40010040, 0x41000000, 0x01000000, 0x41010040, - 0x00010000, 0x01000040, 0x41000040, 0x00010040, - 0x01000040, 0x00000000, 0x41010000, 0x40000040, - 0x41000000, 0x40010040, 0x00000040, 0x01010000}, - -/* nibble 3 */ - {0x00100402, 0x04000400, 0x00000002, 0x04100402, - 0x00000000, 0x04100000, 0x04000402, 0x00100002, - 0x04100400, 0x04000002, 0x04000000, 0x00000402, - 0x04000002, 0x00100402, 0x00100000, 0x04000000, - 0x04100002, 0x00100400, 0x00000400, 0x00000002, - 0x00100400, 0x04000402, 0x04100000, 0x00000400, - 0x00000402, 0x00000000, 0x00100002, 0x04100400, - 0x04000400, 0x04100002, 0x04100402, 0x00100000, - 0x04100002, 0x00000402, 0x00100000, 0x04000002, - 0x00100400, 0x04000400, 0x00000002, 0x04100000, - 0x04000402, 0x00000000, 0x00000400, 0x00100002, - 0x00000000, 0x04100002, 0x04100400, 0x00000400, - 0x04000000, 0x04100402, 0x00100402, 0x00100000, - 0x04100402, 0x00000002, 0x04000400, 0x00100402, - 0x00100002, 0x00100400, 0x04100000, 0x04000402, - 0x00000402, 0x04000000, 0x04000002, 0x04100400}, - -/* nibble 4 */ - {0x02000000, 0x00004000, 0x00000100, 0x02004108, - 0x02004008, 0x02000100, 0x00004108, 0x02004000, - 0x00004000, 0x00000008, 0x02000008, 0x00004100, - 0x02000108, 0x02004008, 0x02004100, 0x00000000, - 0x00004100, 0x02000000, 0x00004008, 0x00000108, - 0x02000100, 0x00004108, 0x00000000, 0x02000008, - 0x00000008, 0x02000108, 0x02004108, 0x00004008, - 0x02004000, 0x00000100, 0x00000108, 0x02004100, - 0x02004100, 0x02000108, 0x00004008, 0x02004000, - 0x00004000, 0x00000008, 0x02000008, 0x02000100, - 0x02000000, 0x00004100, 0x02004108, 0x00000000, - 0x00004108, 0x02000000, 0x00000100, 0x00004008, - 0x02000108, 0x00000100, 0x00000000, 0x02004108, - 0x02004008, 0x02004100, 0x00000108, 0x00004000, - 0x00004100, 0x02004008, 0x02000100, 0x00000108, - 0x00000008, 0x00004108, 0x02004000, 0x02000008}, - -/* nibble 5 */ - {0x20000010, 0x00080010, 0x00000000, 0x20080800, - 0x00080010, 0x00000800, 0x20000810, 0x00080000, - 0x00000810, 0x20080810, 0x00080800, 0x20000000, - 0x20000800, 0x20000010, 0x20080000, 0x00080810, - 0x00080000, 0x20000810, 0x20080010, 0x00000000, - 0x00000800, 0x00000010, 0x20080800, 0x20080010, - 0x20080810, 0x20080000, 0x20000000, 0x00000810, - 0x00000010, 0x00080800, 0x00080810, 0x20000800, - 0x00000810, 0x20000000, 0x20000800, 0x00080810, - 0x20080800, 0x00080010, 0x00000000, 0x20000800, - 0x20000000, 0x00000800, 0x20080010, 0x00080000, - 0x00080010, 0x20080810, 0x00080800, 0x00000010, - 0x20080810, 0x00080800, 0x00080000, 0x20000810, - 0x20000010, 0x20080000, 0x00080810, 0x00000000, - 0x00000800, 0x20000010, 0x20000810, 0x20080800, - 0x20080000, 0x00000810, 0x00000010, 0x20080010}, - -/* nibble 6 */ - {0x00001000, 0x00000080, 0x00400080, 0x00400001, - 0x00401081, 0x00001001, 0x00001080, 0x00000000, - 0x00400000, 0x00400081, 0x00000081, 0x00401000, - 0x00000001, 0x00401080, 0x00401000, 0x00000081, - 0x00400081, 0x00001000, 0x00001001, 0x00401081, - 0x00000000, 0x00400080, 0x00400001, 0x00001080, - 0x00401001, 0x00001081, 0x00401080, 0x00000001, - 0x00001081, 0x00401001, 0x00000080, 0x00400000, - 0x00001081, 0x00401000, 0x00401001, 0x00000081, - 0x00001000, 0x00000080, 0x00400000, 0x00401001, - 0x00400081, 0x00001081, 0x00001080, 0x00000000, - 0x00000080, 0x00400001, 0x00000001, 0x00400080, - 0x00000000, 0x00400081, 0x00400080, 0x00001080, - 0x00000081, 0x00001000, 0x00401081, 0x00400000, - 0x00401080, 0x00000001, 0x00001001, 0x00401081, - 0x00400001, 0x00401080, 0x00401000, 0x00001001}, - -/* nibble 7 */ - {0x08200020, 0x08208000, 0x00008020, 0x00000000, - 0x08008000, 0x00200020, 0x08200000, 0x08208020, - 0x00000020, 0x08000000, 0x00208000, 0x00008020, - 0x00208020, 0x08008020, 0x08000020, 0x08200000, - 0x00008000, 0x00208020, 0x00200020, 0x08008000, - 0x08208020, 0x08000020, 0x00000000, 0x00208000, - 0x08000000, 0x00200000, 0x08008020, 0x08200020, - 0x00200000, 0x00008000, 0x08208000, 0x00000020, - 0x00200000, 0x00008000, 0x08000020, 0x08208020, - 0x00008020, 0x08000000, 0x00000000, 0x00208000, - 0x08200020, 0x08008020, 0x08008000, 0x00200020, - 0x08208000, 0x00000020, 0x00200020, 0x08008000, - 0x08208020, 0x00200000, 0x08200000, 0x08000020, - 0x00208000, 0x00008020, 0x08008020, 0x08200000, - 0x00000020, 0x08208000, 0x00208020, 0x00000000, - 0x08000000, 0x08200020, 0x00008000, 0x00208020}}; - -static unsigned long des_skb[8][64]={ -/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ - {0x00000000,0x00000010,0x20000000,0x20000010, - 0x00010000,0x00010010,0x20010000,0x20010010, - 0x00000800,0x00000810,0x20000800,0x20000810, - 0x00010800,0x00010810,0x20010800,0x20010810, - 0x00000020,0x00000030,0x20000020,0x20000030, - 0x00010020,0x00010030,0x20010020,0x20010030, - 0x00000820,0x00000830,0x20000820,0x20000830, - 0x00010820,0x00010830,0x20010820,0x20010830, - 0x00080000,0x00080010,0x20080000,0x20080010, - 0x00090000,0x00090010,0x20090000,0x20090010, - 0x00080800,0x00080810,0x20080800,0x20080810, - 0x00090800,0x00090810,0x20090800,0x20090810, - 0x00080020,0x00080030,0x20080020,0x20080030, - 0x00090020,0x00090030,0x20090020,0x20090030, - 0x00080820,0x00080830,0x20080820,0x20080830, - 0x00090820,0x00090830,0x20090820,0x20090830}, -/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ - {0x00000000,0x02000000,0x00002000,0x02002000, - 0x00200000,0x02200000,0x00202000,0x02202000, - 0x00000004,0x02000004,0x00002004,0x02002004, - 0x00200004,0x02200004,0x00202004,0x02202004, - 0x00000400,0x02000400,0x00002400,0x02002400, - 0x00200400,0x02200400,0x00202400,0x02202400, - 0x00000404,0x02000404,0x00002404,0x02002404, - 0x00200404,0x02200404,0x00202404,0x02202404, - 0x10000000,0x12000000,0x10002000,0x12002000, - 0x10200000,0x12200000,0x10202000,0x12202000, - 0x10000004,0x12000004,0x10002004,0x12002004, - 0x10200004,0x12200004,0x10202004,0x12202004, - 0x10000400,0x12000400,0x10002400,0x12002400, - 0x10200400,0x12200400,0x10202400,0x12202400, - 0x10000404,0x12000404,0x10002404,0x12002404, - 0x10200404,0x12200404,0x10202404,0x12202404}, -/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ - {0x00000000,0x00000001,0x00040000,0x00040001, - 0x01000000,0x01000001,0x01040000,0x01040001, - 0x00000002,0x00000003,0x00040002,0x00040003, - 0x01000002,0x01000003,0x01040002,0x01040003, - 0x00000200,0x00000201,0x00040200,0x00040201, - 0x01000200,0x01000201,0x01040200,0x01040201, - 0x00000202,0x00000203,0x00040202,0x00040203, - 0x01000202,0x01000203,0x01040202,0x01040203, - 0x08000000,0x08000001,0x08040000,0x08040001, - 0x09000000,0x09000001,0x09040000,0x09040001, - 0x08000002,0x08000003,0x08040002,0x08040003, - 0x09000002,0x09000003,0x09040002,0x09040003, - 0x08000200,0x08000201,0x08040200,0x08040201, - 0x09000200,0x09000201,0x09040200,0x09040201, - 0x08000202,0x08000203,0x08040202,0x08040203, - 0x09000202,0x09000203,0x09040202,0x09040203}, -/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ - {0x00000000,0x00100000,0x00000100,0x00100100, - 0x00000008,0x00100008,0x00000108,0x00100108, - 0x00001000,0x00101000,0x00001100,0x00101100, - 0x00001008,0x00101008,0x00001108,0x00101108, - 0x04000000,0x04100000,0x04000100,0x04100100, - 0x04000008,0x04100008,0x04000108,0x04100108, - 0x04001000,0x04101000,0x04001100,0x04101100, - 0x04001008,0x04101008,0x04001108,0x04101108, - 0x00020000,0x00120000,0x00020100,0x00120100, - 0x00020008,0x00120008,0x00020108,0x00120108, - 0x00021000,0x00121000,0x00021100,0x00121100, - 0x00021008,0x00121008,0x00021108,0x00121108, - 0x04020000,0x04120000,0x04020100,0x04120100, - 0x04020008,0x04120008,0x04020108,0x04120108, - 0x04021000,0x04121000,0x04021100,0x04121100, - 0x04021008,0x04121008,0x04021108,0x04121108}, -/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ - {0x00000000,0x10000000,0x00010000,0x10010000, - 0x00000004,0x10000004,0x00010004,0x10010004, - 0x20000000,0x30000000,0x20010000,0x30010000, - 0x20000004,0x30000004,0x20010004,0x30010004, - 0x00100000,0x10100000,0x00110000,0x10110000, - 0x00100004,0x10100004,0x00110004,0x10110004, - 0x20100000,0x30100000,0x20110000,0x30110000, - 0x20100004,0x30100004,0x20110004,0x30110004, - 0x00001000,0x10001000,0x00011000,0x10011000, - 0x00001004,0x10001004,0x00011004,0x10011004, - 0x20001000,0x30001000,0x20011000,0x30011000, - 0x20001004,0x30001004,0x20011004,0x30011004, - 0x00101000,0x10101000,0x00111000,0x10111000, - 0x00101004,0x10101004,0x00111004,0x10111004, - 0x20101000,0x30101000,0x20111000,0x30111000, - 0x20101004,0x30101004,0x20111004,0x30111004}, -/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ - {0x00000000,0x08000000,0x00000008,0x08000008, - 0x00000400,0x08000400,0x00000408,0x08000408, - 0x00020000,0x08020000,0x00020008,0x08020008, - 0x00020400,0x08020400,0x00020408,0x08020408, - 0x00000001,0x08000001,0x00000009,0x08000009, - 0x00000401,0x08000401,0x00000409,0x08000409, - 0x00020001,0x08020001,0x00020009,0x08020009, - 0x00020401,0x08020401,0x00020409,0x08020409, - 0x02000000,0x0A000000,0x02000008,0x0A000008, - 0x02000400,0x0A000400,0x02000408,0x0A000408, - 0x02020000,0x0A020000,0x02020008,0x0A020008, - 0x02020400,0x0A020400,0x02020408,0x0A020408, - 0x02000001,0x0A000001,0x02000009,0x0A000009, - 0x02000401,0x0A000401,0x02000409,0x0A000409, - 0x02020001,0x0A020001,0x02020009,0x0A020009, - 0x02020401,0x0A020401,0x02020409,0x0A020409}, -/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ - {0x00000000,0x00000100,0x00080000,0x00080100, - 0x01000000,0x01000100,0x01080000,0x01080100, - 0x00000010,0x00000110,0x00080010,0x00080110, - 0x01000010,0x01000110,0x01080010,0x01080110, - 0x00200000,0x00200100,0x00280000,0x00280100, - 0x01200000,0x01200100,0x01280000,0x01280100, - 0x00200010,0x00200110,0x00280010,0x00280110, - 0x01200010,0x01200110,0x01280010,0x01280110, - 0x00000200,0x00000300,0x00080200,0x00080300, - 0x01000200,0x01000300,0x01080200,0x01080300, - 0x00000210,0x00000310,0x00080210,0x00080310, - 0x01000210,0x01000310,0x01080210,0x01080310, - 0x00200200,0x00200300,0x00280200,0x00280300, - 0x01200200,0x01200300,0x01280200,0x01280300, - 0x00200210,0x00200310,0x00280210,0x00280310, - 0x01200210,0x01200310,0x01280210,0x01280310}, -/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ - {0x00000000,0x04000000,0x00040000,0x04040000, - 0x00000002,0x04000002,0x00040002,0x04040002, - 0x00002000,0x04002000,0x00042000,0x04042000, - 0x00002002,0x04002002,0x00042002,0x04042002, - 0x00000020,0x04000020,0x00040020,0x04040020, - 0x00000022,0x04000022,0x00040022,0x04040022, - 0x00002020,0x04002020,0x00042020,0x04042020, - 0x00002022,0x04002022,0x00042022,0x04042022, - 0x00000800,0x04000800,0x00040800,0x04040800, - 0x00000802,0x04000802,0x00040802,0x04040802, - 0x00002800,0x04002800,0x00042800,0x04042800, - 0x00002802,0x04002802,0x00042802,0x04042802, - 0x00000820,0x04000820,0x00040820,0x04040820, - 0x00000822,0x04000822,0x00040822,0x04040822, - 0x00002820,0x04002820,0x00042820,0x04042820, - 0x00002822,0x04002822,0x00042822,0x04042822} -}; - -typedef struct des_ks_struct -{ - union { - des_cblock _; - /* make sure things are correct size on machines with - * 8 byte longs */ - unsigned long pad[2]; - } ks; -#define _ ks._ -} block_state[16]; - -static int des_encrypt(unsigned long *input, unsigned long *output, - block_state ks, int encrypt) -{ - unsigned long l,r,t,u; - int i; - unsigned long *s; - - l=input[0]; - r=input[1]; - - /* do IP */ - PERM_OP(r,l,t, 4,0x0f0f0f0f); - PERM_OP(l,r,t,16,0x0000ffff); - PERM_OP(r,l,t, 2,0x33333333); - PERM_OP(l,r,t, 8,0x00ff00ff); - PERM_OP(r,l,t, 1,0x55555555); - /* r and l are reversed - remember that :-) - fix - * it in the next step */ - - /* Things have been modified so that the initial rotate is - * done outside the loop. This required the - * des_SPtrans values in sp.h to be rotated 1 bit to the right. - * One perl script later and things have a 5% speed up on a sparc2. - * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> - * for pointing this out. */ - t=(r<<1)|(r>>31); - r=(l<<1)|(l>>31); - l=t; - - /* clear the top bits on machines with 8byte longs */ - l&=0xffffffff; - r&=0xffffffff; - - s=(unsigned long *)ks; - /* I don't know if it is worth the effort of loop unrolling the - * inner loop */ - if (encrypt) - { - for (i=0; i<32; i+=4) - { - D_ENCRYPT(l,r,i+0); /* 1 */ - D_ENCRYPT(r,l,i+2); /* 2 */ - } - } - else - { - for (i=30; i>0; i-=4) - { - D_ENCRYPT(l,r,i-0); /* 16 */ - D_ENCRYPT(r,l,i-2); /* 15 */ - } - } - l=(l>>1)|(l<<31); - r=(r>>1)|(r<<31); - /* clear the top bits on machines with 8byte longs */ - l&=0xffffffff; - r&=0xffffffff; - - /* swap l and r - * we will not do the swap so just remember they are - * reversed for the rest of the subroutine - * luckily FP fixes this problem :-) */ - - PERM_OP(r,l,t, 1,0x55555555); - PERM_OP(l,r,t, 8,0x00ff00ff); - PERM_OP(r,l,t, 2,0x33333333); - PERM_OP(l,r,t,16,0x0000ffff); - PERM_OP(r,l,t, 4,0x0f0f0f0f); - - output[0]=l; - output[1]=r; - l=r=t=u=0; - return(0); -} - -static int des_ecb_encrypt(des_cblock *input, des_cblock *output, - block_state ks, int encrypt) -{ - register unsigned long l0,l1; - register unsigned char *in,*out; - unsigned long ll[2]; - - in=(unsigned char *)input; - out=(unsigned char *)output; - c2l(in,l0); - c2l(in,l1); - ll[0]=l0; - ll[1]=l1; - des_encrypt(ll,ll,ks,encrypt); - l0=ll[0]; - l1=ll[1]; - l2c(l0,out); - l2c(l1,out); - l0=l1=ll[0]=ll[1]=0; - return(0); -} - - - -static void block_decrypt(block_state *state, - unsigned char *in, - unsigned char *out) -{ - des_ecb_encrypt((des_cblock *)in, (des_cblock *)out, *state, 0); -} - -static void block_encrypt(block_state *state, - unsigned char *in, - unsigned char *out) -{ - des_ecb_encrypt((des_cblock *)in, (des_cblock *)out, *state, 1); -} - -/* NOW DEFINED IN des_local.h - * See ecb_encrypt.c for a pseudo description of these macros. - * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ - * (b)^=(t),\ - * (a)=((a)^((t)<<(n)))) - */ - -#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ - (a)=(a)^(t)^(t>>(16-(n)))) - -static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; - -/* return 0 if key parity is odd (correct), - * return -1 if key parity error, - * return -2 if illegal weak key. - */ -static int des_set_key(des_cblock *key, block_state schedule) -{ - register unsigned long c,d,t,s; - register unsigned char *in; - register unsigned long *k; - register int i; - - k=(unsigned long *)schedule; - in=(unsigned char *)key; - - c2l(in,c); - c2l(in,d); - - /* do PC1 in 60 simple operations */ -/* PERM_OP(d,c,t,4,0x0f0f0f0f); - HPERM_OP(c,t,-2, 0xcccc0000); - HPERM_OP(c,t,-1, 0xaaaa0000); - HPERM_OP(c,t, 8, 0x00ff0000); - HPERM_OP(c,t,-1, 0xaaaa0000); - HPERM_OP(d,t,-8, 0xff000000); - HPERM_OP(d,t, 8, 0x00ff0000); - HPERM_OP(d,t, 2, 0x33330000); - d=((d&0x00aa00aa)<<7)|((d&0x55005500)>>7)|(d&0xaa55aa55); - d=(d>>8)|((c&0xf0000000)>>4); - c&=0x0fffffff; */ - - /* I now do it in 47 simple operations :-) - * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) - * for the inspiration. :-) */ - PERM_OP (d,c,t,4,0x0f0f0f0f); - HPERM_OP(c,t,-2,0xcccc0000); - HPERM_OP(d,t,-2,0xcccc0000); - PERM_OP (d,c,t,1,0x55555555); - PERM_OP (c,d,t,8,0x00ff00ff); - PERM_OP (d,c,t,1,0x55555555); - d= (((d&0x000000ff)<<16)| (d&0x0000ff00) | - ((d&0x00ff0000)>>16)|((c&0xf0000000)>>4)); - c&=0x0fffffff; - - for (i=0; i<16; i++) - { - if (shifts2[i]) - { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); } - else - { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); } - c&=0x0fffffff; - d&=0x0fffffff; - /* could be a few less shifts but I am to lazy at this - * point in time to investigate */ - s= des_skb[0][ (c )&0x3f ]| - des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]| - des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]| - des_skb[3][((c>>20)&0x01)|((c>>21)&0x06) | - ((c>>22)&0x38)]; - t= des_skb[4][ (d )&0x3f ]| - des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]| - des_skb[6][ (d>>15)&0x3f ]| - des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)]; - - /* table contained 0213 4657 */ - *(k++)=((t<<16)|(s&0x0000ffff))&0xffffffff; - s= ((s>>16)|(t&0xffff0000)); - - s=(s<<4)|(s>>28); - *(k++)=s&0xffffffff; - } - return(0); -} - -static const unsigned char odd_parity[256]={ - 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, - 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, - 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, - 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, - 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, - 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, - 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, - 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, - 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, - 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, - 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, - 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, - 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, - 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, - 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, - 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; - -static void block_init(block_state *state, unsigned char *key, - int keylen) -{ - char oddkey[8]; - int i; - - for (i=0; i<8; i++) - { - oddkey[i]=odd_parity[ key[i] ]; - } - des_set_key((des_cblock *)oddkey, *state); -} - -#include "block_template.c" diff --git a/Crypto/src/DES3.c b/Crypto/src/DES3.c deleted file mode 100644 index 49bf6f48..00000000 --- a/Crypto/src/DES3.c +++ /dev/null @@ -1,688 +0,0 @@ - -/* - * des.c : Source code for the DES block cipher - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -/* des.c */ -/* Copyright (C) 1993 Eric Young */ -/* Integrated into the PCT by A.M. Kuchling, November 1994 */ -/* Fully independent key mode added by Wim Lewis, July 1997 */ - -#include "Python.h" - -#define MODULE_NAME DES3 -#define BLOCK_SIZE 8 -#define KEY_SIZE 0 - -typedef unsigned char des_cblock[8]; - -/* ecb_enc.c */ -/* Copyright (C) 1993 Eric Young - see README for more details */ - -#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ - l|=((unsigned long)(*((c)++)))<< 8, \ - l|=((unsigned long)(*((c)++)))<<16, \ - l|=((unsigned long)(*((c)++)))<<24) - -/* NOTE - c is not incremented as per c2l */ -#define c2ln(c,l1,l2,n) { \ - c+=n; \ - l1=l2=0; \ - switch (n) { \ - case 8: l2|=((unsigned long)(*(--(c))))<<24; \ - case 7: l2|=((unsigned long)(*(--(c))))<<16; \ - case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ - case 5: l2|=((unsigned long)(*(--(c)))); \ - case 4: l1|=((unsigned long)(*(--(c))))<<24; \ - case 3: l1|=((unsigned long)(*(--(c))))<<16; \ - case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ - case 1: l1|=((unsigned long)(*(--(c)))); \ - } \ - } - -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff)) - -/* replacements for htonl and ntohl since I have no idea what to do - * when faced with machines with 8 byte longs. */ -#define HDRSIZE 4 - -#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ - l|=((unsigned long)(*((c)++)))<<16, \ - l|=((unsigned long)(*((c)++)))<< 8, \ - l|=((unsigned long)(*((c)++)))) - -#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - -/* NOTE - c is not incremented as per l2c */ -#define l2cn(l1,l2,c,n) { \ - c+=n; \ - switch (n) { \ - case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ - case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ - } \ - } - -#define D_ENCRYPT(L,R,S) \ - u=(R^s[S ]); \ - t=R^s[S+1]; \ - t=((t>>4)+(t<<28)); \ - L^= des_SPtrans[1][(t )&0x3f]| \ - des_SPtrans[3][(t>> 8)&0x3f]| \ - des_SPtrans[5][(t>>16)&0x3f]| \ - des_SPtrans[7][(t>>24)&0x3f]| \ - des_SPtrans[0][(u )&0x3f]| \ - des_SPtrans[2][(u>> 8)&0x3f]| \ - des_SPtrans[4][(u>>16)&0x3f]| \ - des_SPtrans[6][(u>>24)&0x3f]; - - /* IP and FP - * The problem is more of a geometric problem that random bit fiddling. - 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 - 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 - 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 - 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 - - 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 - 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 - 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 - 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 - - The output has been subject to swaps of the form - 0 1 -> 3 1 but the odd and even bits have been put into - 2 3 2 0 - different words. The main trick is to remember that - t=((l>>size)^r)&(mask); - r^=t; - l^=(t<>(n))^(b))&(m)),\ - (b)^=(t),\ - (a)^=((t)<<(n))) - - - -/* spr.h */ -/* Copyright (C) 1993 Eric Young - see README for more details */ -static unsigned long des_SPtrans[8][64]={ -/* nibble 0 */ - {0x00820200, 0x00020000, 0x80800000, 0x80820200, - 0x00800000, 0x80020200, 0x80020000, 0x80800000, - 0x80020200, 0x00820200, 0x00820000, 0x80000200, - 0x80800200, 0x00800000, 0x00000000, 0x80020000, - 0x00020000, 0x80000000, 0x00800200, 0x00020200, - 0x80820200, 0x00820000, 0x80000200, 0x00800200, - 0x80000000, 0x00000200, 0x00020200, 0x80820000, - 0x00000200, 0x80800200, 0x80820000, 0x00000000, - 0x00000000, 0x80820200, 0x00800200, 0x80020000, - 0x00820200, 0x00020000, 0x80000200, 0x00800200, - 0x80820000, 0x00000200, 0x00020200, 0x80800000, - 0x80020200, 0x80000000, 0x80800000, 0x00820000, - 0x80820200, 0x00020200, 0x00820000, 0x80800200, - 0x00800000, 0x80000200, 0x80020000, 0x00000000, - 0x00020000, 0x00800000, 0x80800200, 0x00820200, - 0x80000000, 0x80820000, 0x00000200, 0x80020200}, - -/* nibble 1 */ - {0x10042004, 0x00000000, 0x00042000, 0x10040000, - 0x10000004, 0x00002004, 0x10002000, 0x00042000, - 0x00002000, 0x10040004, 0x00000004, 0x10002000, - 0x00040004, 0x10042000, 0x10040000, 0x00000004, - 0x00040000, 0x10002004, 0x10040004, 0x00002000, - 0x00042004, 0x10000000, 0x00000000, 0x00040004, - 0x10002004, 0x00042004, 0x10042000, 0x10000004, - 0x10000000, 0x00040000, 0x00002004, 0x10042004, - 0x00040004, 0x10042000, 0x10002000, 0x00042004, - 0x10042004, 0x00040004, 0x10000004, 0x00000000, - 0x10000000, 0x00002004, 0x00040000, 0x10040004, - 0x00002000, 0x10000000, 0x00042004, 0x10002004, - 0x10042000, 0x00002000, 0x00000000, 0x10000004, - 0x00000004, 0x10042004, 0x00042000, 0x10040000, - 0x10040004, 0x00040000, 0x00002004, 0x10002000, - 0x10002004, 0x00000004, 0x10040000, 0x00042000}, - -/* nibble 2 */ - {0x41000000, 0x01010040, 0x00000040, 0x41000040, - 0x40010000, 0x01000000, 0x41000040, 0x00010040, - 0x01000040, 0x00010000, 0x01010000, 0x40000000, - 0x41010040, 0x40000040, 0x40000000, 0x41010000, - 0x00000000, 0x40010000, 0x01010040, 0x00000040, - 0x40000040, 0x41010040, 0x00010000, 0x41000000, - 0x41010000, 0x01000040, 0x40010040, 0x01010000, - 0x00010040, 0x00000000, 0x01000000, 0x40010040, - 0x01010040, 0x00000040, 0x40000000, 0x00010000, - 0x40000040, 0x40010000, 0x01010000, 0x41000040, - 0x00000000, 0x01010040, 0x00010040, 0x41010000, - 0x40010000, 0x01000000, 0x41010040, 0x40000000, - 0x40010040, 0x41000000, 0x01000000, 0x41010040, - 0x00010000, 0x01000040, 0x41000040, 0x00010040, - 0x01000040, 0x00000000, 0x41010000, 0x40000040, - 0x41000000, 0x40010040, 0x00000040, 0x01010000}, - -/* nibble 3 */ - {0x00100402, 0x04000400, 0x00000002, 0x04100402, - 0x00000000, 0x04100000, 0x04000402, 0x00100002, - 0x04100400, 0x04000002, 0x04000000, 0x00000402, - 0x04000002, 0x00100402, 0x00100000, 0x04000000, - 0x04100002, 0x00100400, 0x00000400, 0x00000002, - 0x00100400, 0x04000402, 0x04100000, 0x00000400, - 0x00000402, 0x00000000, 0x00100002, 0x04100400, - 0x04000400, 0x04100002, 0x04100402, 0x00100000, - 0x04100002, 0x00000402, 0x00100000, 0x04000002, - 0x00100400, 0x04000400, 0x00000002, 0x04100000, - 0x04000402, 0x00000000, 0x00000400, 0x00100002, - 0x00000000, 0x04100002, 0x04100400, 0x00000400, - 0x04000000, 0x04100402, 0x00100402, 0x00100000, - 0x04100402, 0x00000002, 0x04000400, 0x00100402, - 0x00100002, 0x00100400, 0x04100000, 0x04000402, - 0x00000402, 0x04000000, 0x04000002, 0x04100400}, - -/* nibble 4 */ - {0x02000000, 0x00004000, 0x00000100, 0x02004108, - 0x02004008, 0x02000100, 0x00004108, 0x02004000, - 0x00004000, 0x00000008, 0x02000008, 0x00004100, - 0x02000108, 0x02004008, 0x02004100, 0x00000000, - 0x00004100, 0x02000000, 0x00004008, 0x00000108, - 0x02000100, 0x00004108, 0x00000000, 0x02000008, - 0x00000008, 0x02000108, 0x02004108, 0x00004008, - 0x02004000, 0x00000100, 0x00000108, 0x02004100, - 0x02004100, 0x02000108, 0x00004008, 0x02004000, - 0x00004000, 0x00000008, 0x02000008, 0x02000100, - 0x02000000, 0x00004100, 0x02004108, 0x00000000, - 0x00004108, 0x02000000, 0x00000100, 0x00004008, - 0x02000108, 0x00000100, 0x00000000, 0x02004108, - 0x02004008, 0x02004100, 0x00000108, 0x00004000, - 0x00004100, 0x02004008, 0x02000100, 0x00000108, - 0x00000008, 0x00004108, 0x02004000, 0x02000008}, - -/* nibble 5 */ - {0x20000010, 0x00080010, 0x00000000, 0x20080800, - 0x00080010, 0x00000800, 0x20000810, 0x00080000, - 0x00000810, 0x20080810, 0x00080800, 0x20000000, - 0x20000800, 0x20000010, 0x20080000, 0x00080810, - 0x00080000, 0x20000810, 0x20080010, 0x00000000, - 0x00000800, 0x00000010, 0x20080800, 0x20080010, - 0x20080810, 0x20080000, 0x20000000, 0x00000810, - 0x00000010, 0x00080800, 0x00080810, 0x20000800, - 0x00000810, 0x20000000, 0x20000800, 0x00080810, - 0x20080800, 0x00080010, 0x00000000, 0x20000800, - 0x20000000, 0x00000800, 0x20080010, 0x00080000, - 0x00080010, 0x20080810, 0x00080800, 0x00000010, - 0x20080810, 0x00080800, 0x00080000, 0x20000810, - 0x20000010, 0x20080000, 0x00080810, 0x00000000, - 0x00000800, 0x20000010, 0x20000810, 0x20080800, - 0x20080000, 0x00000810, 0x00000010, 0x20080010}, - -/* nibble 6 */ - {0x00001000, 0x00000080, 0x00400080, 0x00400001, - 0x00401081, 0x00001001, 0x00001080, 0x00000000, - 0x00400000, 0x00400081, 0x00000081, 0x00401000, - 0x00000001, 0x00401080, 0x00401000, 0x00000081, - 0x00400081, 0x00001000, 0x00001001, 0x00401081, - 0x00000000, 0x00400080, 0x00400001, 0x00001080, - 0x00401001, 0x00001081, 0x00401080, 0x00000001, - 0x00001081, 0x00401001, 0x00000080, 0x00400000, - 0x00001081, 0x00401000, 0x00401001, 0x00000081, - 0x00001000, 0x00000080, 0x00400000, 0x00401001, - 0x00400081, 0x00001081, 0x00001080, 0x00000000, - 0x00000080, 0x00400001, 0x00000001, 0x00400080, - 0x00000000, 0x00400081, 0x00400080, 0x00001080, - 0x00000081, 0x00001000, 0x00401081, 0x00400000, - 0x00401080, 0x00000001, 0x00001001, 0x00401081, - 0x00400001, 0x00401080, 0x00401000, 0x00001001}, - -/* nibble 7 */ - {0x08200020, 0x08208000, 0x00008020, 0x00000000, - 0x08008000, 0x00200020, 0x08200000, 0x08208020, - 0x00000020, 0x08000000, 0x00208000, 0x00008020, - 0x00208020, 0x08008020, 0x08000020, 0x08200000, - 0x00008000, 0x00208020, 0x00200020, 0x08008000, - 0x08208020, 0x08000020, 0x00000000, 0x00208000, - 0x08000000, 0x00200000, 0x08008020, 0x08200020, - 0x00200000, 0x00008000, 0x08208000, 0x00000020, - 0x00200000, 0x00008000, 0x08000020, 0x08208020, - 0x00008020, 0x08000000, 0x00000000, 0x00208000, - 0x08200020, 0x08008020, 0x08008000, 0x00200020, - 0x08208000, 0x00000020, 0x00200020, 0x08008000, - 0x08208020, 0x00200000, 0x08200000, 0x08000020, - 0x00208000, 0x00008020, 0x08008020, 0x08200000, - 0x00000020, 0x08208000, 0x00208020, 0x00000000, - 0x08000000, 0x08200020, 0x00008000, 0x00208020}}; - -static unsigned long des_skb[8][64]={ -/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ - {0x00000000,0x00000010,0x20000000,0x20000010, - 0x00010000,0x00010010,0x20010000,0x20010010, - 0x00000800,0x00000810,0x20000800,0x20000810, - 0x00010800,0x00010810,0x20010800,0x20010810, - 0x00000020,0x00000030,0x20000020,0x20000030, - 0x00010020,0x00010030,0x20010020,0x20010030, - 0x00000820,0x00000830,0x20000820,0x20000830, - 0x00010820,0x00010830,0x20010820,0x20010830, - 0x00080000,0x00080010,0x20080000,0x20080010, - 0x00090000,0x00090010,0x20090000,0x20090010, - 0x00080800,0x00080810,0x20080800,0x20080810, - 0x00090800,0x00090810,0x20090800,0x20090810, - 0x00080020,0x00080030,0x20080020,0x20080030, - 0x00090020,0x00090030,0x20090020,0x20090030, - 0x00080820,0x00080830,0x20080820,0x20080830, - 0x00090820,0x00090830,0x20090820,0x20090830}, -/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ - {0x00000000,0x02000000,0x00002000,0x02002000, - 0x00200000,0x02200000,0x00202000,0x02202000, - 0x00000004,0x02000004,0x00002004,0x02002004, - 0x00200004,0x02200004,0x00202004,0x02202004, - 0x00000400,0x02000400,0x00002400,0x02002400, - 0x00200400,0x02200400,0x00202400,0x02202400, - 0x00000404,0x02000404,0x00002404,0x02002404, - 0x00200404,0x02200404,0x00202404,0x02202404, - 0x10000000,0x12000000,0x10002000,0x12002000, - 0x10200000,0x12200000,0x10202000,0x12202000, - 0x10000004,0x12000004,0x10002004,0x12002004, - 0x10200004,0x12200004,0x10202004,0x12202004, - 0x10000400,0x12000400,0x10002400,0x12002400, - 0x10200400,0x12200400,0x10202400,0x12202400, - 0x10000404,0x12000404,0x10002404,0x12002404, - 0x10200404,0x12200404,0x10202404,0x12202404}, -/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ - {0x00000000,0x00000001,0x00040000,0x00040001, - 0x01000000,0x01000001,0x01040000,0x01040001, - 0x00000002,0x00000003,0x00040002,0x00040003, - 0x01000002,0x01000003,0x01040002,0x01040003, - 0x00000200,0x00000201,0x00040200,0x00040201, - 0x01000200,0x01000201,0x01040200,0x01040201, - 0x00000202,0x00000203,0x00040202,0x00040203, - 0x01000202,0x01000203,0x01040202,0x01040203, - 0x08000000,0x08000001,0x08040000,0x08040001, - 0x09000000,0x09000001,0x09040000,0x09040001, - 0x08000002,0x08000003,0x08040002,0x08040003, - 0x09000002,0x09000003,0x09040002,0x09040003, - 0x08000200,0x08000201,0x08040200,0x08040201, - 0x09000200,0x09000201,0x09040200,0x09040201, - 0x08000202,0x08000203,0x08040202,0x08040203, - 0x09000202,0x09000203,0x09040202,0x09040203}, -/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ - {0x00000000,0x00100000,0x00000100,0x00100100, - 0x00000008,0x00100008,0x00000108,0x00100108, - 0x00001000,0x00101000,0x00001100,0x00101100, - 0x00001008,0x00101008,0x00001108,0x00101108, - 0x04000000,0x04100000,0x04000100,0x04100100, - 0x04000008,0x04100008,0x04000108,0x04100108, - 0x04001000,0x04101000,0x04001100,0x04101100, - 0x04001008,0x04101008,0x04001108,0x04101108, - 0x00020000,0x00120000,0x00020100,0x00120100, - 0x00020008,0x00120008,0x00020108,0x00120108, - 0x00021000,0x00121000,0x00021100,0x00121100, - 0x00021008,0x00121008,0x00021108,0x00121108, - 0x04020000,0x04120000,0x04020100,0x04120100, - 0x04020008,0x04120008,0x04020108,0x04120108, - 0x04021000,0x04121000,0x04021100,0x04121100, - 0x04021008,0x04121008,0x04021108,0x04121108}, -/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ - {0x00000000,0x10000000,0x00010000,0x10010000, - 0x00000004,0x10000004,0x00010004,0x10010004, - 0x20000000,0x30000000,0x20010000,0x30010000, - 0x20000004,0x30000004,0x20010004,0x30010004, - 0x00100000,0x10100000,0x00110000,0x10110000, - 0x00100004,0x10100004,0x00110004,0x10110004, - 0x20100000,0x30100000,0x20110000,0x30110000, - 0x20100004,0x30100004,0x20110004,0x30110004, - 0x00001000,0x10001000,0x00011000,0x10011000, - 0x00001004,0x10001004,0x00011004,0x10011004, - 0x20001000,0x30001000,0x20011000,0x30011000, - 0x20001004,0x30001004,0x20011004,0x30011004, - 0x00101000,0x10101000,0x00111000,0x10111000, - 0x00101004,0x10101004,0x00111004,0x10111004, - 0x20101000,0x30101000,0x20111000,0x30111000, - 0x20101004,0x30101004,0x20111004,0x30111004}, -/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ - {0x00000000,0x08000000,0x00000008,0x08000008, - 0x00000400,0x08000400,0x00000408,0x08000408, - 0x00020000,0x08020000,0x00020008,0x08020008, - 0x00020400,0x08020400,0x00020408,0x08020408, - 0x00000001,0x08000001,0x00000009,0x08000009, - 0x00000401,0x08000401,0x00000409,0x08000409, - 0x00020001,0x08020001,0x00020009,0x08020009, - 0x00020401,0x08020401,0x00020409,0x08020409, - 0x02000000,0x0A000000,0x02000008,0x0A000008, - 0x02000400,0x0A000400,0x02000408,0x0A000408, - 0x02020000,0x0A020000,0x02020008,0x0A020008, - 0x02020400,0x0A020400,0x02020408,0x0A020408, - 0x02000001,0x0A000001,0x02000009,0x0A000009, - 0x02000401,0x0A000401,0x02000409,0x0A000409, - 0x02020001,0x0A020001,0x02020009,0x0A020009, - 0x02020401,0x0A020401,0x02020409,0x0A020409}, -/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ - {0x00000000,0x00000100,0x00080000,0x00080100, - 0x01000000,0x01000100,0x01080000,0x01080100, - 0x00000010,0x00000110,0x00080010,0x00080110, - 0x01000010,0x01000110,0x01080010,0x01080110, - 0x00200000,0x00200100,0x00280000,0x00280100, - 0x01200000,0x01200100,0x01280000,0x01280100, - 0x00200010,0x00200110,0x00280010,0x00280110, - 0x01200010,0x01200110,0x01280010,0x01280110, - 0x00000200,0x00000300,0x00080200,0x00080300, - 0x01000200,0x01000300,0x01080200,0x01080300, - 0x00000210,0x00000310,0x00080210,0x00080310, - 0x01000210,0x01000310,0x01080210,0x01080310, - 0x00200200,0x00200300,0x00280200,0x00280300, - 0x01200200,0x01200300,0x01280200,0x01280300, - 0x00200210,0x00200310,0x00280210,0x00280310, - 0x01200210,0x01200310,0x01280210,0x01280310}, -/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ - {0x00000000,0x04000000,0x00040000,0x04040000, - 0x00000002,0x04000002,0x00040002,0x04040002, - 0x00002000,0x04002000,0x00042000,0x04042000, - 0x00002002,0x04002002,0x00042002,0x04042002, - 0x00000020,0x04000020,0x00040020,0x04040020, - 0x00000022,0x04000022,0x00040022,0x04040022, - 0x00002020,0x04002020,0x00042020,0x04042020, - 0x00002022,0x04002022,0x00042022,0x04042022, - 0x00000800,0x04000800,0x00040800,0x04040800, - 0x00000802,0x04000802,0x00040802,0x04040802, - 0x00002800,0x04002800,0x00042800,0x04042800, - 0x00002802,0x04002802,0x00042802,0x04042802, - 0x00000820,0x04000820,0x00040820,0x04040820, - 0x00000822,0x04000822,0x00040822,0x04040822, - 0x00002820,0x04002820,0x00042820,0x04042820, - 0x00002822,0x04002822,0x00042822,0x04042822} -}; - -typedef struct des_ks_struct -{ - union { - des_cblock _; - /* make sure things are correct size on machines with - * 8 byte longs */ - unsigned long pad[2]; - } ks; -#define _ ks._ -} des_key_schedule[16]; - -typedef struct -{ - des_key_schedule KeySched1, KeySched2, KeySched3; -} block_state; - -static int des_encrypt(unsigned long *input, unsigned long *output, - des_key_schedule ks, int encrypt) -{ - register unsigned long l,r,t,u; - register int i; - register unsigned long *s; - - l=input[0]; - r=input[1]; - - /* do IP */ - PERM_OP(r,l,t, 4,0x0f0f0f0f); - PERM_OP(l,r,t,16,0x0000ffff); - PERM_OP(r,l,t, 2,0x33333333); - PERM_OP(l,r,t, 8,0x00ff00ff); - PERM_OP(r,l,t, 1,0x55555555); - /* r and l are reversed - remember that :-) - fix - * it in the next step */ - - /* Things have been modified so that the initial rotate is - * done outside the loop. This required the - * des_SPtrans values in sp.h to be rotated 1 bit to the right. - * One perl script later and things have a 5% speed up on a sparc2. - * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> - * for pointing this out. */ - t=(r<<1)|(r>>31); - r=(l<<1)|(l>>31); - l=t; - - /* clear the top bits on machines with 8byte longs */ - l&=0xffffffff; - r&=0xffffffff; - - s=(unsigned long *)ks; - /* I don't know if it is worth the effort of loop unrolling the - * inner loop */ - if (encrypt) - { - for (i=0; i<32; i+=4) - { - D_ENCRYPT(l,r,i+0); /* 1 */ - D_ENCRYPT(r,l,i+2); /* 2 */ - } - } - else - { - for (i=30; i>0; i-=4) - { - D_ENCRYPT(l,r,i-0); /* 16 */ - D_ENCRYPT(r,l,i-2); /* 15 */ - } - } - l=(l>>1)|(l<<31); - r=(r>>1)|(r<<31); - /* clear the top bits on machines with 8byte longs */ - l&=0xffffffff; - r&=0xffffffff; - - /* swap l and r - * we will not do the swap so just remember they are - * reversed for the rest of the subroutine - * luckily FP fixes this problem :-) */ - - PERM_OP(r,l,t, 1,0x55555555); - PERM_OP(l,r,t, 8,0x00ff00ff); - PERM_OP(r,l,t, 2,0x33333333); - PERM_OP(l,r,t,16,0x0000ffff); - PERM_OP(r,l,t, 4,0x0f0f0f0f); - - output[0]=l; - output[1]=r; - l=r=t=u=0; - return(0); -} - -static int des_ecb_encrypt(des_cblock *input, des_cblock *output, - des_key_schedule ks, int encrypt) -{ - register unsigned long l0,l1; - register unsigned char *in,*out; - unsigned long ll[2]; - - in=(unsigned char *)input; - out=(unsigned char *)output; - c2l(in,l0); - c2l(in,l1); - ll[0]=l0; - ll[1]=l1; - des_encrypt(ll,ll,ks,encrypt); - l0=ll[0]; - l1=ll[1]; - l2c(l0,out); - l2c(l1,out); - l0=l1=ll[0]=ll[1]=0; - return(0); -} - - - -static void block_decrypt(block_state *self, - unsigned char *in, - unsigned char *out) -{ - des_cblock output, output2; - - des_ecb_encrypt((des_cblock *)in, &output, self->KeySched3, 0); - des_ecb_encrypt(&output, &output2, self->KeySched2, 1); - des_ecb_encrypt(&output2, (des_cblock *)out, self->KeySched1, 0); -} - -static void block_encrypt(block_state *self, - unsigned char *in, - unsigned char *out) -{ - des_cblock output, output2; - - des_ecb_encrypt((des_cblock *)in, &output, self->KeySched1, 1); - des_ecb_encrypt(&output, &output2, self->KeySched2, 0); - des_ecb_encrypt(&output2, (des_cblock *)out, self->KeySched3, 1); -} - -/* NOW DEFINED IN des_local.h - * See ecb_encrypt.c for a pseudo description of these macros. - * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ - * (b)^=(t),\ - * (a)=((a)^((t)<<(n)))) - */ - -#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ - (a)=(a)^(t)^(t>>(16-(n)))) - -static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; - -static int des_set_key(des_cblock *key, des_key_schedule schedule) -{ - register unsigned long c,d,t,s; - register unsigned char *in; - register unsigned long *k; - register int i; - - k=(unsigned long *)schedule; - in=(unsigned char *)key; - - c2l(in,c); - c2l(in,d); - - /* do PC1 in 60 simple operations */ -/* PERM_OP(d,c,t,4,0x0f0f0f0f); - HPERM_OP(c,t,-2, 0xcccc0000); - HPERM_OP(c,t,-1, 0xaaaa0000); - HPERM_OP(c,t, 8, 0x00ff0000); - HPERM_OP(c,t,-1, 0xaaaa0000); - HPERM_OP(d,t,-8, 0xff000000); - HPERM_OP(d,t, 8, 0x00ff0000); - HPERM_OP(d,t, 2, 0x33330000); - d=((d&0x00aa00aa)<<7)|((d&0x55005500)>>7)|(d&0xaa55aa55); - d=(d>>8)|((c&0xf0000000)>>4); - c&=0x0fffffff; */ - - /* I now do it in 47 simple operations :-) - * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) - * for the inspiration. :-) */ - PERM_OP (d,c,t,4,0x0f0f0f0f); - HPERM_OP(c,t,-2,0xcccc0000); - HPERM_OP(d,t,-2,0xcccc0000); - PERM_OP (d,c,t,1,0x55555555); - PERM_OP (c,d,t,8,0x00ff00ff); - PERM_OP (d,c,t,1,0x55555555); - d= (((d&0x000000ff)<<16)| (d&0x0000ff00) | - ((d&0x00ff0000)>>16)|((c&0xf0000000)>>4)); - c&=0x0fffffff; - - for (i=0; i<16; i++) - { - if (shifts2[i]) - { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); } - else - { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); } - c&=0x0fffffff; - d&=0x0fffffff; - /* could be a few less shifts but I am to lazy at this - * point in time to investigate */ - s= des_skb[0][ (c )&0x3f ]| - des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]| - des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]| - des_skb[3][((c>>20)&0x01)|((c>>21)&0x06) | - ((c>>22)&0x38)]; - t= des_skb[4][ (d )&0x3f ]| - des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]| - des_skb[6][ (d>>15)&0x3f ]| - des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)]; - - /* table contained 0213 4657 */ - *(k++)=((t<<16)|(s&0x0000ffff))&0xffffffff; - s= ((s>>16)|(t&0xffff0000)); - - s=(s<<4)|(s>>28); - *(k++)=s&0xffffffff; - } - return(0); -} - -static const unsigned char odd_parity[256]={ - 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, - 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, - 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, - 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, - 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, - 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, - 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, - 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, - 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, - 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, - 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, - 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, - 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, - 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, - 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, - 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; - -static void block_init(block_state *self, unsigned char *key, - int keylength) -{ - char oddkey[24]; - int i; - - if (keylength != 16 && keylength != 24) { - PyErr_SetString(PyExc_ValueError, - "DES3 key must be either 16 or 24 bytes long"); - return; - } - - for (i=0; iKeySched1); - des_set_key((des_cblock *)(oddkey+8), self->KeySched2); - if (keylength == 24) { - des_set_key((des_cblock *)(oddkey+16), self->KeySched3); - } else { - memcpy(self->KeySched3, self->KeySched1, - sizeof(self->KeySched3)); - } -} - -#include "block_template.c" diff --git a/Crypto/src/MD2.c b/Crypto/src/MD2.c deleted file mode 100644 index aa53c59c..00000000 --- a/Crypto/src/MD2.c +++ /dev/null @@ -1,118 +0,0 @@ - -/* - * md2.c : MD2 hash algorithm. - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - - -#include -#include "Python.h" - -#define MODULE_NAME MD2 -#define DIGEST_SIZE 16 - -typedef unsigned char U8; -typedef unsigned int U32; - -typedef struct { - U8 C[16], X[48]; - int count; - U8 buf[16]; -} hash_state; - -static void hash_init (hash_state *ptr) -{ - memset(ptr->X, 0, 48); - memset(ptr->C, 0, 16); - ptr->count=0; -} - -static U8 S[256] = { - 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, - 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, - 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, - 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, - 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, - 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, - 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, - 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, - 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, - 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, - 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, - 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, - 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, - 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, - 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, - 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, - 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, - 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 -}; - -static void -hash_copy(hash_state *src, hash_state *dest) -{ - dest->count=src->count; - memcpy(dest->buf, src->buf, dest->count); - memcpy(dest->X, src->X, 48); - memcpy(dest->C, src->C, 16); -} - - -static void hash_update (hash_state *self, const U8 *buf, U32 len) -{ - U32 L; - while (len) - { - L=(16-self->count) < len ? (16-self->count) : len; - memcpy(self->buf+self->count, buf, L); - self->count+=L; - buf+=L; - len-=L; - if (self->count==16) - { - U8 t; - int i,j; - - self->count=0; - memcpy(self->X+16, self->buf, 16); - t=self->C[15]; - for(i=0; i<16; i++) - { - self->X[32+i]=self->X[16+i]^self->X[i]; - t=self->C[i]^=S[self->buf[i]^t]; - } - - t=0; - for(i=0; i<18; i++) - { - for(j=0; j<48; j++) - t=self->X[j]^=S[t]; - t=(t+i) & 0xFF; - } - } - } -} - -static PyObject * -hash_digest (const hash_state *self) -{ - U8 padding[16]; - U32 padlen; - hash_state temp; - int i; - - memcpy(&temp, self, sizeof(hash_state)); - padlen= 16-self->count; - for(i=0; i -#include - -#define MODULE_NAME MD4 -#define DIGEST_SIZE 16 - -typedef unsigned int U32; -typedef unsigned char U8; -#define U32_MAX (U32)4294967295 - -typedef struct { - U32 A,B,C,D, count; - U32 len1, len2; - U8 buf[64]; -} hash_state; - -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* ROTATE_LEFT rotates x left n bits */ -#define ROL(x, n) (((x) << n) | ((x) >> (32-n) )) - -static void -hash_init (hash_state *ptr) -{ - ptr->A=(U32)0x67452301; - ptr->B=(U32)0xefcdab89; - ptr->C=(U32)0x98badcfe; - ptr->D=(U32)0x10325476; - ptr->count=ptr->len1=ptr->len2=0; -} - -static void -hash_copy(hash_state *src, hash_state *dest) -{ - dest->len1=src->len1; - dest->len2=src->len2; - dest->A=src->A; - dest->B=src->B; - dest->C=src->C; - dest->D=src->D; - dest->count=src->count; - memcpy(dest->buf, src->buf, dest->count); -} - -static void -hash_update (hash_state *self, const U8 *buf, U32 len) -{ - U32 L; - - if ((self->len1+(len<<3))len1) - { - self->len2++; - } - self->len1+=len<< 3; - self->len2+=len>>29; - while (len>0) - { - L=(64-self->count) < len ? (64-self->count) : len; - memcpy(self->buf+self->count, buf, L); - self->count+=L; - buf+=L; - len-=L; - if (self->count==64) - { - U32 X[16], A, B, C, D; - int i,j; - self->count=0; - for(i=j=0; j<16; i+=4, j++) - X[j]=((U32)self->buf[i] + ((U32)self->buf[i+1]<<8) + - ((U32)self->buf[i+2]<<16) + ((U32)self->buf[i+3]<<24)); - - - A=self->A; B=self->B; C=self->C; D=self->D; - -#define function(a,b,c,d,k,s) a=ROL(a+F(b,c,d)+X[k],s); - function(A,B,C,D, 0, 3); - function(D,A,B,C, 1, 7); - function(C,D,A,B, 2,11); - function(B,C,D,A, 3,19); - function(A,B,C,D, 4, 3); - function(D,A,B,C, 5, 7); - function(C,D,A,B, 6,11); - function(B,C,D,A, 7,19); - function(A,B,C,D, 8, 3); - function(D,A,B,C, 9, 7); - function(C,D,A,B,10,11); - function(B,C,D,A,11,19); - function(A,B,C,D,12, 3); - function(D,A,B,C,13, 7); - function(C,D,A,B,14,11); - function(B,C,D,A,15,19); - -#undef function -#define function(a,b,c,d,k,s) a=ROL(a+G(b,c,d)+X[k]+(U32)0x5a827999,s); - function(A,B,C,D, 0, 3); - function(D,A,B,C, 4, 5); - function(C,D,A,B, 8, 9); - function(B,C,D,A,12,13); - function(A,B,C,D, 1, 3); - function(D,A,B,C, 5, 5); - function(C,D,A,B, 9, 9); - function(B,C,D,A,13,13); - function(A,B,C,D, 2, 3); - function(D,A,B,C, 6, 5); - function(C,D,A,B,10, 9); - function(B,C,D,A,14,13); - function(A,B,C,D, 3, 3); - function(D,A,B,C, 7, 5); - function(C,D,A,B,11, 9); - function(B,C,D,A,15,13); - -#undef function -#define function(a,b,c,d,k,s) a=ROL(a+H(b,c,d)+X[k]+(U32)0x6ed9eba1,s); - function(A,B,C,D, 0, 3); - function(D,A,B,C, 8, 9); - function(C,D,A,B, 4,11); - function(B,C,D,A,12,15); - function(A,B,C,D, 2, 3); - function(D,A,B,C,10, 9); - function(C,D,A,B, 6,11); - function(B,C,D,A,14,15); - function(A,B,C,D, 1, 3); - function(D,A,B,C, 9, 9); - function(C,D,A,B, 5,11); - function(B,C,D,A,13,15); - function(A,B,C,D, 3, 3); - function(D,A,B,C,11, 9); - function(C,D,A,B, 7,11); - function(B,C,D,A,15,15); - - self->A+=A; self->B+=B; self->C+=C; self->D+=D; - } - } -} - -static PyObject * -hash_digest (const hash_state *self) -{ - U8 digest[16]; - static U8 s[8]; - U32 padlen, oldlen1, oldlen2; - hash_state temp; - static U8 padding[64] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - memcpy(&temp, self, sizeof(hash_state)); - oldlen1=temp.len1; oldlen2=temp.len2; /* Save current length */ - padlen= (56<=self->count) ? 56-self->count+64: 56-self->count; - hash_update(&temp, padding, padlen); - s[0]= oldlen1 & 255; - s[1]=(oldlen1 >> 8) & 255; - s[2]=(oldlen1 >> 16) & 255; - s[3]=(oldlen1 >> 24) & 255; - s[4]= oldlen2 & 255; - s[5]=(oldlen2 >> 8) & 255; - s[6]=(oldlen2 >> 16) & 255; - s[7]=(oldlen2 >> 24) & 255; - hash_update(&temp, s, 8); - - digest[ 0]= temp.A & 255; - digest[ 1]=(temp.A >> 8) & 255; - digest[ 2]=(temp.A >> 16) & 255; - digest[ 3]=(temp.A >> 24) & 255; - digest[ 4]= temp.B & 255; - digest[ 5]=(temp.B >> 8) & 255; - digest[ 6]=(temp.B >> 16) & 255; - digest[ 7]=(temp.B >> 24) & 255; - digest[ 8]= temp.C & 255; - digest[ 9]=(temp.C >> 8) & 255; - digest[10]=(temp.C >> 16) & 255; - digest[11]=(temp.C >> 24) & 255; - digest[12]= temp.D & 255; - digest[13]=(temp.D >> 8) & 255; - digest[14]=(temp.D >> 16) & 255; - digest[15]=(temp.D >> 24) & 255; - - return PyString_FromStringAndSize(digest, 16); -} - -#include "hash_template.c" diff --git a/Crypto/src/SHA256.c b/Crypto/src/SHA256.c deleted file mode 100644 index 6bd9df2b..00000000 --- a/Crypto/src/SHA256.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * An implementation of the SHA-256 hash function, this is endian neutral - * so should work just about anywhere. - * - * This code works much like the MD5 code provided by RSA. You sha_init() - * a "sha_state" then sha_process() the bytes you want and sha_done() to get - * the output. - * - * Revised Code: Complies to SHA-256 standard now. - * - * Tom St Denis -- http://tomstdenis.home.dhs.org - * */ -#include "Python.h" -#define MODULE_NAME SHA256 -#define DIGEST_SIZE 32 - -typedef unsigned char U8; -#ifdef __alpha__ -typedef unsigned int U32; -#elif defined(__amd64__) -#include -typedef uint32_t U32; -#else -typedef unsigned int U32; -#endif - -typedef struct { - U32 state[8], length, curlen; - unsigned char buf[64]; -} -hash_state; - -/* the K array */ -static const U32 K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; - -/* Various logical functions */ -#define Ch(x,y,z) ((x & y) ^ (~x & z)) -#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) -#define S(x, n) (((x)>>((n)&31))|((x)<<(32-((n)&31)))) -#define R(x, n) ((x)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -/* compress 512-bits */ -static void sha_compress(hash_state * md) -{ - U32 S[8], W[64], t0, t1; - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) - S[i] = md->state[i]; - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) - W[i] = (((U32) md->buf[(4 * i) + 0]) << 24) | - (((U32) md->buf[(4 * i) + 1]) << 16) | - (((U32) md->buf[(4 * i) + 2]) << 8) | - (((U32) md->buf[(4 * i) + 3])); - - /* fill W[16..63] */ - for (i = 16; i < 64; i++) - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - - /* Compress */ - for (i = 0; i < 64; i++) { - t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; - t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); - S[7] = S[6]; - S[6] = S[5]; - S[5] = S[4]; - S[4] = S[3] + t0; - S[3] = S[2]; - S[2] = S[1]; - S[1] = S[0]; - S[0] = t0 + t1; - } - - /* feedback */ - for (i = 0; i < 8; i++) - md->state[i] += S[i]; -} - -/* init the SHA state */ -void sha_init(hash_state * md) -{ - md->curlen = md->length = 0; - md->state[0] = 0x6A09E667UL; - md->state[1] = 0xBB67AE85UL; - md->state[2] = 0x3C6EF372UL; - md->state[3] = 0xA54FF53AUL; - md->state[4] = 0x510E527FUL; - md->state[5] = 0x9B05688CUL; - md->state[6] = 0x1F83D9ABUL; - md->state[7] = 0x5BE0CD19UL; -} - -void sha_process(hash_state * md, unsigned char *buf, int len) -{ - while (len--) { - /* copy byte */ - md->buf[md->curlen++] = *buf++; - - /* is 64 bytes full? */ - if (md->curlen == 64) { - sha_compress(md); - md->length += 512; - md->curlen = 0; - } - } -} - -void sha_done(hash_state * md, unsigned char *hash) -{ - int i; - - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = 0x80; - - /* if the length is currenlly above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen >= 56) { - for (; md->curlen < 64;) - md->buf[md->curlen++] = 0; - sha_compress(md); - md->curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - for (; md->curlen < 56;) - md->buf[md->curlen++] = 0; - - /* since all messages are under 2^32 bits we mark the top bits zero */ - for (i = 56; i < 60; i++) - md->buf[i] = 0; - - /* append length */ - for (i = 60; i < 64; i++) - md->buf[i] = (md->length >> ((63 - i) * 8)) & 255; - sha_compress(md); - - /* copy output */ - for (i = 0; i < 32; i++) - hash[i] = (md->state[i >> 2] >> (((3 - i) & 3) << 3)) & 255; -} - -// Done -static void hash_init (hash_state *ptr) -{ - sha_init(ptr); -} - -// Done -static void -hash_update (hash_state *self, const U8 *buf, U32 len) -{ - sha_process(self,(unsigned char *)buf,len); -} - -// Done -static void -hash_copy(hash_state *src, hash_state *dest) -{ - memcpy(dest,src,sizeof(hash_state)); -} - -// Done -static PyObject * -hash_digest (const hash_state *self) -{ - unsigned char digest[32]; - hash_state temp; - - hash_copy((hash_state*)self,&temp); - sha_done(&temp,digest); - return PyString_FromStringAndSize(digest, 32); -} - -#include "hash_template.c" diff --git a/Crypto/src/XOR.c b/Crypto/src/XOR.c deleted file mode 100644 index f2c74afa..00000000 --- a/Crypto/src/XOR.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * xor.c : Source for the trivial cipher which XORs the message with the key. - * The key can be up to 32 bytes long. - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -#define MODULE_NAME XOR -#define BLOCK_SIZE 1 -#define KEY_SIZE 0 - -typedef struct -{ - unsigned char key[32]; - int keylen, last_pos; -} stream_state; - -static void -stream_init(stream_state *self, unsigned char *key, int len) -{ - int i; - - if (32 <= len) len=32; - self->keylen = len; - self->last_pos = 0; - - for(i=0; ikey[i] = key[i]; - } -} - -/* Encryption and decryption are symmetric */ -#define stream_decrypt stream_encrypt - -static void stream_encrypt(stream_state *self, unsigned char *block, - int len) -{ - int i, j = self->last_pos; - for(i=0; ikeylen) - { - block[i] ^= self->key[j]; - } - self->last_pos = j; -} - -#include "stream_template.c" diff --git a/Crypto/src/_dsa.c b/Crypto/src/_dsa.c deleted file mode 100644 index 4752f438..00000000 --- a/Crypto/src/_dsa.c +++ /dev/null @@ -1,331 +0,0 @@ - -/* - * _dsa.c: C implementation of the DSA algorithm. - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -#include -#include -#include -#include /* for conversions */ -#include - -PyObject *_dsa_module; -PyObject *_dsa_dict; - -void -longObjToMPZ (mpz_t m, PyLongObject * p) -{ - int size, i; - mpz_t temp, temp2; - mpz_init (temp); - mpz_init (temp2); - if (p->ob_size > 0) - size = p->ob_size; - else - size = -p->ob_size; - for (i = 0; i < size; i++) - { - mpz_set_ui (temp, p->ob_digit[i]); - mpz_mul_2exp (temp2, temp, SHIFT * i); - mpz_add (m, m, temp2); - } - mpz_clear (temp); - mpz_clear (temp2); -} - -PyObject * -mpzToLongObj (mpz_t m) -{ - /* borrowed from gmpy */ - int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT; - int i; - mpz_t temp; - PyLongObject *l = _PyLong_New (size); - if (!l) - { - return NULL; - } - mpz_init_set (temp, m); - for (i = 0; i < size; i++) - { - l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK); - mpz_fdiv_q_2exp (temp, temp, SHIFT); - } - i = size; - while ((i > 0) && (l->ob_digit[i - 1] == 0)) - i--; - l->ob_size = i; - mpz_clear (temp); - return (PyObject *) l; -} - -PyObject *dsaKey_new (PyObject *, PyObject *); - -static PyMethodDef _dsa__methods__[] = { - {"construct", dsaKey_new, METH_VARARGS}, - {NULL, NULL} -}; - -typedef struct -{ - PyObject_HEAD mpz_t y; - mpz_t g; - mpz_t p; - mpz_t q; - mpz_t x; -} -dsaKey; - -static int -dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s) -{ - mpz_t temp; - if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0) - { - return 1; - } - mpz_init (temp); - mpz_powm (r, key->g, k, key->p); - mpz_mod (r, r, key->q); - mpz_invert (s, k, key->q); - mpz_mul (temp, key->x, r); - mpz_add (temp, m, temp); - mpz_mul (s, s, temp); - mpz_mod (s, s, key->q); - mpz_clear (temp); - return 0; -} - -static int -dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s) -{ - int result; - mpz_t u1, u2, v1, v2, w; - if (mpz_cmp_ui (r, 0) <= 0 || mpz_cmp (r, key->q) >= 0 || - mpz_cmp_ui (s, 0) <= 0 || mpz_cmp (s, key->q) >= 0) - return 0; - mpz_init (u1); - mpz_init (u2); - mpz_init (v1); - mpz_init (v2); - mpz_init (w); - mpz_invert (w, s, key->q); - mpz_mul (u1, m, w); - mpz_mod (u1, u1, key->q); - mpz_mul (u2, r, w); - mpz_mod (u2, u2, key->q); - mpz_powm (v1, key->g, u1, key->p); - mpz_powm (v2, key->y, u2, key->p); - mpz_mul (w, v1, v2); - mpz_mod (w, w, key->p); - mpz_mod (w, w, key->q); - if (mpz_cmp (r, w) == 0) - result = 1; - else - result = 0; - mpz_clear (u1); - mpz_clear (u2); - mpz_clear (v1); - mpz_clear (v2); - mpz_clear (w); - return result; -} - -static void dsaKey_dealloc (dsaKey *); -static PyObject *dsaKey_getattr (dsaKey *, char *); -static PyObject *dsaKey__sign (dsaKey *, PyObject *); -static PyObject *dsaKey__verify (dsaKey *, PyObject *); -static PyObject *dsaKey_size (dsaKey *, PyObject *); -static PyObject *dsaKey_hasprivate (dsaKey *, PyObject *); - -PyObject *dsaError; /* raised on errors */ - -static PyTypeObject dsaKeyType = { - PyObject_HEAD_INIT (NULL) 0, - "dsaKey", - sizeof (dsaKey), - 0, - (destructor) dsaKey_dealloc, /* dealloc */ - 0, /* print */ - (getattrfunc) dsaKey_getattr, /* getattr */ - 0, /* setattr */ - 0, /* compare */ - 0, /* repr */ - 0, /* as_number */ - 0, /* as_sequence */ - 0, /* as_mapping */ - 0, /* hash */ - 0, /* call */ -}; - -static PyMethodDef dsaKey__methods__[] = { - {"_sign", (PyCFunction) dsaKey__sign, METH_VARARGS, "Sign the given long."}, - {"_verify", (PyCFunction) dsaKey__verify, METH_VARARGS, - "Verify that the signature is valid."}, - {"size", (PyCFunction) dsaKey_size, METH_VARARGS, - "Return the number of bits that this key can handle."}, - {"hasprivate", (PyCFunction) dsaKey_hasprivate, METH_VARARGS, - "Return 1 or 0 if this key does/doesn't have a private key."}, - {NULL, NULL, 0, NULL} -}; - -PyObject * -dsaKey_new (PyObject * self, PyObject * args) -{ - PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL; - dsaKey *key; - key = PyObject_New (dsaKey, &dsaKeyType); - mpz_init (key->y); - mpz_init (key->g); - mpz_init (key->p); - mpz_init (key->q); - mpz_init (key->x); - PyArg_ParseTuple (args, "O!O!O!O!|O!", &PyLong_Type, &y, - &PyLong_Type, &g, - &PyLong_Type, &p, &PyLong_Type, &q, &PyLong_Type, &x); - longObjToMPZ (key->y, y); - longObjToMPZ (key->g, g); - longObjToMPZ (key->p, p); - longObjToMPZ (key->q, q); - if (x) - { - longObjToMPZ (key->x, x); - } - /*Py_XDECREF(n); - Py_XDECREF(e); - Py_XDECREF(d); - Py_XDECREF(p); - Py_XDECREF(q); */ - return (PyObject *) key; -} - -static void -dsaKey_dealloc (dsaKey * key) -{ - mpz_clear (key->y); - mpz_clear (key->g); - mpz_clear (key->p); - mpz_clear (key->q); - mpz_clear (key->x); - PyObject_Del (key); -} - -static PyObject * -dsaKey_getattr (dsaKey * key, char *attr) -{ - if (strcmp (attr, "y") == 0) - return mpzToLongObj (key->y); - else if (strcmp (attr, "g") == 0) - return mpzToLongObj (key->g); - else if (strcmp (attr, "p") == 0) - return mpzToLongObj (key->p); - else if (strcmp (attr, "q") == 0) - return mpzToLongObj (key->q); - else if (strcmp (attr, "x") == 0) - { - if (mpz_size (key->x) == 0) - { - PyErr_SetString (PyExc_AttributeError, - "rsaKey instance has no attribute 'x'"); - return NULL; - } - return mpzToLongObj (key->x); - } - else - { - return Py_FindMethod (dsaKey__methods__, (PyObject *) key, attr); - } -} - -PyObject * -dsaKey__sign (dsaKey * key, PyObject * args) -{ - PyObject *lm, *lk, *lr, *ls; - mpz_t m, k, r, s; - int result; - if (!(PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm, - &PyLong_Type, &lk))) - { - return NULL; - } - mpz_init (m); - mpz_init (k); - mpz_init (r); - mpz_init (s); - longObjToMPZ (m, (PyLongObject *) lm); - longObjToMPZ (k, (PyLongObject *) lk); - result = dsaSign (key, m, k, r, s); - if (result == 1) - { - PyErr_SetString (dsaError, "K not between 2 and q"); - return NULL; - } - lr = mpzToLongObj (r); - ls = mpzToLongObj (s); - mpz_clear (m); - mpz_clear (k); - mpz_clear (r); - mpz_clear (s); - return Py_BuildValue ("(NN)", lr, ls); -} - -PyObject * -dsaKey__verify (dsaKey * key, PyObject * args) -{ - PyObject *lm, *lr, *ls; - mpz_t m, r, s; - int result; - if (!(PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm, - &PyLong_Type, &lr, &PyLong_Type, &ls))) - { - return NULL; - } - mpz_init (m); - mpz_init (r); - mpz_init (s); - longObjToMPZ (m, (PyLongObject *) lm); - longObjToMPZ (r, (PyLongObject *) lr); - longObjToMPZ (s, (PyLongObject *) ls); - result = dsaVerify (key, m, r, s); - mpz_clear (m); - mpz_clear (r); - mpz_clear (s); - return Py_BuildValue ("i", result); -} - -PyObject * -dsaKey_size (dsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1); -} - -PyObject * -dsaKey_hasprivate (dsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - if (mpz_size (key->x) == 0) - return Py_BuildValue ("i", 0); - else - return Py_BuildValue ("i", 1); -} - - -void -init_dsa (void) -{ - dsaKeyType.ob_type = &PyType_Type; - _dsa_module = Py_InitModule ("_dsa", _dsa__methods__); - _dsa_dict = PyModule_GetDict (_dsa_module); - dsaError = PyErr_NewException ("_dsa.error", NULL, NULL); - PyDict_SetItemString (_dsa_dict, "error", dsaError); -} diff --git a/Crypto/src/_fastmath.c b/Crypto/src/_fastmath.c deleted file mode 100644 index 7fe7abec..00000000 --- a/Crypto/src/_fastmath.c +++ /dev/null @@ -1,804 +0,0 @@ - -/* - * _fastmath.c: Accelerator module that uses GMP for faster numerics. - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - * $Id: _fastmath.c,v 1.13 2003/04/04 19:20:29 jbontje Exp $ - */ - -#include -#include -#include -#include /* for conversions */ -#include - -void -longObjToMPZ (mpz_t m, PyLongObject * p) -{ - int size, i; - mpz_t temp, temp2; - mpz_init (temp); - mpz_init (temp2); - if (p->ob_size > 0) - size = p->ob_size; - else - size = -p->ob_size; - for (i = 0; i < size; i++) - { - mpz_set_ui (temp, p->ob_digit[i]); - mpz_mul_2exp (temp2, temp, SHIFT * i); - mpz_add (m, m, temp2); - } - mpz_clear (temp); - mpz_clear (temp2); -} - -PyObject * -mpzToLongObj (mpz_t m) -{ - /* borrowed from gmpy */ - int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT; - int i; - mpz_t temp; - PyLongObject *l = _PyLong_New (size); - if (!l) - return NULL; - mpz_init_set (temp, m); - for (i = 0; i < size; i++) - { - l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK); - mpz_fdiv_q_2exp (temp, temp, SHIFT); - } - i = size; - while ((i > 0) && (l->ob_digit[i - 1] == 0)) - i--; - l->ob_size = i; - mpz_clear (temp); - return (PyObject *) l; -} - -typedef struct -{ - PyObject_HEAD mpz_t y; - mpz_t g; - mpz_t p; - mpz_t q; - mpz_t x; -} -dsaKey; - -typedef struct -{ - PyObject_HEAD mpz_t n; - mpz_t e; - mpz_t d; - mpz_t p; - mpz_t q; - mpz_t u; -} -rsaKey; - -PyObject *rsaKey_new (PyObject *, PyObject *); -PyObject *dsaKey_new (PyObject *, PyObject *); - -static void dsaKey_dealloc (dsaKey *); -static PyObject *dsaKey_getattr (dsaKey *, char *); -static PyObject *dsaKey__sign (dsaKey *, PyObject *); -static PyObject *dsaKey__verify (dsaKey *, PyObject *); -static PyObject *dsaKey_size (dsaKey *, PyObject *); -static PyObject *dsaKey_has_private (dsaKey *, PyObject *); - -static void rsaKey_dealloc (rsaKey *); -static PyObject *rsaKey_getattr (rsaKey *, char *); -static PyObject *rsaKey__encrypt (rsaKey *, PyObject *); -static PyObject *rsaKey__decrypt (rsaKey *, PyObject *); -static PyObject *rsaKey__verify (rsaKey *, PyObject *); -static PyObject *rsaKey__blind (rsaKey *, PyObject *); -static PyObject *rsaKey__unblind (rsaKey *, PyObject *); -static PyObject *rsaKey_size (rsaKey *, PyObject *); -static PyObject *rsaKey_has_private (rsaKey *, PyObject *); - -static int -dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s) -{ - mpz_t temp; - if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0) - { - return 1; - } - mpz_init (temp); - mpz_powm (r, key->g, k, key->p); - mpz_mod (r, r, key->q); - mpz_invert (s, k, key->q); - mpz_mul (temp, key->x, r); - mpz_add (temp, m, temp); - mpz_mul (s, s, temp); - mpz_mod (s, s, key->q); - mpz_clear (temp); - return 0; -} - -static int -dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s) -{ - int result; - mpz_t u1, u2, v1, v2, w; - if (mpz_cmp_ui (r, 0) <= 0 || mpz_cmp (r, key->q) >= 0 || - mpz_cmp_ui (s, 0) <= 0 || mpz_cmp (s, key->q) >= 0) - return 0; - mpz_init (u1); - mpz_init (u2); - mpz_init (v1); - mpz_init (v2); - mpz_init (w); - mpz_invert (w, s, key->q); - mpz_mul (u1, m, w); - mpz_mod (u1, u1, key->q); - mpz_mul (u2, r, w); - mpz_mod (u2, u2, key->q); - mpz_powm (v1, key->g, u1, key->p); - mpz_powm (v2, key->y, u2, key->p); - mpz_mul (w, v1, v2); - mpz_mod (w, w, key->p); - mpz_mod (w, w, key->q); - if (mpz_cmp (r, w) == 0) - result = 1; - else - result = 0; - mpz_clear (u1); - mpz_clear (u2); - mpz_clear (v1); - mpz_clear (v2); - mpz_clear (w); - return result; -} - - -static int -rsaEncrypt (rsaKey * key, mpz_t v) -{ - if (mpz_cmp (v, key->n) >= 0) - { - return 1; - } - mpz_powm (v, v, key->e, key->n); - return 0; -} - -static int -rsaDecrypt (rsaKey * key, mpz_t v) -{ - mpz_t m1, m2, h; - if (mpz_cmp (v, key->n) >= 0) - { - return 1; - } - if (mpz_size (key->d) == 0) - { - return 2; - } - - if ((mpz_size (key->p) != 0) && (mpz_size (key->q) != 0) && - (mpz_size (key->u) != 0)) - { - /* fast path */ - mpz_init(m1); - mpz_init(m2); - mpz_init(h); - - /* m1 = c ^ (d mod (p-1)) mod p */ - mpz_sub_ui(h, key->p, 1); - mpz_fdiv_r(h, key->d, h); - mpz_powm(m1, v, h, key->p); - /* m2 = c ^ (d mod (q-1)) mod q */ - mpz_sub_ui(h, key->q, 1); - mpz_fdiv_r(h, key->d, h); - mpz_powm(m2, v, h, key->q); - /* h = u * ( m2 - m1 ) mod q */ - mpz_sub(h, m2, m1); - if (mpz_sgn(h)==-1) - mpz_add(h, h, key->q); - mpz_mul(h, key->u, h); - mpz_mod(h, h, key->q); - /* m = m2 + h * p */ - mpz_mul(h, h, key->p); - mpz_add(v, m1, h); - /* ready */ - - mpz_clear(m1); - mpz_clear(m2); - mpz_clear(h); - return 0; - } - - /* slow */ - mpz_powm (v, v, key->d, key->n); - return 0; -} - -static int -rsaBlind (rsaKey * key, mpz_t v, mpz_t b) -{ - if (mpz_cmp (v, key->n) >= 0) - { - return 1; - } - if (mpz_cmp (b, key->n) >= 0) - { - return 2; - } - mpz_powm (b, b, key->e, key->n); - mpz_mul (v, v, b); - mpz_mod (v, v, key->n); - return 0; -} - -static int -rsaUnBlind (rsaKey * key, mpz_t v, mpz_t b) -{ - if (mpz_cmp (v, key->n) >= 0) - { - return 1; - } - if (mpz_cmp (b, key->n) >= 0) - { - return 2; - } - if (!mpz_invert (b, b, key->n)) - { - return 3; - } - mpz_mul (v, v, b); - mpz_mod (v, v, key->n); - return 0; -} - - -static PyTypeObject dsaKeyType = { - PyObject_HEAD_INIT (NULL) 0, - "dsaKey", - sizeof (dsaKey), - 0, - (destructor) dsaKey_dealloc, /* dealloc */ - 0, /* print */ - (getattrfunc) dsaKey_getattr, /* getattr */ - 0, /* setattr */ - 0, /* compare */ - 0, /* repr */ - 0, /* as_number */ - 0, /* as_sequence */ - 0, /* as_mapping */ - 0, /* hash */ - 0, /* call */ -}; - -static PyMethodDef dsaKey__methods__[] = { - {"_sign", (PyCFunction) dsaKey__sign, METH_VARARGS, - "Sign the given long."}, - {"_verify", (PyCFunction) dsaKey__verify, METH_VARARGS, - "Verify that the signature is valid."}, - {"size", (PyCFunction) dsaKey_size, METH_VARARGS, - "Return the number of bits that this key can handle."}, - {"has_private", (PyCFunction) dsaKey_has_private, METH_VARARGS, - "Return 1 or 0 if this key does/doesn't have a private key."}, - {NULL, NULL, 0, NULL} -}; - -PyObject *fastmathError; /* raised on errors */ - -static PyTypeObject rsaKeyType = { - PyObject_HEAD_INIT (NULL) 0, - "rsaKey", - sizeof (rsaKey), - 0, - (destructor) rsaKey_dealloc, /* dealloc */ - 0, /* print */ - (getattrfunc) rsaKey_getattr, /* getattr */ - 0, /* setattr */ - 0, /* compare */ - 0, /* repr */ - 0, /* as_number */ - 0, /* as_sequence */ - 0, /* as_mapping */ - 0, /* hash */ - 0, /* call */ -}; - -static PyMethodDef rsaKey__methods__[] = { - {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS, - "Encrypt the given long."}, - {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS, - "Decrypt the given long."}, - {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS, - "Sign the given long."}, - {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS, - "Verify that the signature is valid."}, - {"_blind", (PyCFunction) rsaKey__blind, METH_VARARGS, - "Blind the given long."}, - {"_unblind", (PyCFunction) rsaKey__unblind, METH_VARARGS, - "Unblind the given long."}, - {"size", (PyCFunction) rsaKey_size, METH_VARARGS, - "Return the number of bits that this key can handle."}, - {"has_private", (PyCFunction) rsaKey_has_private, METH_VARARGS, - "Return 1 or 0 if this key does/doesn't have a private key."}, - {NULL, NULL, 0, NULL} -}; - -PyObject * -dsaKey_new (PyObject * self, PyObject * args) -{ - PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL; - dsaKey *key; - if (!PyArg_ParseTuple(args, "O!O!O!O!|O!", &PyLong_Type, &y, - &PyLong_Type, &g, &PyLong_Type, &p, - &PyLong_Type, &q, &PyLong_Type, &x)) - return NULL; - - key = PyObject_New (dsaKey, &dsaKeyType); - mpz_init (key->y); - mpz_init (key->g); - mpz_init (key->p); - mpz_init (key->q); - mpz_init (key->x); - longObjToMPZ (key->y, y); - longObjToMPZ (key->g, g); - longObjToMPZ (key->p, p); - longObjToMPZ (key->q, q); - if (x) - { - longObjToMPZ (key->x, x); - } - return (PyObject *) key; -} - -static void -dsaKey_dealloc (dsaKey * key) -{ - mpz_clear (key->y); - mpz_clear (key->g); - mpz_clear (key->p); - mpz_clear (key->q); - mpz_clear (key->x); - PyObject_Del (key); -} - -static PyObject * -dsaKey_getattr (dsaKey * key, char *attr) -{ - if (strcmp (attr, "y") == 0) - return mpzToLongObj (key->y); - else if (strcmp (attr, "g") == 0) - return mpzToLongObj (key->g); - else if (strcmp (attr, "p") == 0) - return mpzToLongObj (key->p); - else if (strcmp (attr, "q") == 0) - return mpzToLongObj (key->q); - else if (strcmp (attr, "x") == 0) - { - if (mpz_size (key->x) == 0) - { - PyErr_SetString (PyExc_AttributeError, - "dsaKey instance has no attribute 'x'"); - return NULL; - } - return mpzToLongObj (key->x); - } - else - { - return Py_FindMethod (dsaKey__methods__, (PyObject *) key, attr); - } -} - -PyObject * -dsaKey__sign (dsaKey * key, PyObject * args) -{ - PyObject *lm, *lk, *lr, *ls; - mpz_t m, k, r, s; - int result; - if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm, - &PyLong_Type, &lk)) - { - return NULL; - } - mpz_init (m); - mpz_init (k); - mpz_init (r); - mpz_init (s); - longObjToMPZ (m, (PyLongObject *) lm); - longObjToMPZ (k, (PyLongObject *) lk); - result = dsaSign (key, m, k, r, s); - if (result == 1) - { - PyErr_SetString (fastmathError, "K not between 2 and q"); - return NULL; - } - lr = mpzToLongObj (r); - ls = mpzToLongObj (s); - mpz_clear (m); - mpz_clear (k); - mpz_clear (r); - mpz_clear (s); - return Py_BuildValue ("(NN)", lr, ls); -} - -PyObject * -dsaKey__verify (dsaKey * key, PyObject * args) -{ - PyObject *lm, *lr, *ls; - mpz_t m, r, s; - int result; - if (!PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm, - &PyLong_Type, &lr, &PyLong_Type, &ls)) - { - return NULL; - } - mpz_init (m); - mpz_init (r); - mpz_init (s); - longObjToMPZ (m, (PyLongObject *) lm); - longObjToMPZ (r, (PyLongObject *) lr); - longObjToMPZ (s, (PyLongObject *) ls); - result = dsaVerify (key, m, r, s); - mpz_clear (m); - mpz_clear (r); - mpz_clear (s); - if (result) { - Py_INCREF(Py_True); - return Py_True; - } else { - Py_INCREF(Py_False); - return Py_False; - } -} - -PyObject * -dsaKey_size (dsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1); -} - -PyObject * -dsaKey_has_private (dsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - if (mpz_size (key->x) == 0) { - Py_INCREF(Py_False); - return Py_False; - } else { - Py_INCREF(Py_True); - return Py_True; - } -} - -PyObject * -rsaKey_new (PyObject * self, PyObject * args) -{ - PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, - *u = NULL; - rsaKey *key; - - if (!PyArg_ParseTuple(args, "O!O!|O!O!O!O!", &PyLong_Type, &n, - &PyLong_Type, &e, &PyLong_Type, &d, - &PyLong_Type, &p, &PyLong_Type, &q, - &PyLong_Type, &u)) - return NULL; - - key = PyObject_New (rsaKey, &rsaKeyType); - mpz_init (key->n); - mpz_init (key->e); - mpz_init (key->d); - mpz_init (key->p); - mpz_init (key->q); - mpz_init (key->u); - longObjToMPZ (key->n, n); - longObjToMPZ (key->e, e); - if (!d) - { - return (PyObject *) key; - } - longObjToMPZ (key->d, d); - if (p && q) - { - longObjToMPZ (key->p, p); - longObjToMPZ (key->q, q); - if (u) { - longObjToMPZ (key->u, u); - } else { - mpz_invert (key->u, key->p, key->q); - } - } - return (PyObject *) key; -} - -static void -rsaKey_dealloc (rsaKey * key) -{ - mpz_clear (key->n); - mpz_clear (key->e); - mpz_clear (key->d); - mpz_clear (key->p); - mpz_clear (key->q); - mpz_clear (key->u); - PyObject_Del (key); -} - -static PyObject * -rsaKey_getattr (rsaKey * key, char *attr) -{ - if (strcmp (attr, "n") == 0) - return mpzToLongObj (key->n); - else if (strcmp (attr, "e") == 0) - return mpzToLongObj (key->e); - else if (strcmp (attr, "d") == 0) - { - if (mpz_size (key->d) == 0) - { - PyErr_SetString(PyExc_AttributeError, - "rsaKey instance has no attribute 'd'"); - return NULL; - } - return mpzToLongObj (key->d); - } - else if (strcmp (attr, "p") == 0) - { - if (mpz_size (key->p) == 0) - { - PyErr_SetString(PyExc_AttributeError, - "rsaKey instance has no attribute 'p'"); - return NULL; - } - return mpzToLongObj (key->p); - } - else if (strcmp (attr, "q") == 0) - { - if (mpz_size (key->q) == 0) - { - PyErr_SetString(PyExc_AttributeError, - "rsaKey instance has no attribute 'q'"); - return NULL; - } - return mpzToLongObj (key->q); - } - else if (strcmp (attr, "u") == 0) - { - if (mpz_size (key->u) == 0) - { - PyErr_SetString(PyExc_AttributeError, - "rsaKey instance has no attribute 'u'"); - return NULL; - } - return mpzToLongObj (key->u); - } - else - { - return Py_FindMethod (rsaKey__methods__, - (PyObject *) key, attr); - } -} - -PyObject * -rsaKey__encrypt (rsaKey * key, PyObject * args) -{ - PyObject *l, *r; - mpz_t v; - int result; - if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) - { - return NULL; - } - mpz_init (v); - longObjToMPZ (v, (PyLongObject *) l); - result = rsaEncrypt (key, v); - if (result == 1) - { - PyErr_SetString (fastmathError, "Plaintext too large"); - return NULL; - } - r = (PyObject *) mpzToLongObj (v); - mpz_clear (v); - return Py_BuildValue ("N", r); -} - -PyObject * -rsaKey__decrypt (rsaKey * key, PyObject * args) -{ - PyObject *l, *r; - mpz_t v; - int result; - if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) - { - return NULL; - } - mpz_init (v); - longObjToMPZ (v, (PyLongObject *) l); - result = rsaDecrypt (key, v); - if (result == 1) - { - PyErr_SetString (fastmathError, - "Ciphertext too large"); - return NULL; - } - else if (result == 2) - { - PyErr_SetString (fastmathError, - "Private key not available in this object"); - return NULL; - } - r = mpzToLongObj (v); - mpz_clear (v); - return Py_BuildValue ("N", r); -} - -PyObject * -rsaKey__verify (rsaKey * key, PyObject * args) -{ - PyObject *l, *lsig; - mpz_t v, vsig; - if (!PyArg_ParseTuple(args, "O!O!", - &PyLong_Type, &l, &PyLong_Type, &lsig)) - { - return NULL; - } - mpz_init (v); - mpz_init (vsig); - longObjToMPZ (v, (PyLongObject *) l); - longObjToMPZ (vsig, (PyLongObject *) lsig); - rsaEncrypt (key, vsig); - if (mpz_cmp (v, vsig) == 0) { - Py_INCREF(Py_True); - return Py_True; - } - else { - Py_INCREF(Py_False); - return Py_False; - } -} - -PyObject * -rsaKey__blind (rsaKey * key, PyObject * args) -{ - PyObject *l, *lblind, *r; - mpz_t v, vblind; - int result; - if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, - &PyLong_Type, &lblind)) - { - return NULL; - } - mpz_init (v); - mpz_init (vblind); - longObjToMPZ (v, (PyLongObject *) l); - longObjToMPZ (vblind, (PyLongObject *) lblind); - result = rsaBlind (key, v, vblind); - if (result == 1) - { - PyErr_SetString (fastmathError, "Message too large"); - return NULL; - } - else if (result == 2) - { - PyErr_SetString (fastmathError, "Blinding factor too large"); - return NULL; - } - r = (PyObject *) mpzToLongObj (v); - mpz_clear (v); - mpz_clear (vblind); - return Py_BuildValue ("N", r); -} - -PyObject * -rsaKey__unblind (rsaKey * key, PyObject * args) -{ - PyObject *l, *lblind, *r; - mpz_t v, vblind; - int result; - if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, - &PyLong_Type, &lblind)) - { - return NULL; - } - mpz_init (v); - mpz_init (vblind); - longObjToMPZ (v, (PyLongObject *) l); - longObjToMPZ (vblind, (PyLongObject *) lblind); - result = rsaUnBlind (key, v, vblind); - if (result == 1) - { - PyErr_SetString (fastmathError, "Message too large"); - return NULL; - } - else if (result == 2) - { - PyErr_SetString (fastmathError, "Blinding factor too large"); - return NULL; - } - else if (result == 3) - { - PyErr_SetString (fastmathError, "Inverse doesn't exist"); - return NULL; - } - r = (PyObject *) mpzToLongObj (v); - mpz_clear (v); - mpz_clear (vblind); - return Py_BuildValue ("N", r); -} - -PyObject * -rsaKey_size (rsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1); -} - -PyObject * -rsaKey_has_private (rsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - if (mpz_size (key->d) == 0) { - Py_INCREF(Py_False); - return Py_False; - } else { - Py_INCREF(Py_True); - return Py_True; - } -} - - -PyObject * -isPrime (PyObject * self, PyObject * args) -{ - PyObject *l; - mpz_t n; - int result; - - if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) - { - return NULL; - } - mpz_init (n); - longObjToMPZ (n, (PyLongObject *) l); - - result = mpz_probab_prime_p(n, 5); - - mpz_clear (n); - - if (result == 0) { - Py_INCREF(Py_False); - return Py_False; - } else { - Py_INCREF(Py_True); - return Py_True; - } -} - - -static PyMethodDef _fastmath__methods__[] = { - {"dsa_construct", dsaKey_new, METH_VARARGS}, - {"rsa_construct", rsaKey_new, METH_VARARGS}, - {"isPrime", isPrime, METH_VARARGS}, - {NULL, NULL} -}; - -void -init_fastmath (void) -{ - PyObject *_fastmath_module; - PyObject *_fastmath_dict; - - rsaKeyType.ob_type = &PyType_Type; - dsaKeyType.ob_type = &PyType_Type; - _fastmath_module = Py_InitModule ("_fastmath", _fastmath__methods__); - _fastmath_dict = PyModule_GetDict (_fastmath_module); - fastmathError = PyErr_NewException ("_fastmath.error", NULL, NULL); - PyDict_SetItemString (_fastmath_dict, "error", fastmathError); -} diff --git a/Crypto/src/_rsa.c b/Crypto/src/_rsa.c deleted file mode 100644 index e51d1884..00000000 --- a/Crypto/src/_rsa.c +++ /dev/null @@ -1,346 +0,0 @@ - -/* - * _rsa.c: C implementation of the RSA algorithm. - * - * Part of the Python Cryptography Toolkit - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -#include -#include -#include -#include /* for conversions */ -#include - -PyObject *_rsa_module; -PyObject *_rsa_dict; - -void -longObjToMPZ (mpz_t m, PyLongObject * p) -{ - int size, i; - mpz_t temp, temp2; - mpz_init (temp); - mpz_init (temp2); - if (p->ob_size > 0) - size = p->ob_size; - else - size = -p->ob_size; - for (i = 0; i < size; i++) - { - mpz_set_ui (temp, p->ob_digit[i]); - mpz_mul_2exp (temp2, temp, SHIFT * i); - mpz_add (m, m, temp2); - } - mpz_clear (temp); - mpz_clear (temp2); -} - -PyObject * -mpzToLongObj (mpz_t m) -{ - /* borrowed from gmpy */ - int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT; - int i; - mpz_t temp; - PyLongObject *l = _PyLong_New (size); - if (!l) - return NULL; - mpz_init_set (temp, m); - for (i = 0; i < size; i++) - { - l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK); - mpz_fdiv_q_2exp (temp, temp, SHIFT); - } - i = size; - while ((i > 0) && (l->ob_digit[i - 1] == 0)) - i--; - l->ob_size = i; - mpz_clear (temp); - return (PyObject *) l; -} - -PyObject *rsaKey_new (PyObject *, PyObject *); - -static PyMethodDef _rsa__methods__[] = { - {"construct", rsaKey_new, METH_VARARGS}, - {NULL, NULL} -}; - -typedef struct -{ - PyObject_HEAD mpz_t n; - mpz_t e; - mpz_t d; - mpz_t p; - mpz_t q; -} -rsaKey; - -static int -rsaEncrypt (rsaKey * key, mpz_t v) -{ - if (mpz_cmp (v, key->n) >= 0) - { - return 1; - } - mpz_powm (v, v, key->e, key->n); - return 0; -} - -static int -rsaDecrypt (rsaKey * key, mpz_t v) -{ - if (mpz_cmp (v, key->n) >= 0) - { - return 1; - } - if (mpz_size (key->d) == 0) - { - return 2; - } - mpz_powm (v, v, key->d, key->n); - return 0; -} - -static void rsaKey_dealloc (rsaKey *); -static PyObject *rsaKey_getattr (rsaKey *, char *); -static PyObject *rsaKey__encrypt (rsaKey *, PyObject *); -static PyObject *rsaKey__decrypt (rsaKey *, PyObject *); -static PyObject *rsaKey__verify (rsaKey *, PyObject *); -static PyObject *rsaKey_size (rsaKey *, PyObject *); -static PyObject *rsaKey_hasprivate (rsaKey *, PyObject *); - -PyObject *rsaError; /* raised on errors */ - -static PyTypeObject rsaKeyType = { - PyObject_HEAD_INIT (NULL) 0, - "rsaKey", - sizeof (rsaKey), - 0, - (destructor) rsaKey_dealloc, /* dealloc */ - 0, /* print */ - (getattrfunc) rsaKey_getattr, /* getattr */ - 0, /* setattr */ - 0, /* compare */ - 0, /* repr */ - 0, /* as_number */ - 0, /* as_sequence */ - 0, /* as_mapping */ - 0, /* hash */ - 0, /* call */ -}; - -static PyMethodDef rsaKey__methods__[] = { - {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS, - "Encrypt the given long."}, - {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS, - "Decrypt the given long."}, - {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS, - "Sign the given long."}, - {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS, - "Verify that the signature is valid."}, - {"size", (PyCFunction) rsaKey_size, METH_VARARGS, - "Return the number of bits that this key can handle."}, - {"hasprivate", (PyCFunction) rsaKey_hasprivate, METH_VARARGS, - "Return 1 or 0 if this key does/doesn't have a private key."}, - {NULL, NULL, 0, NULL} -}; - -PyObject * -rsaKey_new (PyObject * self, PyObject * args) -{ - PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; - rsaKey *key; - key = PyObject_New (rsaKey, &rsaKeyType); - mpz_init (key->n); - mpz_init (key->e); - mpz_init (key->d); - mpz_init (key->p); - mpz_init (key->q); - PyArg_ParseTuple (args, "O!O!|O!O!O!", &PyLong_Type, &n, - &PyLong_Type, &e, - &PyLong_Type, &d, &PyLong_Type, &p, &PyLong_Type, &q); - longObjToMPZ (key->n, n); - longObjToMPZ (key->e, e); - if (!d) - { - return (PyObject *) key; - } - longObjToMPZ (key->d, d); - if (p) - { - if (q) - { - longObjToMPZ (key->p, p); - longObjToMPZ (key->q, q); - } - } - /*Py_XDECREF(n); - Py_XDECREF(e); - Py_XDECREF(d); - Py_XDECREF(p); - Py_XDECREF(q); */ - return (PyObject *) key; -} - -static void -rsaKey_dealloc (rsaKey * key) -{ - mpz_clear (key->n); - mpz_clear (key->e); - mpz_clear (key->d); - mpz_clear (key->p); - mpz_clear (key->q); - PyObject_Del (key); -} - -static PyObject * -rsaKey_getattr (rsaKey * key, char *attr) -{ - if (strcmp (attr, "n") == 0) - return mpzToLongObj (key->n); - else if (strcmp (attr, "e") == 0) - return mpzToLongObj (key->e); - else if (strcmp (attr, "d") == 0) - { - if (mpz_size (key->d) == 0) - { - PyErr_SetString (PyExc_AttributeError, - "rsaKey instance has no attribute 'd'"); - return NULL; - } - return mpzToLongObj (key->d); - } - else if (strcmp (attr, "p") == 0) - { - if (mpz_size (key->p) == 0) - { - PyErr_SetString (PyExc_AttributeError, - "rsaKey instance has no attribute 'p'"); - return NULL; - } - return mpzToLongObj (key->p); - } - else if (strcmp (attr, "q") == 0) - { - if (mpz_size (key->q) == 0) - { - PyErr_SetString (PyExc_AttributeError, - "rsaKey instance has no attribute 'q'"); - return NULL; - } - return mpzToLongObj (key->q); - } - else - { - return Py_FindMethod (rsaKey__methods__, (PyObject *) key, attr); - } -} - -PyObject * -rsaKey__encrypt (rsaKey * key, PyObject * args) -{ - PyObject *l, *r; - mpz_t v; - int result; - if (!(PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))) - { - return NULL; - } - mpz_init (v); - longObjToMPZ (v, (PyLongObject *) l); - result = rsaEncrypt (key, v); - if (result == 1) - { - PyErr_SetString (rsaError, "Plaintext too large"); - return NULL; - } - r = (PyObject *) mpzToLongObj (v); - mpz_clear (v); - return Py_BuildValue ("N", r); -} - -PyObject * -rsaKey__decrypt (rsaKey * key, PyObject * args) -{ - PyObject *l, *r; - mpz_t v; - int result; - if (!(PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))) - { - return NULL; - } - mpz_init (v); - longObjToMPZ (v, (PyLongObject *) l); - result = rsaDecrypt (key, v); - if (result == 1) - { - PyErr_SetString (rsaError, "Ciphertext too large"); - return NULL; - } - else if (result == 2) - { - PyErr_SetString (rsaError, "Private key not available in this object"); - return NULL; - } - r = mpzToLongObj (v); - mpz_clear (v); - return Py_BuildValue ("N", r); -} - -PyObject * -rsaKey__verify (rsaKey * key, PyObject * args) -{ - PyObject *l, *lsig; - mpz_t v, vsig; - if (! - (PyArg_ParseTuple - (args, "O!O!", &PyLong_Type, &l, &PyLong_Type, &lsig))) - { - return NULL; - } - mpz_init (v); - mpz_init (vsig); - longObjToMPZ (v, (PyLongObject *) l); - longObjToMPZ (vsig, (PyLongObject *) lsig); - rsaEncrypt (key, vsig); - if (mpz_cmp (v, vsig) == 0) - return Py_BuildValue ("i", 1); - else - return Py_BuildValue ("i", 0); -} - -PyObject * -rsaKey_size (rsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1); -} - -PyObject * -rsaKey_hasprivate (rsaKey * key, PyObject * args) -{ - if (!PyArg_ParseTuple (args, "")) - return NULL; - if (mpz_size (key->d) == 0) - return Py_BuildValue ("i", 0); - else - return Py_BuildValue ("i", 1); -} - - -void -init_rsa (void) -{ - rsaKeyType.ob_type = &PyType_Type; - _rsa_module = Py_InitModule ("_rsa", _rsa__methods__); - _rsa_dict = PyModule_GetDict (_rsa_module); - rsaError = PyErr_NewException ("_rsa.error", NULL, NULL); - PyDict_SetItemString (_rsa_dict, "error", rsaError); -} diff --git a/Crypto/src/block_template.c b/Crypto/src/block_template.c deleted file mode 100644 index 37aa0453..00000000 --- a/Crypto/src/block_template.c +++ /dev/null @@ -1,750 +0,0 @@ - -/* -*- C -*- */ -/* - * block_template.c : Generic framework for block encryption algorithms - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. This software is provided "as is" without - * warranty of fitness for use or suitability for any purpose, express - * or implied. Use at your own risk or not at all. - * - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef _HAVE_STDC_HEADERS -#include -#endif - -#include "Python.h" -#include "modsupport.h" - -/* Cipher operation modes */ - -#define MODE_ECB 1 -#define MODE_CBC 2 -#define MODE_CFB 3 -#define MODE_PGP 4 -#define MODE_OFB 5 -#define MODE_CTR 6 - -#define _STR(x) #x -#define _XSTR(x) _STR(x) -#define _PASTE(x,y) x##y -#define _PASTE2(x,y) _PASTE(x,y) -#define _MODULE_NAME _PASTE2(init,MODULE_NAME) -#define _MODULE_STRING _XSTR(MODULE_NAME) - -typedef struct -{ - PyObject_HEAD - int mode, count, segment_size; - unsigned char IV[BLOCK_SIZE], oldCipher[BLOCK_SIZE]; - unsigned char ctrval[BLOCK_SIZE]; /* carries counter value between block crypt calls */ - unsigned char ctroffset; /* carries offset into current block between block crypt calls */ - block_state st; -} ALGobject; - -staticforward PyTypeObject ALGtype; - -#define is_ALGobject(v) ((v)->ob_type == &ALGtype) - -static ALGobject * -newALGobject(void) -{ - ALGobject * new; - new = PyObject_New(ALGobject, &ALGtype); - new->mode = MODE_ECB; - memset(new->ctrval, 0, BLOCK_SIZE); - new->ctroffset = 0; - return new; -} - -static void -ALGdealloc(PyObject *ptr) -{ - ALGobject *self = (ALGobject *)ptr; - - /* Overwrite the contents of the object */ - memset(self->IV, 0, BLOCK_SIZE); - memset(self->oldCipher, 0, BLOCK_SIZE); - memset((char*)&(self->st), 0, sizeof(block_state)); - memset(self->ctrval, 0, BLOCK_SIZE); - self->ctroffset = 0; - self->mode = self->count = self->segment_size = 0; - PyObject_Del(ptr); -} - - -static char ALGnew__doc__[] = -"new(key, [mode], [IV]): Return a new " _MODULE_STRING " encryption object."; - -static char *kwlist[] = {"key", "mode", "IV", "counterstart", "segment_size", -#ifdef PCT_RC5_MODULE - "version", "word_size", "rounds", -#endif - NULL}; - -static ALGobject * -ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) -{ - unsigned char *key, *IV; - ALGobject * new=NULL; - int keylen, IVlen=0, mode=MODE_ECB, segment_size=0; - PyObject *counterstart = NULL; -#ifdef PCT_RC5_MODULE - int version = 0x10, word_size = 32, rounds = 16; /*XXX default rounds? */ -#endif - /* Set default values */ - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#|is#Oi" -#ifdef PCT_RC5_MODULE - "iii" -#endif - , kwlist, - &key, &keylen, &mode, &IV, &IVlen, - &counterstart, &segment_size -#ifdef PCT_RC5_MODULE - , &version, &word_size, &rounds -#endif - )) - { - return NULL; - } - - if (KEY_SIZE!=0 && keylen!=KEY_SIZE) - { - PyErr_Format(PyExc_ValueError, - "Key must be %i bytes long, not %i", - KEY_SIZE, keylen); - return NULL; - } - if (KEY_SIZE==0 && keylen==0) - { - PyErr_SetString(PyExc_ValueError, - "Key cannot be the null string"); - return NULL; - } - if (IVlen != BLOCK_SIZE && IVlen != 0) - { - PyErr_Format(PyExc_ValueError, - "IV must be %i bytes long", BLOCK_SIZE); - return NULL; - } - if (modeMODE_CTR) - { - PyErr_Format(PyExc_ValueError, - "Unknown cipher feedback mode %i", - mode); - return NULL; - } - - /* Mode-specific checks */ - if (mode == MODE_CFB) { - if (segment_size == 0) segment_size = 8; - if (segment_size < 1 || segment_size > BLOCK_SIZE*8) { - PyErr_Format(PyExc_ValueError, - "segment_size must be multiple of 8 " - "between 1 and %i", BLOCK_SIZE); - } - } - - if (mode == MODE_CTR) { - if ((counterstart == NULL) || (!PyString_Check(counterstart))) { - PyErr_SetString(PyExc_ValueError, - "'counterstart' parameter is required to be a string"); - return NULL; - } - if (PyString_Size(counterstart) != BLOCK_SIZE) { - PyErr_SetString(PyExc_ValueError, - "'counterstart' parameter is required to be of length block size"); - return NULL; - } - } else { - if (counterstart != NULL) { - PyErr_SetString(PyExc_ValueError, - "'counterstart' parameter only useful with CTR mode"); - return NULL; - } - } - - /* Cipher-specific checks */ -#ifdef PCT_RC5_MODULE - if (version!=0x10) { - PyErr_Format(PyExc_ValueError, - "RC5: Bad RC5 algorithm version: %i", - version); - return NULL; - } - if (word_size!=16 && word_size!=32) { - PyErr_Format(PyExc_ValueError, - "RC5: Unsupported word size: %i", - word_size); - return NULL; - } - if (rounds<0 || 255segment_size = segment_size; - if ((counterstart != NULL) && PyString_Check(counterstart)) - { - assert (PyString_Size(counterstart) == BLOCK_SIZE); - memcpy(new->ctrval, PyString_AsString(counterstart), PyString_Size(counterstart)); - } -#ifdef PCT_RC5_MODULE - new->st.version = version; - new->st.word_size = word_size; - new->st.rounds = rounds; -#endif - - block_init(&(new->st), key, keylen); - if (PyErr_Occurred()) - { - Py_DECREF(new); - return NULL; - } - memset(new->IV, 0, BLOCK_SIZE); - memset(new->oldCipher, 0, BLOCK_SIZE); - memcpy(new->IV, IV, IVlen); - new->mode = mode; - new->count=8; - return new; -} - -static char ALG_Encrypt__doc__[] = -"Encrypt the provided string of binary data."; - -/* - * Treat the data in buf as an big-endian unsigned integer and increment it - * mod 2^(bytes*8). - */ -void -increment_unsigned(unsigned char*buf, size_t bytes) -{ - unsigned char* p = buf + bytes - 1; - while (*p == 255) - { - *p += 1; - /* carry */ - if (p == buf) - return; - p--; - } - *p += 1; -} - -static void -ctr_crypt(ALGobject *const self, const unsigned char*const str, unsigned char*const buffer, const int len) -{ - int i = 0; /* always points to the next byte of str which is to be crypted */ - unsigned char temp[BLOCK_SIZE]; - - while (i < len) - { - /* This loop is per block. */ - block_encrypt(&(self->st), self->ctrval, temp); - - while (self->ctroffset < BLOCK_SIZE) - { - if (i == len) - return; /* finished */ - /* This loop is per byte. */ - buffer[i] = str[i]^temp[self->ctroffset]; - i++; self->ctroffset++; - } - - increment_unsigned(self->ctrval, BLOCK_SIZE); - self->ctroffset = 0; - } -} - -static PyObject * -ALG_Encrypt(ALGobject *self, PyObject *args) -{ - unsigned char *buffer, *str; - unsigned char temp[BLOCK_SIZE]; - int i, j, len; - PyObject *result; - - if (!PyArg_Parse(args, "s#", &str, &len)) - return NULL; - if (len==0) /* Handle empty string */ - { - return PyString_FromStringAndSize(NULL, 0); - } - if ( (len % BLOCK_SIZE) !=0 && - (self->mode!=MODE_CFB) && (self->mode!=MODE_PGP) && self->mode!=MODE_CTR) - { - PyErr_Format(PyExc_ValueError, - "Input strings must be " - "a multiple of %i in length", - BLOCK_SIZE); - return NULL; - } - if (self->mode == MODE_CFB && - (len % (self->segment_size/8) !=0)) { - PyErr_Format(PyExc_ValueError, - "Input strings must be a multiple of " - "the segment size %i in length", - self->segment_size/8); - return NULL; - } - - buffer=malloc(len); - if (buffer==NULL) - { - PyErr_SetString(PyExc_MemoryError, - "No memory available in " - _MODULE_STRING " encrypt"); - return NULL; - } - switch(self->mode) - { - case(MODE_ECB): - for(i=0; ist), str+i, buffer+i); - } - break; - - case(MODE_CBC): - for(i=0; iIV[j]; - } - block_encrypt(&(self->st), temp, buffer+i); - memcpy(self->IV, buffer+i, BLOCK_SIZE); - } - break; - - case(MODE_CFB): - for(i=0; isegment_size/8) - { - block_encrypt(&(self->st), self->IV, temp); - for (j=0; jsegment_size/8; j++) { - buffer[i+j] = str[i+j] ^ temp[j]; - } - if (self->segment_size == BLOCK_SIZE * 8) { - /* s == b: segment size is identical to - the algorithm block size */ - memcpy(self->IV, buffer + i, BLOCK_SIZE); - } - else if ((self->segment_size % 8) == 0) { - int sz = self->segment_size/8; - memmove(self->IV, self->IV + sz, - BLOCK_SIZE-sz); - memcpy(self->IV + BLOCK_SIZE - sz, buffer + i, - sz); - } - else { - /* segment_size is not a multiple of 8; - currently this can't happen */ - } - } - break; - - case(MODE_PGP): - if (len<=BLOCK_SIZE-self->count) - { - /* If less than one block, XOR it in */ - for(i=0; iIV[self->count+i] ^= str[i]; - self->count += len; - } - else - { - int j; - for(i=0; icount; i++) - buffer[i] = self->IV[self->count+i] ^= str[i]; - self->count=0; - for(; ist), self->oldCipher, - self->IV); - for(j=0; jIV[j] ^= str[i+j]; - } - /* Do the remaining 1 to BLOCK_SIZE bytes */ - block_encrypt(&(self->st), self->oldCipher, self->IV); - self->count=len-i; - for(j=0; jIV[j] ^= str[i+j]; - } - } - break; - - case(MODE_OFB): - for(i=0; ist), self->IV, temp); - memcpy(self->IV, temp, BLOCK_SIZE); - for(j=0; jmode); - free(buffer); - return NULL; - } - result=PyString_FromStringAndSize(buffer, len); - free(buffer); - return(result); -} - -static char ALG_Decrypt__doc__[] = -"decrypt(string): Decrypt the provided string of binary data."; - - -static PyObject * -ALG_Decrypt(ALGobject *self, PyObject *args) -{ - unsigned char *buffer, *str; - unsigned char temp[BLOCK_SIZE]; - int i, j, len; - PyObject *result; - - if (!PyArg_Parse(args, "s#", &str, &len)) - return NULL; - if (len==0) /* Handle empty string */ - { - return PyString_FromStringAndSize(NULL, 0); - } - if ( (len % BLOCK_SIZE) !=0 && - (self->mode!=MODE_CFB && self->mode!=MODE_PGP && self->mode!=MODE_CTR)) - { - PyErr_Format(PyExc_ValueError, - "Input strings must be " - "a multiple of %i in length", - BLOCK_SIZE); - return NULL; - } - if (self->mode == MODE_CFB && - (len % (self->segment_size/8) !=0)) { - PyErr_Format(PyExc_ValueError, - "Input strings must be a multiple of " - "the segment size %i in length", - self->segment_size/8); - return NULL; - } - buffer=malloc(len); - if (buffer==NULL) - { - PyErr_SetString(PyExc_MemoryError, - "No memory available in " _MODULE_STRING - " decrypt"); - return NULL; - } - switch(self->mode) - { - case(MODE_ECB): - for(i=0; ist), str+i, buffer+i); - } - break; - - case(MODE_CBC): - for(i=0; ioldCipher, self->IV, BLOCK_SIZE); - block_decrypt(&(self->st), str+i, temp); - for(j=0; jIV[j]; - self->IV[j]=str[i+j]; - } - } - break; - - case(MODE_CFB): - for(i=0; isegment_size/8) - { - block_encrypt(&(self->st), self->IV, temp); - for (j=0; jsegment_size/8; j++) { - buffer[i+j] = str[i+j]^temp[j]; - } - if (self->segment_size == BLOCK_SIZE * 8) { - /* s == b: segment size is identical to - the algorithm block size */ - memcpy(self->IV, str + i, BLOCK_SIZE); - } - else if ((self->segment_size % 8) == 0) { - int sz = self->segment_size/8; - memmove(self->IV, self->IV + sz, - BLOCK_SIZE-sz); - memcpy(self->IV + BLOCK_SIZE - sz, str + i, - sz); - } - else { - /* segment_size is not a multiple of 8; - currently this can't happen */ - } - } - break; - - case(MODE_PGP): - if (len<=BLOCK_SIZE-self->count) - { - /* If less than one block, XOR it in */ - unsigned char t; - for(i=0; iIV[self->count+i]; - buffer[i] = t ^ (self->IV[self->count+i] = str[i]); - } - self->count += len; - } - else - { - int j; - unsigned char t; - for(i=0; icount; i++) - { - t=self->IV[self->count+i]; - buffer[i] = t ^ (self->IV[self->count+i] = str[i]); - } - self->count=0; - for(; ist), self->oldCipher, self->IV); - for(j=0; jIV[j]; - buffer[i+j] = t ^ (self->IV[j] = str[i+j]); - } - } - /* Do the remaining 1 to BLOCK_SIZE bytes */ - block_encrypt(&(self->st), self->oldCipher, self->IV); - self->count=len-i; - for(j=0; jIV[j]; - buffer[i+j] = t ^ (self->IV[j] = str[i+j]); - } - } - break; - - case (MODE_OFB): - for(i=0; ist), self->IV, temp); - memcpy(self->IV, temp, BLOCK_SIZE); - for(j=0; jIV[j]; - } - } - break; - - case (MODE_CTR): - ctr_crypt(self, str, buffer, len); - break; - - default: - PyErr_Format(PyExc_SystemError, - "Unknown ciphertext feedback mode %i; " - "this shouldn't happen", - self->mode); - free(buffer); - return NULL; - } - result=PyString_FromStringAndSize(buffer, len); - free(buffer); - return(result); -} - -static char ALG_Sync__doc__[] = -"sync(): For objects using the PGP feedback mode, this method modifies " -"the IV, synchronizing it with the preceding ciphertext."; - -static PyObject * -ALG_Sync(ALGobject *self, PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) { - return NULL; - } - - if (self->mode!=MODE_PGP) - { - PyErr_SetString(PyExc_SystemError, "sync() operation not defined for " - "this feedback mode"); - return NULL; - } - - if (self->count!=8) - { - memmove(self->IV+BLOCK_SIZE-self->count, self->IV, - self->count); - memcpy(self->IV, self->oldCipher+self->count, - BLOCK_SIZE-self->count); - self->count=8; - } - Py_INCREF(Py_None); - return Py_None; -} - -#if 0 -void PrintState(self, msg) - ALGobject *self; - char * msg; -{ - int count; - - printf("%sing: %i IV ", msg, (int)self->count); - for(count=0; count<8; count++) printf("%i ", self->IV[count]); - printf("\noldCipher:"); - for(count=0; count<8; count++) printf("%i ", self->oldCipher[count]); - printf("\n"); -} -#endif - - -/* ALG object methods */ - -static PyMethodDef ALGmethods[] = -{ - {"encrypt", (PyCFunction) ALG_Encrypt, 0, ALG_Encrypt__doc__}, - {"decrypt", (PyCFunction) ALG_Decrypt, 0, ALG_Decrypt__doc__}, - {"sync", (PyCFunction) ALG_Sync, METH_VARARGS, ALG_Sync__doc__}, - {NULL, NULL} /* sentinel */ -}; - - -static int -ALGsetattr(PyObject *ptr, char *name, PyObject *v) -{ - ALGobject *self=(ALGobject *)ptr; - if (strcmp(name, "IV") != 0) - { - PyErr_Format(PyExc_AttributeError, - "non-existent block cipher object attribute '%s'", - name); - return -1; - } - if (v==NULL) - { - PyErr_SetString(PyExc_AttributeError, - "Can't delete IV attribute of block cipher object"); - return -1; - } - if (!PyString_Check(v)) - { - PyErr_SetString(PyExc_TypeError, - "IV attribute of block cipher object must be string"); - return -1; - } - if (PyString_Size(v)!=BLOCK_SIZE) - { - PyErr_Format(PyExc_ValueError, - _MODULE_STRING " IV must be %i bytes long", - BLOCK_SIZE); - return -1; - } - memcpy(self->IV, PyString_AsString(v), BLOCK_SIZE); - return 0; -} - -static PyObject * -ALGgetattr(PyObject *s, char *name) -{ - ALGobject *self = (ALGobject*)s; - if (strcmp(name, "IV") == 0) - { - return(PyString_FromStringAndSize(self->IV, BLOCK_SIZE)); - } - if (strcmp(name, "mode") == 0) - { - return(PyInt_FromLong((long)(self->mode))); - } - if (strcmp(name, "block_size") == 0) - { - return PyInt_FromLong(BLOCK_SIZE); - } - if (strcmp(name, "key_size") == 0) - { - return PyInt_FromLong(KEY_SIZE); - } - return Py_FindMethod(ALGmethods, (PyObject *) self, name); -} - -/* List of functions defined in the module */ - -static struct PyMethodDef modulemethods[] = -{ - {"new", (PyCFunction) ALGnew, METH_VARARGS|METH_KEYWORDS, ALGnew__doc__}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject ALGtype = -{ - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - _MODULE_STRING, /*tp_name*/ - sizeof(ALGobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - ALGdealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - ALGgetattr, /*tp_getattr*/ - ALGsetattr, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc) 0, /*tp_repr*/ - 0, /*tp_as_number*/ -}; - -/* Initialization function for the module */ - -#if PYTHON_API_VERSION < 1011 -#define PyModule_AddIntConstant(m,n,v) {PyObject *o=PyInt_FromLong(v); \ - if (o!=NULL) \ - {PyDict_SetItemString(PyModule_GetDict(m),n,o); Py_DECREF(o);}} -#endif - -void -_MODULE_NAME (void) -{ - PyObject *m; - - ALGtype.ob_type = &PyType_Type; - - /* Create the module and add the functions */ - m = Py_InitModule("Crypto.Cipher." _MODULE_STRING, modulemethods); - - PyModule_AddIntConstant(m, "MODE_ECB", MODE_ECB); - PyModule_AddIntConstant(m, "MODE_CBC", MODE_CBC); - PyModule_AddIntConstant(m, "MODE_CFB", MODE_CFB); - PyModule_AddIntConstant(m, "MODE_PGP", MODE_PGP); - PyModule_AddIntConstant(m, "MODE_OFB", MODE_OFB); - PyModule_AddIntConstant(m, "MODE_CTR", MODE_CTR); - PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); - PyModule_AddIntConstant(m, "key_size", KEY_SIZE); - - /* Check for errors */ - if (PyErr_Occurred()) - Py_FatalError("can't initialize module " _MODULE_STRING); -} - diff --git a/Crypto/src/cast5.c b/Crypto/src/cast5.c deleted file mode 100644 index 0843b98d..00000000 --- a/Crypto/src/cast5.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - These are the S-boxes for CAST5 as given in RFC 2144. -*/ - - -static const uint32 S1[256] = { -0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, -0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, -0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, -0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, -0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, -0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, -0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, -0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, -0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, -0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, -0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, -0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, -0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, -0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, -0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, -0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, -0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, -0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, -0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, -0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, -0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, -0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, -0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, -0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, -0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, -0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, -0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, -0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, -0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, -0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, -0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, -0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, -0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, -0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, -0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, -0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, -0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, -0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, -0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, -0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, -0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, -0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, -0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, -0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, -0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, -0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, -0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, -0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, -0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, -0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, -0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, -0x5c8165bf }; - -static const uint32 S2[256] = { -0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, -0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, -0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, -0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, -0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, -0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, -0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, -0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, -0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, -0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, -0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, -0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, -0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, -0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, -0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, -0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, -0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, -0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, -0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, -0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, -0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, -0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, -0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, -0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, -0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, -0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, -0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, -0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, -0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, -0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, -0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, -0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, -0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, -0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, -0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, -0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, -0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, -0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, -0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, -0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, -0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, -0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, -0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, -0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, -0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, -0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, -0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, -0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, -0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, -0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, -0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, -0x4523ecf1 }; - -static const uint32 S3[256] = { -0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, -0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, -0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, -0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, -0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, -0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, -0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, -0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, -0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, -0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, -0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, -0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, -0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, -0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, -0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, -0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, -0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, -0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, -0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, -0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, -0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, -0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, -0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, -0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, -0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, -0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, -0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, -0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, -0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, -0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, -0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, -0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, -0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, -0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, -0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, -0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, -0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, -0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, -0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, -0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, -0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, -0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, -0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, -0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, -0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, -0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, -0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, -0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, -0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, -0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, -0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, -0xee353783 }; - -static const uint32 S4[256] = { -0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, -0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, -0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, -0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, -0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, -0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, -0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, -0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, -0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, -0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, -0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, -0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, -0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, -0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, -0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, -0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, -0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, -0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, -0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, -0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, -0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, -0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, -0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, -0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, -0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, -0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, -0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, -0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, -0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, -0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, -0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, -0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, -0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, -0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, -0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, -0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, -0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, -0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, -0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, -0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, -0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, -0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, -0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, -0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, -0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, -0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, -0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, -0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, -0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, -0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, -0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, -0x0aef7ed2 }; - -static const uint32 S5[256] = { -0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, -0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, -0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, -0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, -0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, -0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, -0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, -0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, -0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, -0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, -0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, -0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, -0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, -0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, -0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, -0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, -0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, -0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, -0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, -0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, -0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, -0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, -0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, -0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, -0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, -0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, -0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, -0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, -0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, -0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, -0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, -0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, -0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, -0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, -0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, -0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, -0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, -0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, -0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, -0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, -0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, -0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, -0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, -0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, -0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, -0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, -0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, -0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, -0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, -0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, -0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, -0xefe9e7d4 }; - -static const uint32 S6[256] = { -0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, -0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, -0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, -0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, -0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, -0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, -0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, -0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, -0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, -0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, -0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, -0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, -0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, -0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, -0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, -0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, -0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, -0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, -0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, -0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, -0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, -0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, -0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, -0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, -0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, -0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, -0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, -0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, -0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, -0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, -0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, -0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, -0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, -0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, -0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, -0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, -0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, -0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, -0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, -0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, -0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, -0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, -0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, -0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, -0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, -0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, -0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, -0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, -0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, -0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, -0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, -0xd675cf2f }; - -static const uint32 S7[256] = { -0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, -0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, -0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, -0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, -0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, -0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, -0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, -0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, -0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, -0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, -0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, -0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, -0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, -0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, -0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, -0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, -0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, -0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, -0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, -0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, -0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, -0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, -0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, -0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, -0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, -0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, -0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, -0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, -0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, -0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, -0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, -0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, -0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, -0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, -0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, -0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, -0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, -0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, -0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, -0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, -0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, -0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, -0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, -0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, -0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, -0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, -0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, -0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, -0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, -0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, -0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, -0x954b8aa3 }; - -static const uint32 S8[256] = { -0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, -0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, -0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, -0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, -0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, -0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, -0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, -0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, -0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, -0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, -0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, -0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, -0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, -0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, -0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, -0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, -0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, -0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, -0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, -0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, -0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, -0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, -0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, -0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, -0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, -0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, -0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, -0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, -0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, -0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, -0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, -0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, -0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, -0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, -0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, -0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, -0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, -0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, -0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, -0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, -0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, -0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, -0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, -0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, -0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, -0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, -0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, -0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, -0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, -0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, -0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, -0xea8bf59e }; - diff --git a/Crypto/src/hash_template.c b/Crypto/src/hash_template.c deleted file mode 100644 index 6662dd54..00000000 --- a/Crypto/src/hash_template.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * hash_template.c : Generic framework for hash function extension modules - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. This software is provided "as is" without - * warranty of fitness for use or suitability for any purpose, express - * or implied. Use at your own risk or not at all. - * - */ - -/* Basic object type */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef _HAVE_STDC_HEADERS -#include -#endif - -#define _STR(x) #x -#define _XSTR(x) _STR(x) -#define _PASTE(x,y) x##y -#define _PASTE2(x,y) _PASTE(x,y) -#define _MODULE_NAME _PASTE2(init,MODULE_NAME) -#define _MODULE_STRING _XSTR(MODULE_NAME) - -typedef struct { - PyObject_HEAD - hash_state st; -} ALGobject; - -staticforward PyTypeObject ALGtype; - -#define is_ALGobject(v) ((v)->ob_type == &ALGtype) - -static ALGobject * -newALGobject(void) -{ - ALGobject *new; - - new = PyObject_New(ALGobject, &ALGtype); - return new; -} - -/* Internal methods for a hashing object */ - -static void -ALG_dealloc(PyObject *ptr) -{ - ALGobject *self = (ALGobject *)ptr; - - /* Overwrite the contents of the object */ - memset((char*)&(self->st), 0, sizeof(hash_state)); - PyObject_Del(ptr); -} - - -/* External methods for a hashing object */ - -static char ALG_copy__doc__[] = -"copy(): Return a copy of the hashing object."; - -static PyObject * -ALG_copy(ALGobject *self, PyObject *args) -{ - ALGobject *newobj; - - if (!PyArg_ParseTuple(args, "")) { - return NULL; - } - - if ( (newobj = newALGobject())==NULL) - return NULL; - - hash_copy(&(self->st), &(newobj->st)); - return((PyObject *)newobj); -} - -static char ALG_digest__doc__[] = -"digest(): Return the digest value as a string of binary data."; - -static PyObject * -ALG_digest(ALGobject *self, PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) - return NULL; - - return (PyObject *)hash_digest(&(self->st)); -} - -static char ALG_hexdigest__doc__[] = -"hexdigest(): Return the digest value as a string of hexadecimal digits."; - -static PyObject * -ALG_hexdigest(ALGobject *self, PyObject *args) -{ - PyObject *value, *retval; - unsigned char *raw_digest, *hex_digest; - int i, j, size; - - if (!PyArg_ParseTuple(args, "")) - return NULL; - - /* Get the raw (binary) digest value */ - value = (PyObject *)hash_digest(&(self->st)); - size = PyString_Size(value); - raw_digest = PyString_AsString(value); - - /* Create a new string */ - retval = PyString_FromStringAndSize(NULL, size * 2 ); - hex_digest = PyString_AsString(retval); - - /* Make hex version of the digest */ - for(i=j=0; i9) ? c+'a'-10 : c + '0'; - hex_digest[j++] = c; - c = raw_digest[i] % 16; c = (c>9) ? c+'a'-10 : c + '0'; - hex_digest[j++] = c; - } - Py_DECREF(value); - return retval; -} - -static char ALG_update__doc__[] = -"update(string): Update this hashing object's state with the provided string."; - -static PyObject * -ALG_update(ALGobject *self, PyObject *args) -{ - unsigned char *cp; - int len; - - if (!PyArg_ParseTuple(args, "s#", &cp, &len)) - return NULL; - - hash_update(&(self->st), cp, len); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef ALG_methods[] = { - {"copy", (PyCFunction)ALG_copy, METH_VARARGS, ALG_copy__doc__}, - {"digest", (PyCFunction)ALG_digest, METH_VARARGS, ALG_digest__doc__}, - {"hexdigest", (PyCFunction)ALG_hexdigest, METH_VARARGS, - ALG_hexdigest__doc__}, - {"update", (PyCFunction)ALG_update, METH_VARARGS, ALG_update__doc__}, - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -ALG_getattr(PyObject *self, char *name) -{ - if (strcmp(name, "digest_size")==0) - return PyInt_FromLong(DIGEST_SIZE); - - return Py_FindMethod(ALG_methods, self, name); -} - -static PyTypeObject ALGtype = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - _MODULE_STRING, /*tp_name*/ - sizeof(ALGobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - ALG_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - ALG_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ -}; - - -/* The single module-level function: new() */ - -static char ALG_new__doc__[] = -"new([string]): Return a new " _MODULE_STRING -" hashing object. An optional string " -"argument may be provided; if present, this string will be " -"automatically hashed into the initial state of the object."; - -static PyObject * -ALG_new(PyObject *self, PyObject *args) -{ - ALGobject *new; - unsigned char *cp = NULL; - int len; - - if ((new = newALGobject()) == NULL) - return NULL; - - if (!PyArg_ParseTuple(args, "|s#", - &cp, &len)) { - Py_DECREF(new); - return NULL; - } - - hash_init(&(new->st)); - - if (PyErr_Occurred()) { - Py_DECREF(new); - return NULL; - } - if (cp) - hash_update(&(new->st), cp, len); - - return (PyObject *)new; -} - - -/* List of functions exported by this module */ - -static struct PyMethodDef ALG_functions[] = { - {"new", (PyCFunction)ALG_new, METH_VARARGS, ALG_new__doc__}, - {NULL, NULL} /* Sentinel */ -}; - - -/* Initialize this module. */ - -#if PYTHON_API_VERSION < 1011 -#define PyModule_AddIntConstant(m,n,v) {PyObject *o=PyInt_FromLong(v); \ - if (o!=NULL) \ - {PyDict_SetItemString(PyModule_GetDict(m),n,o); Py_DECREF(o);}} -#endif - -void -_MODULE_NAME (void) -{ - PyObject *m; - - ALGtype.ob_type = &PyType_Type; - m = Py_InitModule("Crypto.Hash." _MODULE_STRING, ALG_functions); - - /* Add some symbolic constants to the module */ - PyModule_AddIntConstant(m, "digest_size", DIGEST_SIZE); - - /* Check for errors */ - if (PyErr_Occurred()) - Py_FatalError("can't initialize module " - _MODULE_STRING); -} diff --git a/Crypto/src/stream_template.c b/Crypto/src/stream_template.c deleted file mode 100644 index 71d125c1..00000000 --- a/Crypto/src/stream_template.c +++ /dev/null @@ -1,248 +0,0 @@ -/* -*- C -*- */ - -/* - * stream_template.c : Generic framework for stream ciphers - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. This software is provided "as is" without - * warranty of fitness for use or suitability for any purpose, express - * or implied. Use at your own risk or not at all. - * - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef _HAVE_STDC_HEADERS -#include -#endif - -#include "Python.h" -#include "modsupport.h" - -#define _STR(x) #x -#define _XSTR(x) _STR(x) -#define _PASTE(x,y) x##y -#define _PASTE2(x,y) _PASTE(x,y) -#define _MODULE_NAME _PASTE2(init,MODULE_NAME) -#define _MODULE_STRING _XSTR(MODULE_NAME) - - /* - * - * Python interface - * - */ - -typedef struct -{ - PyObject_HEAD - stream_state st; -} ALGobject; - -staticforward PyTypeObject ALGtype; - -#define is_ALGobject(v) ((v)->ob_type == &ALGtype) - -static ALGobject * -newALGobject(void) -{ - ALGobject * new; - new = PyObject_New(ALGobject, &ALGtype); - return new; -} - -static void -ALGdealloc(PyObject *ptr) -{ - ALGobject *self = (ALGobject *)ptr; - - /* Overwrite the contents of the object */ - memset((char*)&(self->st), 0, sizeof(stream_state)); - PyObject_Del(ptr); -} - -static char ALGnew__doc__[] = -"Return a new " _MODULE_STRING " encryption object."; - -static char *kwlist[] = {"key", NULL}; - -static ALGobject * -ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) -{ - unsigned char *key; - ALGobject * new; - int keylen; - - new = newALGobject(); - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#", kwlist, - &key, &keylen)) - { - Py_DECREF(new); - return NULL; - } - - if (KEY_SIZE!=0 && keylen != KEY_SIZE) - { - PyErr_SetString(PyExc_ValueError, - _MODULE_STRING " key must be " - "KEY_SIZE bytes long"); - return NULL; - } - if (KEY_SIZE== 0 && keylen == 0) - { - PyErr_SetString(PyExc_ValueError, - _MODULE_STRING " key cannot be " - "the null string (0 bytes long)"); - return NULL; - } - stream_init(&(new->st), key, keylen); - if (PyErr_Occurred()) - { - Py_DECREF(new); - return NULL; - } - return new; -} - -static char ALG_Encrypt__doc__[] = -"Decrypt the provided string of binary data."; - -static PyObject * -ALG_Encrypt(ALGobject *self, PyObject *args) -{ - unsigned char *buffer, *str; - int len; - PyObject *result; - - if (!PyArg_Parse(args, "s#", &str, &len)) - return NULL; - if (len == 0) /* Handle empty string */ - { - return PyString_FromStringAndSize(NULL, 0); - } - buffer = malloc(len); - if (buffer == NULL) - { - PyErr_SetString(PyExc_MemoryError, "No memory available in " - _MODULE_STRING " encrypt"); - return NULL; - } - memcpy(buffer, str, len); - stream_encrypt(&(self->st), buffer, len); - result = PyString_FromStringAndSize(buffer, len); - free(buffer); - return (result); -} - -static char ALG_Decrypt__doc__[] = -"decrypt(string): Decrypt the provided string of binary data."; - -static PyObject * -ALG_Decrypt(ALGobject *self, PyObject *args) -{ - char *buffer, *str; - int len; - PyObject *result; - - if (!PyArg_Parse(args, "s#", &str, &len)) - return NULL; - if (len == 0) /* Handle empty string */ - { - return PyString_FromStringAndSize(NULL, 0); - } - buffer = malloc(len); - if (buffer == NULL) - { - PyErr_SetString(PyExc_MemoryError, "No memory available in " - _MODULE_STRING " decrypt"); - return NULL; - } - memcpy(buffer, str, len); - stream_decrypt(&(self->st), buffer, len); - result = PyString_FromStringAndSize(buffer, len); - free(buffer); - return (result); -} - -/* ALGobject methods */ - -static PyMethodDef ALGmethods[] = -{ - {"encrypt", (PyCFunction) ALG_Encrypt, 0, ALG_Encrypt__doc__}, - {"decrypt", (PyCFunction) ALG_Decrypt, 0, ALG_Decrypt__doc__}, - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -ALGgetattr(PyObject *self, char *name) -{ - if (strcmp(name, "block_size") == 0) - { - return PyInt_FromLong(BLOCK_SIZE); - } - if (strcmp(name, "key_size") == 0) - { - return PyInt_FromLong(KEY_SIZE); - } - return Py_FindMethod(ALGmethods, self, name); -} - - -/* List of functions defined in the module */ - -static struct PyMethodDef modulemethods[] = -{ - {"new", (PyCFunction) ALGnew, - METH_VARARGS|METH_KEYWORDS, ALGnew__doc__}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject ALGtype = -{ - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - _MODULE_STRING, /*tp_name*/ - sizeof(ALGobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - ALGdealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - ALGgetattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ -}; - -/* Initialization function for the module */ - -#if PYTHON_API_VERSION < 1011 -#define PyModule_AddIntConstant(m,n,v) {PyObject *o=PyInt_FromLong(v); \ - if (o!=NULL) \ - {PyDict_SetItemString(PyModule_GetDict(m),n,o); Py_DECREF(o);}} -#endif - -void -_MODULE_NAME (void) -{ - PyObject *m, *d, *x; - - ALGtype.ob_type = &PyType_Type; - /* Create the module and add the functions */ - m = Py_InitModule("Crypto.Cipher." _MODULE_STRING, modulemethods); - - /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); - x = PyString_FromString(_MODULE_STRING ".error"); - PyDict_SetItemString(d, "error", x); - - PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); - PyModule_AddIntConstant(m, "key_size", KEY_SIZE); - - /* Check for errors */ - if (PyErr_Occurred()) - Py_FatalError("can't initialize module " _MODULE_STRING); -} diff --git a/Crypto/src/winrand.c b/Crypto/src/winrand.c deleted file mode 100644 index 8c82bd45..00000000 --- a/Crypto/src/winrand.c +++ /dev/null @@ -1,366 +0,0 @@ -/* -*- C -*- */ -/* - * Uses Windows CryptoAPI CryptGenRandom to get random bytes. - * The "new" method returns an object, whose "get_bytes" method - * can be called repeatedly to get random bytes, seeded by the - * OS. See the description in the comment at the end. - * - * If you have the Intel Security Driver header files (icsp4ms.h) - * for their hardware random number generator in the 810 and 820 chipsets, - * then define HAVE_INTEL_RNG. - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. This software is provided "as is" without - * warranty of fitness for use or suitability for any purpose, express - * or implied. Use at your own risk or not at all. - * - */ - -/* Author: Mark Moraes */ - -#include "Python.h" - -#ifdef MS_WIN32 - -#define _WIN32_WINNT 0x400 -#define WINSOCK - -#include -#include - -#ifdef HAVE_INTEL_RNG -# include "icsp4ms.h" -#else -# define PROV_INTEL_SEC 22 -# define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider" -#endif - -/* To-Do: store provider name and type for print/repr? */ -typedef struct -{ - PyObject_HEAD - HCRYPTPROV hcp; -} WRobject; - -staticforward PyTypeObject WRtype; - -#define is_WRobject(v) ((v)->ob_type == &WRtype) - -static void -WRdealloc(PyObject *ptr) -{ - WRobject *o = (WRobject *)ptr; - - if (! is_WRobject(ptr)) { - PyErr_Format(PyExc_TypeError, - "WinRandom trying to dealloc non-WinRandom object"); - return; - } - if (! CryptReleaseContext(o->hcp, 0)) { - PyErr_Format(PyExc_SystemError, - "CryptReleaseContext failed, error 0x%x", - GetLastError()); - return; - } - /* Overwrite the contents of the object */ - o->hcp = 0; - PyObject_Del(ptr); -} - -static char winrandom__doc__[] = -"new([provider], [provtype]): Returns an object handle to Windows\n\ -CryptoAPI that can be used to access a cryptographically strong\n\ -pseudo-random generator that uses OS-gathered entropy.\n\ -Provider is a string that specifies the Cryptographic Service Provider\n\ -to use, default is the default OS CSP.\n\ -provtype is an integer specifying the provider type to use, default\n\ -is 1 (PROV_RSA_FULL)"; - -static char WR_get_bytes__doc__[] = -"get_bytes(nbytes, [userdata]]): Returns nbytes of random data\n\ -from Windows CryptGenRandom.\n\ -userdata is a string with any additional entropic data that the\n\ -user wishes to provide."; - -static WRobject * -winrandom_new(PyObject *self, PyObject *args, PyObject *kwdict) -{ - HCRYPTPROV hcp = 0; - WRobject *res; - char *provname = NULL; - int provtype = PROV_RSA_FULL; - static char *kwlist[] = { "provider", "provtype", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|si", kwlist, - &provname, &provtype)) { - return NULL; - } - if (! CryptAcquireContext(&hcp, NULL, (LPCTSTR) provname, - (DWORD) provtype, 0)) { - PyErr_Format(PyExc_SystemError, - "CryptAcquireContext for provider \"%s\" type %i failed, error 0x%x", - provname? provname : "(null)", provtype, - GetLastError()); - return NULL; - } - res = PyObject_New(WRobject, &WRtype); - res->hcp = hcp; - return res; -} - -static PyObject * -WR_get_bytes(WRobject *self, PyObject *args) -{ - HCRYPTPROV hcp = 0; - int n, nbytes, len = 0; - PyObject *res; - char *buf, *str = NULL; - - if (! is_WRobject(self)) { - PyErr_Format(PyExc_TypeError, - "WinRandom trying to get_bytes with non-WinRandom object"); - return NULL; - } - if (!PyArg_ParseTuple(args, "i|s#", &n, &str, &len)) { - return NULL; - } - if (n <= 0) { - PyErr_SetString(PyExc_ValueError, "nbytes must be positive number"); - return NULL; - } - /* Just in case char != BYTE, or userdata > desired result */ - nbytes = (((n > len) ? n : len) * sizeof(char)) / sizeof(BYTE) + 1; - if ((buf = (char *) PyMem_Malloc(nbytes)) == NULL) - return PyErr_NoMemory(); - if (len > 0) - memcpy(buf, str, len); - /* - * if userdata > desired result, we end up getting - * more bytes than we really needed to return. No - * easy way to avoid that: we prefer that - * CryptGenRandom does the distillation of userdata - * down to entropy, rather than trying to do it - * ourselves. Since the extra bytes presumably come - * from an RC4 stream, they should be relatively - * cheap. - */ - if (! CryptGenRandom(self->hcp, (DWORD) nbytes, (BYTE *) buf)) { - PyErr_Format(PyExc_SystemError, - "CryptGenRandom failed, error 0x%x", - GetLastError()); - PyMem_Free(buf); - return NULL; - } - res = PyString_FromStringAndSize(buf, n); - PyMem_Free(buf); - return res; -} - -/* WinRandom object methods */ - -static PyMethodDef WRmethods[] = -{ - {"get_bytes", (PyCFunction) WR_get_bytes, METH_VARARGS, - WR_get_bytes__doc__}, - {NULL, NULL} /* sentinel */ -}; - -/* winrandom module methods */ - -static PyMethodDef WR_mod_methods[] = { - {"new", (PyCFunction) winrandom_new, METH_VARARGS|METH_KEYWORDS, - winrandom__doc__}, - {NULL, NULL} /* Sentinel */ -}; - - -static PyObject * -WRgetattr(PyObject *s, char *name) -{ - WRobject *self = (WRobject*)s; - if (! is_WRobject(self)) { - PyErr_Format(PyExc_TypeError, - "WinRandom trying to getattr with non-WinRandom object"); - return NULL; - } - if (strcmp(name, "hcp") == 0) - return PyInt_FromLong((long) self->hcp); - return Py_FindMethod(WRmethods, (PyObject *) self, name); -} - -static PyTypeObject WRtype = -{ - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "winrandom.WinRandom", /*tp_name*/ - sizeof(WRobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - WRdealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - WRgetattr, /*tp_getattr*/ -}; - -void -initwinrandom() -{ - PyObject *m; - WRtype.ob_type = &PyType_Type; - m = Py_InitModule("winrandom", WR_mod_methods); - - /* define Windows CSP Provider Types */ -#ifdef PROV_RSA_FULL - PyModule_AddIntConstant(m, "PROV_RSA_FULL", PROV_RSA_FULL); -#endif -#ifdef PROV_RSA_SIG - PyModule_AddIntConstant(m, "PROV_RSA_SIG", PROV_RSA_SIG); -#endif -#ifdef PROV_DSS - PyModule_AddIntConstant(m, "PROV_DSS", PROV_DSS); -#endif -#ifdef PROV_FORTEZZA - PyModule_AddIntConstant(m, "PROV_FORTEZZA", PROV_FORTEZZA); -#endif -#ifdef PROV_MS_EXCHANGE - PyModule_AddIntConstant(m, "PROV_MS_EXCHANGE", PROV_MS_EXCHANGE); -#endif -#ifdef PROV_SSL - PyModule_AddIntConstant(m, "PROV_SSL", PROV_SSL); -#endif -#ifdef PROV_RSA_SCHANNEL - PyModule_AddIntConstant(m, "PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL); -#endif -#ifdef PROV_DSS_DH - PyModule_AddIntConstant(m, "PROV_DSS_DH", PROV_DSS_DH); -#endif -#ifdef PROV_EC_ECDSA_SIG - PyModule_AddIntConstant(m, "PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG); -#endif -#ifdef PROV_EC_ECNRA_SIG - PyModule_AddIntConstant(m, "PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG); -#endif -#ifdef PROV_EC_ECDSA_FULL - PyModule_AddIntConstant(m, "PROV_EC_ECDSA_FULL", PROV_EC_ECDSA_FULL); -#endif -#ifdef PROV_EC_ECNRA_FULL - PyModule_AddIntConstant(m, "PROV_EC_ECNRA_FULL", PROV_EC_ECNRA_FULL); -#endif -#ifdef PROV_SPYRUS_LYNKS - PyModule_AddIntConstant(m, "PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS); -#endif -#ifdef PROV_INTEL_SEC - PyModule_AddIntConstant(m, "PROV_INTEL_SEC", PROV_INTEL_SEC); -#endif - - /* Define Windows CSP Provider Names */ -#ifdef MS_DEF_PROV - PyModule_AddStringConstant(m, "MS_DEF_PROV", MS_DEF_PROV); -#endif -#ifdef MS_ENHANCED_PROV - PyModule_AddStringConstant(m, "MS_ENHANCED_PROV", MS_ENHANCED_PROV); -#endif -#ifdef MS_DEF_RSA_SIG_PROV - PyModule_AddStringConstant(m, "MS_DEF_RSA_SIG_PROV", - MS_DEF_RSA_SIG_PROV); -#endif -#ifdef MS_DEF_RSA_SCHANNEL_PROV - PyModule_AddStringConstant(m, "MS_DEF_RSA_SCHANNEL_PROV", - MS_DEF_RSA_SCHANNEL_PROV); -#endif -#ifdef MS_ENHANCED_RSA_SCHANNEL_PROV - PyModule_AddStringConstant(m, "MS_ENHANCED_RSA_SCHANNEL_PROV", - MS_ENHANCED_RSA_SCHANNEL_PROV); -#endif -#ifdef MS_DEF_DSS_PROV - PyModule_AddStringConstant(m, "MS_DEF_DSS_PROV", MS_DEF_DSS_PROV); -#endif -#ifdef MS_DEF_DSS_DH_PROV - PyModule_AddStringConstant(m, "MS_DEF_DSS_DH_PROV", - MS_DEF_DSS_DH_PROV); -#endif -#ifdef INTEL_DEF_PROV - PyModule_AddStringConstant(m, "INTEL_DEF_PROV", INTEL_DEF_PROV); -#endif - - if (PyErr_Occurred()) - Py_FatalError("can't initialize module winrandom"); -} - -/* - -CryptGenRandom usage is described in -http://msdn.microsoft.com/library/en-us/security/security/cryptgenrandom.asp -and many associated pages on Windows Cryptographic Service -Providers, which say: - - With Microsoft CSPs, CryptGenRandom uses the same - random number generator used by other security - components. This allows numerous processes to - contribute to a system-wide seed. CryptoAPI stores - an intermediate random seed with every user. To form - the seed for the random number generator, a calling - application supplies bits it might havefor instance, - mouse or keyboard timing inputthat are then added to - both the stored seed and various system data and - user data such as the process ID and thread ID, the - system clock, the system time, the system counter, - memory status, free disk clusters, the hashed user - environment block. This result is SHA-1 hashed, and - the output is used to seed an RC4 stream, which is - then used as the random stream and used to update - the stored seed. - -The only other detailed description I've found of the -sources of randomness for CryptGenRandom is this excerpt -from a posting -http://www.der-keiler.de/Newsgroups/comp.security.ssh/2002-06/0169.html - -From: Jon McClelland (dowot69@hotmail.com) -Date: 06/12/02 -... - -Windows, call a function such as CryptGenRandom, which has two of -the properties of a good random number generator, unpredictability and -even value distribution. This function, declared in Wincrypt.h, is -available on just about every Windows platform, including Windows 95 -with Internet Explorer 3.02 or later, Windows 98, Windows Me, Windows -CE v3, Windows NT 4, Windows 2000, and Windows XP. - -CryptGenRandom gets its randomness, also known as entropy, from many -sources in Windows 2000, including the following: -The current process ID (GetCurrentProcessID). -The current thread ID (GetCurrentThreadID). -The ticks since boot (GetTickCount). -The current time (GetLocalTime). -Various high-precision performance counters (QueryPerformanceCounter). -A Message Digest 4 (MD4) hash of the user's environment block, which -includes username, computer name, and search path. - -High-precision internal CPU counters, such as RDTSC, RDMSR, RDPMC (x86 -only-more information about these counters is at -developer.intel.com/software/idap/resources/technical_collateral/pentiumii/RDTSCPM1.HTM -). - -Low-level system information, such as idle time, kernel time, -interrupt times, commit limit, page read count, cache read count, -nonpaged pool allocations, alignment fixup count, operating system -lookaside information. - -Such information is added to a buffer, which is hashed using MD4 and -used as the key to modify a buffer, using RC4, provided by the user. -(Refer to the CryptGenRandom documentation in the Platform SDK for -more information about the user-provided buffer.) Hence, if the user -provides additional data in the buffer, this is used as an element in -the witches brew to generate the random data. The result is a -cryptographically random number generator. -Also, note that if you plan to sell your software to the United States -federal government, you'll need to use FIPS 140-1-approved algorithms. -The default versions of CryptGenRandom in Microsoft Windows CE v3, -Windows 95, Windows 98, Windows Me, Windows 2000, and Windows XP are -FIPS-approved. Obviously FIPS-140 compliance is necessary but not -sufficient to provide a properly secure source of random data. - -*/ - -#endif /* MS_WIN32 */ diff --git a/Crypto/test.py b/Crypto/test.py deleted file mode 100644 index ff59b067..00000000 --- a/Crypto/test.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python - -# -# Test script for the Python Cryptography Toolkit. -# - -__revision__ = "$Id: test.py,v 1.7 2002/07/11 14:31:19 akuchling Exp $" - -import os, sys - - -# Add the build directory to the front of sys.path -from distutils.util import get_platform -s = "build/lib.%s-%.3s" % (get_platform(), sys.version) -s = os.path.join(os.getcwd(), s) -sys.path.insert(0, s) -s = os.path.join(os.getcwd(), 'test') -sys.path.insert(0, s) - -from allmydata.Crypto.Util import test - -args = sys.argv[1:] -quiet = "--quiet" in args -if quiet: args.remove('--quiet') - -if not quiet: - print '\nStream Ciphers:' - print '===============' - -if args: test.TestStreamModules(args, verbose= not quiet) -else: test.TestStreamModules(verbose= not quiet) - -if not quiet: - print '\nBlock Ciphers:' - print '==============' - -if args: test.TestBlockModules(args, verbose= not quiet) -else: test.TestBlockModules(verbose= not quiet) - - diff --git a/Crypto/test/template b/Crypto/test/template deleted file mode 100644 index dce6c9b4..00000000 --- a/Crypto/test/template +++ /dev/null @@ -1,26 +0,0 @@ -# -# Test script for Crypto.XXX -# - -__revision__ = "$Id: template,v 1.1 2002/05/17 13:31:48 akuchling Exp $" - -from sancho.unittest import TestScenario, parse_args, run_scenarios - -tested_modules = [ "Crypto.XXX" ] - -class XXXTest (TestScenario): - - def setup (self): - pass - - def shutdown (self): - pass - - def check_ (self): - "" - pass - - -if __name__ == "__main__": - (scenarios, options) = parse_args() - run_scenarios(scenarios, options) diff --git a/Crypto/test/test_chaffing.py b/Crypto/test/test_chaffing.py deleted file mode 100644 index 512b53bc..00000000 --- a/Crypto/test/test_chaffing.py +++ /dev/null @@ -1,58 +0,0 @@ -# -# Test script for Crypto.XXX -# - -__revision__ = "$Id: test_chaffing.py,v 1.2 2003/02/28 15:23:59 akuchling Exp $" - -from sancho.unittest import TestScenario, parse_args, run_scenarios -from allmydata.Crypto.Protocol import Chaffing - -tested_modules = [ "Crypto.Protocol.Chaffing" ] - -text = """\ -When in the Course of human events, it becomes necessary for one people to -dissolve the political bands which have connected them with another, and to -assume among the powers of the earth, the separate and equal station to which -the Laws of Nature and of Nature's God entitle them, a decent respect to the -opinions of mankind requires that they should declare the causes which impel -them to the separation. - -We hold these truths to be self-evident, that all men are created equal, that -they are endowed by their Creator with certain unalienable Rights, that among -these are Life, Liberty, and the pursuit of Happiness. That to secure these -rights, Governments are instituted among Men, deriving their just powers from -the consent of the governed. That whenever any Form of Government becomes -destructive of these ends, it is the Right of the People to alter or to -abolish it, and to institute new Government, laying its foundation on such -principles and organizing its powers in such form, as to them shall seem most -likely to effect their Safety and Happiness. -""" - -class ChaffingTest (TestScenario): - - def setup (self): - pass - - def shutdown (self): - pass - - def check_chaffing (self): - "Simple tests of chaffing and winnowing" - self.test_stmt('Chaffing.Chaff()') - self.test_stmt('Chaffing.Chaff(0.5, 1)') - self.test_exc('Chaffing.Chaff(factor=-1)', ValueError) - self.test_exc('Chaffing.Chaff(blocksper=-1)', ValueError) - - data = [(1, 'data1', 'data1'), (2, 'data2', 'data2')] - c = Chaffing.Chaff(1.0, 1) - self.test_stmt('c.chaff(data)') - chaff = c.chaff(data) - self.test_val('len(chaff)', 4) - - c = Chaffing.Chaff(0.0, 1) - chaff = c.chaff(data) - self.test_val('len(chaff)', 2) - -if __name__ == "__main__": - (scenarios, options) = parse_args() - run_scenarios(scenarios, options) diff --git a/Crypto/test/test_hashes.py b/Crypto/test/test_hashes.py deleted file mode 100644 index 8e9e074e..00000000 --- a/Crypto/test/test_hashes.py +++ /dev/null @@ -1,94 +0,0 @@ -# -# Test script for Crypto.Util.randpool. -# - -__revision__ = "$Id: test_hashes.py,v 1.4 2004/08/13 22:23:12 akuchling Exp $" - -import time, string, binascii -from sancho.unittest import TestScenario, parse_args, run_scenarios - -from allmydata.Crypto.Hash import * -import testdata - -tested_modules = [ "Crypto.Hash.MD2", "Crypto.Hash.MD4", "Crypto.Hash.MD5", - "Crypto.Hash.RIPEMD", "Crypto.Hash.SHA", "Crypto.Hash.SHA256"] - -class HashTest (TestScenario): - - def setup (self): - teststr='1' # Build 128K of test data - for i in xrange(0, 17): - teststr=teststr+teststr - self.str_128k = teststr - - def shutdown (self): - del self.str_128k - - def compare(self, hash_mod, strg, hex_result): - result = binascii.a2b_hex(hex_result) - obj = hash_mod.new(strg) - s1 = obj.digest() - - # Check that the right hash result is produced - self.test_val('s1', result) - - # Check that .hexdigest() produces the same output - self.test_val('obj.hexdigest()', hex_result) - - # Test second hashing, and copying of a hashing object - self.test_val('obj.digest()', result) - self.test_val('obj.copy().digest()', result) - - - def run_test_suite (self, hash_mod, test_vectors): - for text, digest in test_vectors: - self.compare(hash_mod, text, digest) - - def benchmark (self, hash_mod): - obj = hash_mod.new() - start=time.time() - s=obj.update(self.str_128k) - end=time.time() - delta = end-start - print hash_mod.__name__, ':', - if delta == 0: - print 'Unable to measure time -- elapsed time too small' - else: - print '%.2f K/sec' % (128/(end-start)) - - def check_md2 (self): - "MD2 module" - self.run_test_suite(MD2, testdata.md2) - self.benchmark(MD2) - - def check_md4 (self): - "MD4 module" - self.run_test_suite(MD4, testdata.md4) - self.benchmark(MD4) - - def check_md5 (self): - "MD5 module" - self.run_test_suite(MD5, testdata.md5) - self.benchmark(MD5) - - def check_ripemd (self): - "RIPEMD module" - self.run_test_suite(RIPEMD, testdata.ripemd) - self.benchmark(RIPEMD) - - def check_sha (self): - "SHA module" - self.run_test_suite(SHA, testdata.sha) - self.benchmark(SHA) - - def check_sha256 (self): - "SHA256 module" - self.run_test_suite(SHA256,testdata.sha256) - self.benchmark(SHA256) - -# class HashTest - - -if __name__ == "__main__": - (scenarios, options) = parse_args() - run_scenarios(scenarios, options) diff --git a/Crypto/test/test_number.py b/Crypto/test/test_number.py deleted file mode 100644 index 39a87fce..00000000 --- a/Crypto/test/test_number.py +++ /dev/null @@ -1,85 +0,0 @@ -# -# Test script for Crypto.Util.number. -# - -__revision__ = "$Id: test_number.py,v 1.4 2003/04/04 18:21:35 akuchling Exp $" - -from sancho.unittest import TestScenario, parse_args, run_scenarios -from allmydata.Crypto.Util import number - -tested_modules = [ "Crypto.Util.number" ] - -class NumberTest (TestScenario): - - def setup (self): - pass - - def shutdown (self): - pass - - def check_getRandomNumber (self): - "Check generation of N-bit random numbers" - def f(N): - return '\xff' * N - - self.test_val('number.getRandomNumber(1, f)', 1) - self.test_val('number.getRandomNumber(4, f)', 15) - self.test_val('number.getRandomNumber(8, f)', 255) - self.test_val('number.getRandomNumber(12, f)', 4095) - self.test_val('number.getRandomNumber(16, f)', 65535) - - def check_GCD (self): - "Check GCD computation" - self.test_val('number.GCD(1, 5)', 1) - self.test_val('number.GCD(2, 6)', 2) - self.test_val('number.GCD(16, 12)', 4) - - def check_inverse (self): - "Check computation of inverses" - self.test_val('number.inverse(9, 10)', 9) - self.test_val('number.inverse(1, 2)', 1) - self.test_val('number.inverse(529, 10502)', 3097) - - def check_getPrime (self): - "Check generation of primes" - def f(n): - return '\xff' * n - self.test_val('number.getPrime(1, f)', 3) - self.test_val('number.getPrime(2, f)', 3) - self.test_val('number.getPrime(8, f)', 257) - self.test_val('number.getPrime(75, f)', 37778931862957161709601L) - - def check_isPrime (self): - "Check verification of primes" - self.test_bool('number.isPrime(1)', want_true=0) - self.test_bool('number.isPrime(2)') - self.test_bool('number.isPrime(3)') - self.test_bool('number.isPrime(4)', want_true=0) - self.test_bool('number.isPrime(37778931862957161709601L)') - self.test_bool('number.isPrime(37778931862957161709603L)', - want_true=0) - - def check_longbytes (self): - "Check conversion between bytes and integers" - self.test_val('number.long_to_bytes(1)', '\x01') - self.test_val('number.long_to_bytes(1, 2)', '\x00\x01') - self.test_val('number.long_to_bytes(511)', '\x01\xff') - - self.test_val('number.bytes_to_long("\x01")', 1) - self.test_val('number.bytes_to_long("\xff\x01")', 0xff01) - self.test_val('number.bytes_to_long("\x12\x34\x01")', 0x123401) - - def check_size (self): - "Check measurement of number sizes" - self.test_val('number.size(1)', 1) - self.test_val('number.size(15)', 4) - self.test_val('number.size(255)', 8) - self.test_val('number.size(256)', 9) - - -# class NumberTest - - -if __name__ == "__main__": - (scenarios, options) = parse_args() - run_scenarios(scenarios, options) diff --git a/Crypto/test/test_publickey.py b/Crypto/test/test_publickey.py deleted file mode 100644 index d03fa91f..00000000 --- a/Crypto/test/test_publickey.py +++ /dev/null @@ -1,122 +0,0 @@ -# -# Test script for Crypto.Util.PublicKey. -# - -__revision__ = "$Id: test_publickey.py,v 1.7 2003/04/04 19:38:28 akuchling Exp $" - -import sys, cPickle -from sancho.unittest import TestScenario, parse_args, run_scenarios -from allmydata.Crypto.PublicKey import * -from allmydata.Crypto.Util.randpool import RandomPool -from allmydata.Crypto.Util import number - -tested_modules = [ "Crypto.PublicKey.RSA", "Crypto.PublicKey.DSA", - "Crypto.PublicKey.ElGamal", "Crypto.PublicKey.qNEW"] - -class PublicKeyTest (TestScenario): - - def setup (self): - # Set up a random pool; we won't bother to actually fill it with - # entropy from the keyboard - self.pool = RandomPool(384) - self.pool.stir() - - def shutdown (self): - del self.pool - - def testkey (self, key, randfunc, verbose=0): - plaintext="Hello" - # Generate maximum-size plaintext - maxplain = (key.size() // 8) * '\377' - - if key.can_encrypt(): - if verbose: print ' Encryption/decryption test' - K=number.getPrime(10, randfunc) - ciphertext=key.encrypt(plaintext, K) - self.test_val('key.decrypt(ciphertext)', plaintext) - ciphertext=key.encrypt(maxplain, K) - self.test_val('key.decrypt(ciphertext)', maxplain) - - if key.can_sign(): - if verbose: print ' Signature test' - K=number.getPrime(30, randfunc) - signature=key.sign(plaintext, K) - self.test_bool('key.verify(plaintext, signature)') - self.test_bool('key.verify(plaintext[:-1], signature)', - want_true=0) - - # Change a single bit in the plaintext - badtext=plaintext[:-3]+chr( 1 ^ ord(plaintext[-3]) )+plaintext[-3:] - self.test_bool('key.verify(badtext, signature)', want_true=0) - - if verbose: print ' Removing private key data' - pubonly=key.publickey() - self.test_bool('pubonly.verify(plaintext, signature)') - - # Test blinding - if key.can_blind(): - if verbose: print ' Blinding test' - K=number.getPrime(30, randfunc) - B="garbage" - blindedtext=key.blind(plaintext, B) - signature=key.sign(blindedtext, K) - unblindedsignature=(key.unblind(signature[0], B),) - self.test_bool('key.verify(plaintext, unblindedsignature)') - self.test_val('key.sign(plaintext, K)', unblindedsignature) - - # Change a single bit in the blinding factor - badB=B[:-3]+chr( 1 ^ ord(B[-3]) )+B[-3:] - badunblindedsignature=(key.unblind(signature[0], badB),) - self.test_false('key.verify(badtext, badunblindedsignature)') - - badblindedtext=key.blind(plaintext, badB) - badsignature=key.sign(blindedtext, K) - badunblindedsignature2=(key.unblind(signature[0], B),) - self.test_false('key.verify(badtext, badunblindedsignature2)') - - - def exercise (self, randfunc, pk_mod, verbose=0): - N=256 # Key size, measured in bits - - key=pk_mod.generate(N, randfunc) - - if verbose: - print ' Key data:' - for field in key.keydata: - print " ", field, ':', hex(getattr(key,field)) - - if verbose: print " Testing newly generated key" - self.testkey(key, randfunc, verbose) - if verbose: print " Testing pickled/unpickled key" - import pickle - s = pickle.dumps(key) ; key2 = pickle.loads(s) - self.testkey(key2, randfunc, verbose) - - if verbose: print " Testing cPickled key" - s = cPickle.dumps(key) ; key2 = cPickle.loads(s) - self.testkey(key2, randfunc, verbose) - if verbose: print - - - def check_rsa(self): - "Check RSA algorithm" - self.exercise(self.pool.get_bytes, RSA) - - def check_dsa(self): - "Check DSA algorithm" - self.exercise(self.pool.get_bytes, DSA) - - def check_elgamal(self): - "Check ElGamal algorithm" - self.exercise(self.pool.get_bytes, ElGamal) - - def check_qnew(self): - "Check qNEW algorithm" - self.exercise(self.pool.get_bytes, qNEW) - -# class PublicKeyTest - - -if __name__ == "__main__": - (scenarios, options) = parse_args() - run_scenarios(scenarios, options) diff --git a/Crypto/test/test_randpool.py b/Crypto/test/test_randpool.py deleted file mode 100644 index 800af9ca..00000000 --- a/Crypto/test/test_randpool.py +++ /dev/null @@ -1,48 +0,0 @@ -# -# Test script for Crypto.Util.randpool. -# - -__revision__ = "$Id: test_randpool.py,v 1.3 2003/02/28 15:24:01 akuchling Exp $" - -from sancho.unittest import TestScenario, parse_args, run_scenarios -from allmydata.Crypto.Hash import SHA -from allmydata.Crypto.Util import randpool - -tested_modules = [ "Crypto.Util.randpool" ] - -class RandomPoolTest (TestScenario): - - def setup (self): - self.pool = randpool.RandomPool(160, hash=SHA) - - def shutdown (self): - del self.pool - - def check_init (self): - "Check initial state" - self.test_val('self.pool.entropy', self.pool.bits) - - def check_get_bytes (self): - "Check retrieving of bytes from the pool" - start_entropy = self.pool.entropy - self.test_bool('self.pool.entropy > 0') - - # Draw out half of the pool's entropy - size = self.pool.entropy / 8 / 2 - self.test_stmt('self.pool.get_bytes(size)') - self.test_val('self.pool.entropy', start_entropy - size*8) - - # Draw out the rest of the pool's entropy - self.test_stmt('self.pool.get_bytes(size)') - self.test_val('self.pool.entropy', 0) - - # Remove yet more data; entropy stays at zero - self.test_stmt('self.pool.get_bytes(size)') - self.test_val('self.pool.entropy', 0) - -# class RandomPoolTest - - -if __name__ == "__main__": - (scenarios, options) = parse_args() - run_scenarios(scenarios, options) diff --git a/Crypto/test/test_rfc1751.py b/Crypto/test/test_rfc1751.py deleted file mode 100644 index 60ec4427..00000000 --- a/Crypto/test/test_rfc1751.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Test script for Crypto.Util.randpool. -# - -__revision__ = "$Id: test_rfc1751.py,v 1.3 2003/02/28 15:24:01 akuchling Exp $" - -import binascii -from sancho.unittest import TestScenario, parse_args, run_scenarios -from allmydata.Crypto.Util import RFC1751 - -tested_modules = [ "Crypto.Util.RFC1751" ] - -test_data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', - 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', - 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] - -class RFC1751Test (TestScenario): - - def setup (self): - pass - - def shutdown (self): - pass - - def check_k2e (self): - "Check converting keys to English" - for key, words in test_data: - key=binascii.a2b_hex(key) - self.test_val('RFC1751.key_to_english(key)', words) - - def check_e2k (self): - "Check converting English strings to keys" - for key, words in test_data: - key=binascii.a2b_hex(key) - self.test_val('RFC1751.english_to_key(words)', key) - -# class RFC1751Test - - -if __name__ == "__main__": - (scenarios, options) = parse_args() - run_scenarios(scenarios, options) diff --git a/Crypto/test/testdata.py b/Crypto/test/testdata.py deleted file mode 100644 index d6efdf28..00000000 --- a/Crypto/test/testdata.py +++ /dev/null @@ -1,667 +0,0 @@ -# -# testdata.py : Test data for the various algorithms -# -# Part of the Python Cryptography Toolkit -# -# Distribute and use freely; there are no restrictions on further -# dissemination and usage except those imposed by the laws of your -# country of residence. This software is provided "as is" without -# warranty of fitness for use or suitability for any purpose, express -# or implied. Use at your own risk or not at all. -# - -# Data for encryption algorithms is saved as (key, plaintext, -# ciphertext) tuples. Hashing algorithm test data is simply -# (text, hashvalue) pairs. - -# MD2 validation data - -md2= [ - ("", "8350e5a3e24c153df2275c9f80692773"), - ("a", "32ec01ec4a6dac72c0ab96fb34c0b5d1"), - ("abc", "da853b0d3f88d99b30283a69e6ded6bb"), - ("message digest", "ab4f496bfb2a530b219ff33031fe06b0"), - ("abcdefghijklmnopqrstuvwxyz", "4e8ddff3650292ab5a4108c3aa47940b"), - ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "da33def2a42df13975352846c30338cd"), - ("12345678901234567890123456789012345678901234567890123456789012345678901234567890", - "d5976f79d83d3a0dc9806c3c66f3efd8") - ] - -# MD4 validation data - -md4= [ - ('', "31d6cfe0d16ae931b73c59d7e0c089c0"), - ("a", "bde52cb31de33e46245e05fbdbd6fb24"), - ("abc", "a448017aaf21d8525fc10ae87aa6729d"), - ("message digest", "d9130a8164549fe818874806e1c7014b"), - ("abcdefghijklmnopqrstuvwxyz", "d79e1c308aa5bbcdeea8ed63df412da9"), - ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "043f8582f241db351ce627e153e7f0e4"), - ("12345678901234567890123456789012345678901234567890123456789012345678901234567890", - "e33b4ddc9c38f2199c3e7b164fcc0536"), - ] - -# MD5 validation data - -md5= [ - ('', "d41d8cd98f00b204e9800998ecf8427e"), - ('a', "0cc175b9c0f1b6a831c399e269772661"), - ('abc', "900150983cd24fb0d6963f7d28e17f72"), - ('message digest', "f96b697d7cb7938d525a2f31aaf161d0"), - ('abcdefghijklmnopqrstuvwxyz', "c3fcd3d76192e4007dfb496cca67e13b"), - ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - "d174ab98d277d9f5a5611c2c9f419d9f"), - ('12345678901234567890123456789012345678901234567890123456789' - '012345678901234567890', "57edf4a22be3c955ac49da2e2107b67a") - ] - -# Test data for SHA, the Secure Hash Algorithm. - -sha = [ - ('abc', "a9993e364706816aba3e25717850c26c9cd0d89d"), - ('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', - "84983e441c3bd26ebaae4aa1f95129e5e54670f1"), - (1000000 * 'a', '34aa973cd4c4daa4f61eeb2bdbad27316534016f'), - ] - -sha256 = [ - ('abc', "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), - ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"), - ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"), - ("Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battlefield of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate--we can not consecrate--we can not hallow--this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us--that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion--that we here highly resolve that these dead shall not have died in vain--that this nation, under God, shall have a new birth of freedom--and that government of the people, by the people, for the people, shall not perish from the earth. -- President Abraham Lincoln, November 19, 1863", - "4d25fccf8752ce470a58cd21d90939b7eb25f3fa418dd2da4c38288ea561e600"), - ("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), - ("This is exactly 64 bytes long, not counting the terminating byte", "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"), - ("For this sample, this 63-byte string will be used as input data", "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"), - ("And this textual data, astonishing as it may appear, is exactly 128 bytes in length, as are both SHA-384 and SHA-512 block sizes", - "0ab803344830f92089494fb635ad00d76164ad6e57012b237722df0d7ad26896"), - ("By hashing data that is one byte less than a multiple of a hash block length (like this 127-byte string), bugs may be revealed.", - "e4326d0459653d7d3514674d713e74dc3df11ed4d30b4013fd327fdb9e394c26"), - ("qwerty" * 65536, - "5e3dfe0cc98fd1c2de2a9d2fd893446da43d290f2512200c515416313cdf3192"), - ("Rijndael is AES" * 1024, - "80fced5a97176a5009207cd119551b42c5b51ceb445230d02ecc2663bbfb483a"), - (1000000 * 'a', 'cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0'), - ] - -ripemd = [ ("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"), - ("a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"), - ("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"), - ("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"), - ("abcdefghijklmnopqrstuvwxyz", - "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"), - ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "12a053384a9c0c88e405a06c27dcf49ada62eb2b"), - ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "b0e20b6e3116640286ed3a87a5713079b21f5189"), - (8 *"1234567890", "9b752e45573d4b39f4dbd3323cab82bf63326bfb"), - (1000000 * 'a', "52783243c1697bdbe16d37f97f68f08325dc1528"), -] - -#Test data for SHA256 -sha256 = [("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), - ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"), - ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"), - ("Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battlefield of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate--we can not consecrate--we can not hallow--this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us--that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion--that we here highly resolve that these dead shall not have died in vain--that this nation, under God, shall have a new birth of freedom--and that government of the people, by the people, for the people, shall not perish from the earth. -- President Abraham Lincoln, November 19, 1863", - "4d25fccf8752ce470a58cd21d90939b7eb25f3fa418dd2da4c38288ea561e600"), - ("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), - ("This is exactly 64 bytes long, not counting the terminating byte", "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"), - ("For this sample, this 63-byte string will be used as input data", "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"), - ("And this textual data, astonishing as it may appear, is exactly 128 bytes in length, as are both SHA-384 and SHA-512 block sizes", - "0ab803344830f92089494fb635ad00d76164ad6e57012b237722df0d7ad26896"), - ("By hashing data that is one byte less than a multiple of a hash block length (like this 127-byte string), bugs may be revealed.", - "e4326d0459653d7d3514674d713e74dc3df11ed4d30b4013fd327fdb9e394c26"), - ("qwerty" * 65536, - "5e3dfe0cc98fd1c2de2a9d2fd893446da43d290f2512200c515416313cdf3192"), - ("Rijndael is AES" * 1024, - "80fced5a97176a5009207cd119551b42c5b51ceb445230d02ecc2663bbfb483a"), -] -sha256 = sha256[:1] - -# DES validation data - -# Key, IV, plaintext, ciphertext -des_cbc= [('0123456789abcdef', 'fedcba9876543210', - "7654321 Now is the time for \000\000\000\000", 'ccd173ffab2039f4acd8aefddfd8a1eb468e91157888ba681d269397f7fe62b4')] - -des = [ ('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'), - ('0101010101010101', '95F8A5E5DD31D900', '8000000000000000'), - ('0101010101010101', 'DD7F121CA5015619', '4000000000000000'), - ('0101010101010101', '2E8653104F3834EA', '2000000000000000'), - ('0101010101010101', '4BD388FF6CD81D4F', '1000000000000000'), - ('0101010101010101', '20B9E767B2FB1456', '0800000000000000'), - ('0101010101010101', '55579380D77138EF', '0400000000000000'), - ('0101010101010101', '6CC5DEFAAF04512F', '0200000000000000'), - ('0101010101010101', '0D9F279BA5D87260', '0100000000000000'), - ('0101010101010101', 'D9031B0271BD5A0A', '0080000000000000'), - ('0101010101010101', '424250B37C3DD951', '0040000000000000'), - ('0101010101010101', 'B8061B7ECD9A21E5', '0020000000000000'), - ('0101010101010101', 'F15D0F286B65BD28', '0010000000000000'), - ('0101010101010101', 'ADD0CC8D6E5DEBA1', '0008000000000000'), - ('0101010101010101', 'E6D5F82752AD63D1', '0004000000000000'), - ('0101010101010101', 'ECBFE3BD3F591A5E', '0002000000000000'), - ('0101010101010101', 'F356834379D165CD', '0001000000000000'), - ('0101010101010101', '2B9F982F20037FA9', '0000800000000000'), - ('0101010101010101', '889DE068A16F0BE6', '0000400000000000'), - ('0101010101010101', 'E19E275D846A1298', '0000200000000000'), - ('0101010101010101', '329A8ED523D71AEC', '0000100000000000'), - ('0101010101010101', 'E7FCE22557D23C97', '0000080000000000'), - ('0101010101010101', '12A9F5817FF2D65D', '0000040000000000'), - ('0101010101010101', 'A484C3AD38DC9C19', '0000020000000000'), - ('0101010101010101', 'FBE00A8A1EF8AD72', '0000010000000000'), - ('0101010101010101', '750D079407521363', '0000008000000000'), - ('0101010101010101', '64FEED9C724C2FAF', '0000004000000000'), - ('0101010101010101', 'F02B263B328E2B60', '0000002000000000'), - ('0101010101010101', '9D64555A9A10B852', '0000001000000000'), - ('0101010101010101', 'D106FF0BED5255D7', '0000000800000000'), - ('0101010101010101', 'E1652C6B138C64A5', '0000000400000000'), - ('0101010101010101', 'E428581186EC8F46', '0000000200000000'), - ('0101010101010101', 'AEB5F5EDE22D1A36', '0000000100000000'), - ('0101010101010101', 'E943D7568AEC0C5C', '0000000080000000'), - ('0101010101010101', 'DF98C8276F54B04B', '0000000040000000'), - ('0101010101010101', 'B160E4680F6C696F', '0000000020000000'), - ('0101010101010101', 'FA0752B07D9C4AB8', '0000000010000000'), - ('0101010101010101', 'CA3A2B036DBC8502', '0000000008000000'), - ('0101010101010101', '5E0905517BB59BCF', '0000000004000000'), - ('0101010101010101', '814EEB3B91D90726', '0000000002000000'), - ('0101010101010101', '4D49DB1532919C9F', '0000000001000000'), - ('0101010101010101', '25EB5FC3F8CF0621', '0000000000800000'), - ('0101010101010101', 'AB6A20C0620D1C6F', '0000000000400000'), - ('0101010101010101', '79E90DBC98F92CCA', '0000000000200000'), - ('0101010101010101', '866ECEDD8072BB0E', '0000000000100000'), - ('0101010101010101', '8B54536F2F3E64A8', '0000000000080000'), - ('0101010101010101', 'EA51D3975595B86B', '0000000000040000'), - ('0101010101010101', 'CAFFC6AC4542DE31', '0000000000020000'), - ('0101010101010101', '8DD45A2DDF90796C', '0000000000010000'), - ('0101010101010101', '1029D55E880EC2D0', '0000000000008000'), - ('0101010101010101', '5D86CB23639DBEA9', '0000000000004000'), - ('0101010101010101', '1D1CA853AE7C0C5F', '0000000000002000'), - ('0101010101010101', 'CE332329248F3228', '0000000000001000'), - ('0101010101010101', '8405D1ABE24FB942', '0000000000000800'), - ('0101010101010101', 'E643D78090CA4207', '0000000000000400'), - ('0101010101010101', '48221B9937748A23', '0000000000000200'), - ('0101010101010101', 'DD7C0BBD61FAFD54', '0000000000000100'), - ('0101010101010101', '2FBC291A570DB5C4', '0000000000000080'), - ('0101010101010101', 'E07C30D7E4E26E12', '0000000000000040'), - ('0101010101010101', '0953E2258E8E90A1', '0000000000000020'), - ('0101010101010101', '5B711BC4CEEBF2EE', '0000000000000010'), - ('0101010101010101', 'CC083F1E6D9E85F6', '0000000000000008'), - ('0101010101010101', 'D2FD8867D50D2DFE', '0000000000000004'), - ('0101010101010101', '06E7EA22CE92708F', '0000000000000002'), - ('0101010101010101', '166B40B44ABA4BD6', '0000000000000001'), - ('8001010101010101', '0000000000000000', '95A8D72813DAA94D'), - ('4001010101010101', '0000000000000000', '0EEC1487DD8C26D5'), - ('2001010101010101', '0000000000000000', '7AD16FFB79C45926'), - ('1001010101010101', '0000000000000000', 'D3746294CA6A6CF3'), - ('0801010101010101', '0000000000000000', '809F5F873C1FD761'), - ('0401010101010101', '0000000000000000', 'C02FAFFEC989D1FC'), - ('0201010101010101', '0000000000000000', '4615AA1D33E72F10'), - ('0180010101010101', '0000000000000000', '2055123350C00858'), - ('0140010101010101', '0000000000000000', 'DF3B99D6577397C8'), - ('0120010101010101', '0000000000000000', '31FE17369B5288C9'), - ('0110010101010101', '0000000000000000', 'DFDD3CC64DAE1642'), - ('0108010101010101', '0000000000000000', '178C83CE2B399D94'), - ('0104010101010101', '0000000000000000', '50F636324A9B7F80'), - ('0102010101010101', '0000000000000000', 'A8468EE3BC18F06D'), - ('0101800101010101', '0000000000000000', 'A2DC9E92FD3CDE92'), - ('0101400101010101', '0000000000000000', 'CAC09F797D031287'), - ('0101200101010101', '0000000000000000', '90BA680B22AEB525'), - ('0101100101010101', '0000000000000000', 'CE7A24F350E280B6'), - ('0101080101010101', '0000000000000000', '882BFF0AA01A0B87'), - ('0101040101010101', '0000000000000000', '25610288924511C2'), - ('0101020101010101', '0000000000000000', 'C71516C29C75D170'), - ('0101018001010101', '0000000000000000', '5199C29A52C9F059'), - ('0101014001010101', '0000000000000000', 'C22F0A294A71F29F'), - ('0101012001010101', '0000000000000000', 'EE371483714C02EA'), - ('0101011001010101', '0000000000000000', 'A81FBD448F9E522F'), - ('0101010801010101', '0000000000000000', '4F644C92E192DFED'), - ('0101010401010101', '0000000000000000', '1AFA9A66A6DF92AE'), - ('0101010201010101', '0000000000000000', 'B3C1CC715CB879D8'), - ('0101010180010101', '0000000000000000', '19D032E64AB0BD8B'), - ('0101010140010101', '0000000000000000', '3CFAA7A7DC8720DC'), - ('0101010120010101', '0000000000000000', 'B7265F7F447AC6F3'), - ('0101010110010101', '0000000000000000', '9DB73B3C0D163F54'), - ('0101010108010101', '0000000000000000', '8181B65BABF4A975'), - ('0101010104010101', '0000000000000000', '93C9B64042EAA240'), - ('0101010102010101', '0000000000000000', '5570530829705592'), - ('0101010101800101', '0000000000000000', '8638809E878787A0'), - ('0101010101400101', '0000000000000000', '41B9A79AF79AC208'), - ('0101010101200101', '0000000000000000', '7A9BE42F2009A892'), - ('0101010101100101', '0000000000000000', '29038D56BA6D2745'), - ('0101010101080101', '0000000000000000', '5495C6ABF1E5DF51'), - ('0101010101040101', '0000000000000000', 'AE13DBD561488933'), - ('0101010101020101', '0000000000000000', '024D1FFA8904E389'), - ('0101010101018001', '0000000000000000', 'D1399712F99BF02E'), - ('0101010101014001', '0000000000000000', '14C1D7C1CFFEC79E'), - ('0101010101012001', '0000000000000000', '1DE5279DAE3BED6F'), - ('0101010101011001', '0000000000000000', 'E941A33F85501303'), - ('0101010101010801', '0000000000000000', 'DA99DBBC9A03F379'), - ('0101010101010401', '0000000000000000', 'B7FC92F91D8E92E9'), - ('0101010101010201', '0000000000000000', 'AE8E5CAA3CA04E85'), - ('0101010101010180', '0000000000000000', '9CC62DF43B6EED74'), - ('0101010101010140', '0000000000000000', 'D863DBB5C59A91A0'), - ('0101010101010120', '0000000000000000', 'A1AB2190545B91D7'), - ('0101010101010110', '0000000000000000', '0875041E64C570F7'), - ('0101010101010108', '0000000000000000', '5A594528BEBEF1CC'), - ('0101010101010104', '0000000000000000', 'FCDB3291DE21F0C0'), - ('0101010101010102', '0000000000000000', '869EFD7F9F265A09'), - ('1046913489980131', '0000000000000000', '88D55E54F54C97B4'), - ('1007103489988020', '0000000000000000', '0C0CC00C83EA48FD'), - ('10071034C8980120', '0000000000000000', '83BC8EF3A6570183'), - ('1046103489988020', '0000000000000000', 'DF725DCAD94EA2E9'), - ('1086911519190101', '0000000000000000', 'E652B53B550BE8B0'), - ('1086911519580101', '0000000000000000', 'AF527120C485CBB0'), - ('5107B01519580101', '0000000000000000', '0F04CE393DB926D5'), - ('1007B01519190101', '0000000000000000', 'C9F00FFC74079067'), - ('3107915498080101', '0000000000000000', '7CFD82A593252B4E'), - ('3107919498080101', '0000000000000000', 'CB49A2F9E91363E3'), - ('10079115B9080140', '0000000000000000', '00B588BE70D23F56'), - ('3107911598080140', '0000000000000000', '406A9A6AB43399AE'), - ('1007D01589980101', '0000000000000000', '6CB773611DCA9ADA'), - ('9107911589980101', '0000000000000000', '67FD21C17DBB5D70'), - ('9107D01589190101', '0000000000000000', '9592CB4110430787'), - ('1007D01598980120', '0000000000000000', 'A6B7FF68A318DDD3'), - ('1007940498190101', '0000000000000000', '4D102196C914CA16'), - ('0107910491190401', '0000000000000000', '2DFA9F4573594965'), - ('0107910491190101', '0000000000000000', 'B46604816C0E0774'), - ('0107940491190401', '0000000000000000', '6E7E6221A4F34E87'), - ('19079210981A0101', '0000000000000000', 'AA85E74643233199'), - ('1007911998190801', '0000000000000000', '2E5A19DB4D1962D6'), - ('10079119981A0801', '0000000000000000', '23A866A809D30894'), - ('1007921098190101', '0000000000000000', 'D812D961F017D320'), - ('100791159819010B', '0000000000000000', '055605816E58608F'), - ('1004801598190101', '0000000000000000', 'ABD88E8B1B7716F1'), - ('1004801598190102', '0000000000000000', '537AC95BE69DA1E1'), - ('1004801598190108', '0000000000000000', 'AED0F6AE3C25CDD8'), - ('1002911598100104', '0000000000000000', 'B3E35A5EE53E7B8D'), - ('1002911598190104', '0000000000000000', '61C79C71921A2EF8'), - ('1002911598100201', '0000000000000000', 'E2F5728F0995013C'), - ('1002911698100101', '0000000000000000', '1AEAC39A61F0A464'), - ('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') ] - - -# Test data for Alleged RC4 - -arc4 = [ ('0000000000000000', '0000000000000000', 'de188941a3375d3a'), - ('0123456789abcdef', '0123456789abcdef', '75b7878099e0c596'), - ('0123456789abcdef', '0000000000000000', '7494c2e7104b0879'), - ('ef012345', '00000000000000000000', 'd6a141a7ec3c38dfbd61') ] - -# Test data for IDEA - -idea = [('00010002000300040005000600070008', '0000000100020003', '11fbed2b01986de5'), - ('00010002000300040005000600070008', '0102030405060708', '540E5FEA18C2F8B1'), - ('00010002000300040005000600070008', '0019324B647D96AF', '9F0A0AB6E10CED78'), - ('00010002000300040005000600070008', 'F5202D5B9C671B08', 'CF18FD7355E2C5C5'), - ('00010002000300040005000600070008', 'FAE6D2BEAA96826E', '85DF52005608193D'), - ('00010002000300040005000600070008', '0A141E28323C4650', '2F7DE750212FB734'), - ('00010002000300040005000600070008', '050A0F14191E2328', '7B7314925DE59C09'), - ('0005000A000F00140019001E00230028', '0102030405060708', '3EC04780BEFF6E20'), - ('3A984E2000195DB32EE501C8C47CEA60', '0102030405060708', '97BCD8200780DA86'), - ('006400C8012C019001F4025802BC0320', '05320A6414C819FA', '65BE87E7A2538AED'), - ('9D4075C103BC322AFB03E7BE6AB30006', '0808080808080808', 'F5DB1AC45E5EF9F9') - ]; - -# Test data for RC5 - -rc5 = [('10200c1000000000000000000000000000000000', '0000000000000000', - '21A5DBEE154B8F6D'), - ('10200c10915F4619BE41B2516355A50110A9CE91', '21A5DBEE154B8F6D', - 'F7C013AC5B2B8952'), - ('10200c10783348E75AEB0F2FD7B169BB8DC16787', 'F7C013AC5B2B8952', - '2F42B3B70369FC92'), - ('10200c10DC49DB1375A5584F6485B413B5F12BAF', '2F42B3B70369FC92', - '65C178B284D197CC'), - ('10200c105269F149D41BA0152497574D7F153125', '65C178B284D197CC', - 'EB44E415DA319824') - ] - -# Test data for ARC2 -arc2 = [ -('5068696c6970476c617373', '0000000000000000', '624fb3e887419e48'), -('5068696c6970476c617373', 'ffffffffffffffff', '79cadef44c4a5a85'), -('5068696c6970476c617373', '0001020304050607', '90411525b34e4c2c'), -('5068696c6970476c617373', '0011223344556677', '078656aaba61cbfb'), -('ffffffffffffffff', '0000000000000000', 'd7bcc5dbb4d6e56a'), -('ffffffffffffffff', 'ffffffffffffffff', '7259018ec557b357'), -('ffffffffffffffff', '0001020304050607', '93d20a497f2ccb62'), -('ffffffffffffffff', '0011223344556677', 'cb15a7f819c0014d'), -('ffffffffffffffff5065746572477265656e6177617953e5ffe553', '0000000000000000', '63ac98cdf3843a7a'), -('ffffffffffffffff5065746572477265656e6177617953e5ffe553', 'ffffffffffffffff', '3fb49e2fa12371dd'), -('ffffffffffffffff5065746572477265656e6177617953e5ffe553', '0001020304050607', '46414781ab387d5f'), -('ffffffffffffffff5065746572477265656e6177617953e5ffe553', '0011223344556677', 'be09dc81feaca271'), -('53e5ffe553', '0000000000000000', 'e64221e608be30ab'), -('53e5ffe553', 'ffffffffffffffff', '862bc60fdcd4d9a9'), -('53e5ffe553', '0001020304050607', '6a34da50fa5e47de'), -('53e5ffe553', '0011223344556677', '584644c34503122c'), -] - -# Test data for Blowfish - -blowfish = [('6162636465666768696a6b6c6d6e6f707172737475767778797a', - '424c4f5746495348', '324ed0fef413a203'), - ('57686f206973204a6f686e2047616c743f', 'fedcba9876543210', - 'cc91732b8022f684') - ] - -# Test data for DES3 - -des3_cbc=[] - -des3= [('0123456789abcdeffedcba9876543210', '0123456789abcde7', - '7f1d0a77826b8aff'), - ] - -# The DES test data can also be used to construct DES3 test data. -for key, iv, plain, cipher in des_cbc: - des3_cbc.append((key*3, iv, plain, cipher)) -for key, plain, cipher in des: - des3.append((key*3, plain, cipher)) - -# Test data for CAST - -_castkey = '0123456712345678234567893456789A' -_castdata = '0123456789ABCDEF' - -cast = [(_castkey, _castdata, '238B4FE5847E44B2'), - (_castkey[:10*2], _castdata, 'EB6A711A2C02271B'), - (_castkey[: 5*2], _castdata, '7AC816D16E9B302E'), - ] - -# Test data for XOR - -xor = [] - -# Test data for AES - -aes = [# 128-bit key - ('000102030405060708090A0B0C0D0E0F', - '00112233445566778899AABBCCDDEEFF', - '69C4E0D86A7B0430D8CDB78070B4C55A'), - - # 192-bit key - ('000102030405060708090A0B0C0D0E0F1011121314151617', - '00112233445566778899AABBCCDDEEFF', - 'DDA97CA4864CDFE06EAF70A0EC0D7191'), - - # 256-bit key - ('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F', - '00112233445566778899AABBCCDDEEFF', - '8EA2B7CA516745BFEAFC49904B496089'), - ] - -# Test data for AES modes, from NIST SP800-38A -from allmydata.Crypto.Cipher import AES - -counterstart='\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' - -aes_modes = [ - (AES.MODE_CBC, - '2b7e151628aed2a6abf7158809cf4f3c', - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('7649abac8119b246cee98e9b12e9197d' - '5086cb9b507219ee95db113a917678b2' - '73bed6b8e3c1743b7116e69e22229516' - '3ff1caa1681fac09120eca307586e1a7' - ), - {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), - (AES.MODE_CBC, - '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('4f021db243bc633d7178183a9fa071e8' - 'b4d9ada9ad7dedf4e5e738763f69145a' - '571b242012fb7ae07fa9baac3df102e0' - '08b0e27988598881d920a9e64f5615cd' - ), - {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), - (AES.MODE_CBC, - ('603deb1015ca71be2b73aef0857d7781' - '1f352c073b6108d72d9810a30914dff4' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('f58c4c04d6e5f1ba779eabfb5f7bfbd6' - '9cfc4e967edb808d679f777bc6702c7d' - '39f23369a9d9bacfa530e26304231461' - 'b2eb05e2c39be9fcda6c19078c6a9d1b' - ), - {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), - - (AES.MODE_OFB, - ('2b7e151628aed2a6abf7158809cf4f3c' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('3b3fd92eb72dad20333449f8e83cfb4a' - '7789508d16918f03f53c52dac54ed825' - '9740051e9c5fecf64344f7a82260edcc' - '304c6528f659c77866a510d9c1d6ae5e' - ), - {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), - (AES.MODE_OFB, - ('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('cdc80d6fddf18cab34c25909c99a4174' - 'fcc28b8d4c63837c09e81700c1100401' - '8d9a9aeac0f6596f559c6d4daf59a5f2' - '6d9f200857ca6c3e9cac524bd9acc92a' - ), - {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), - (AES.MODE_OFB, - ('603deb1015ca71be2b73aef0857d7781' - '1f352c073b6108d72d9810a30914dff4' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('dc7e84bfda79164b7ecd8486985d3860' - '4febdc6740d20b3ac88f6ad82a4fb08d' - '71ab47a086e86eedf39d1c5bba97c408' - '0126141d67f37be8538f5a8be740e484' - ), - {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), - - (AES.MODE_CTR, - ('2b7e151628aed2a6abf7158809cf4f3c' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('874d6191b620e3261bef6864990db6ce' - '9806f66b7970fdff8617187bb9fffdff' - '5ae4df3edbd5d35e5b4f09020db03eab' - '1e031dda2fbe03d1792170a0f3009cee' - ), - {'counterstart': counterstart}, ), - (AES.MODE_CTR, - ('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('1abc932417521ca24f2b0459fe7e6e0b' - '090339ec0aa6faefd5ccc2c6f4ce8e94' - '1e36b26bd1ebc670d1bd1d665620abf7' - '4f78a7f6d29809585a97daec58c6b050' - ), - {'counterstart': counterstart}, ), - (AES.MODE_CTR, - ('603deb1015ca71be2b73aef0857d7781' - '1f352c073b6108d72d9810a30914dff4' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ('601ec313775789a5b7a7f504bbf3d228' - 'f443e3ca4d62b59aca84e990cacaf5c5' - '2b0930daa23de94ce87017ba2d84988d' - 'dfc9c58db67aada613c2dd08457941a6' - ), - {'counterstart': counterstart}, ), - - (AES.MODE_CFB, - '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172aae2d', - '3b79424c9c0dd436bace9e0ed4586a4f32b9', - {'segment_size':8, - 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', - } - ), - (AES.MODE_CFB, - '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172aae2d', - 'cda2521ef0a905ca44cd057cbf0d47a0678a', - {'segment_size':8, - 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', - } - ), - (AES.MODE_CFB, - ('603deb1015ca71be2b73aef0857d7781' - '1f352c073b6108d72d9810a30914dff4' - ), - '6bc1bee22e409f96e93d7e117393172aae2d', - 'dc1f1a8520a64db55fcc8ac554844e889700', - {'segment_size':8, - 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', - } - ), - - (AES.MODE_CFB, - ('2b7e151628aed2a6abf7158809cf4f3c' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ( - '3b3fd92eb72dad20333449f8e83cfb4a' - 'c8a64537a0b3a93fcde3cdad9f1ce58b' - '26751f67a3cbb140b1808cf187a4f4df' - 'c04b05357c5d1c0eeac4c66f9ff7f2e6' - ), - {'segment_size':128, - 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', - } - ), - (AES.MODE_CFB, - ('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ( - 'cdc80d6fddf18cab34c25909c99a4174' - '67ce7f7f81173621961a2b70171d3d7a' - '2e1e8a1dd59b88b1c8e60fed1efac4c9' - 'c05f9f9ca9834fa042ae8fba584b09ff' - ), - {'segment_size':128, - 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', - } - ), - (AES.MODE_CFB, - ('603deb1015ca71be2b73aef0857d7781' - '1f352c073b6108d72d9810a30914dff4' - ), - ('6bc1bee22e409f96e93d7e117393172a' - 'ae2d8a571e03ac9c9eb76fac45af8e51' - '30c81c46a35ce411e5fbc1191a0a52ef' - 'f69f2445df4f9b17ad2b417be66c3710' - ), - ( - 'dc7e84bfda79164b7ecd8486985d3860' - '39ffed143b28b1c832113c6331e5407b' - 'df10132415e54b92a13ed0a8267ae2f9' - '75a385741ab9cef82031623d55b1e471' - ), - {'segment_size':128, - 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', - } - ), - ] diff --git a/allmydata/__init__.py b/allmydata/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/allmydata/bucketstore.py b/allmydata/bucketstore.py deleted file mode 100644 index e3e1b675..00000000 --- a/allmydata/bucketstore.py +++ /dev/null @@ -1,134 +0,0 @@ -import os - -from foolscap import Referenceable -from twisted.application import service -from twisted.python.failure import Failure -from allmydata.util import idlib -from zope.interface import implements -from allmydata.interfaces import RIBucketWriter, RIBucketReader - -from allmydata.util.assertutil import precondition, _assert - -class NoSuchBucketError(Failure): - pass - -class BucketStore(service.MultiService, Referenceable): - def __init__(self, store_dir): - precondition(os.path.isdir(store_dir)) - service.MultiService.__init__(self) - self._store_dir = store_dir - - self._leases = set() # should do weakref dances. - - def _get_bucket_dir(self, verifierid): - avid = idlib.b2a(verifierid) - return os.path.join(self._store_dir, avid) - - def has_bucket(self, verifierid): - return os.path.exists(self._get_bucket_dir(verifierid)) - - def allocate_bucket(self, verifierid, bucket_num, size, - leaser_credentials, canary): - bucket_dir = self._get_bucket_dir(verifierid) - precondition(not os.path.exists(bucket_dir)) - precondition(isinstance(bucket_num, int)) - bucket = WriteBucket(bucket_dir, verifierid, bucket_num, size) - bucket.set_leaser(leaser_credentials) - lease = Lease(verifierid, leaser_credentials, bucket, canary) - self._leases.add(lease) - return lease - - def get_buckets(self, verifierid): - # for now, only returns those created by this process, in this run - bucket_dir = self._get_bucket_dir(verifierid) - if os.path.exists(bucket_dir): - b = ReadBucket(bucket_dir, verifierid) - return [(b.get_bucket_num(), b)] - else: - return [] - -class Lease(Referenceable): - implements(RIBucketWriter) - - def __init__(self, verifierid, leaser, bucket, canary): - self._leaser = leaser - self._verifierid = verifierid - self._bucket = bucket - canary.notifyOnDisconnect(self._lost_canary) - - def get_bucket(self): - return self._bucket - - def remote_write(self, data): - self._bucket.write(data) - - def remote_close(self): - self._bucket.close() - - def _lost_canary(self): - pass - -class Bucket: - def __init__(self, bucket_dir, verifierid): - self._bucket_dir = bucket_dir - self._verifierid = verifierid - - def _write_attr(self, name, val): - f = file(os.path.join(self._bucket_dir, name), 'wb') - f.write(val) - f.close() - - def _read_attr(self, name): - f = file(os.path.join(self._bucket_dir, name), 'rb') - data = f.read() - f.close() - return data - - def is_complete(self): - return os.path.exists(os.path.join(self._bucket_dir, 'closed')) - -class WriteBucket(Bucket): - def __init__(self, bucket_dir, verifierid, bucket_num, size): - Bucket.__init__(self, bucket_dir, verifierid) - precondition(not os.path.exists(bucket_dir)) - os.mkdir(bucket_dir) - - self._size = size - self._data = file(os.path.join(self._bucket_dir, 'data'), 'wb') - self._bytes_written = 0 - - self._write_attr('bucket_num', str(bucket_num)) - - def set_leaser(self, leaser): - self._write_attr('leases', leaser) - - def write(self, data): - precondition(len(data) + self._bytes_written <= self._size) - self._data.write(data) - self._data.flush() - self._bytes_written += len(data) - - def close(self): - precondition(self._bytes_written == self._size) - self._data.close() - self._write_attr('closed', '') - - def is_complete(self): - complete = Bucket.is_complete(self) - if complete: - _assert(os.path.getsize(os.path.join(self._bucket_dir, 'data')) == self._size) - return complete - -class ReadBucket(Bucket, Referenceable): - implements(RIBucketReader) - - def __init__(self, bucket_dir, verifierid): - Bucket.__init__(self, bucket_dir, verifierid) - precondition(self.is_complete()) # implicitly asserts bucket_dir exists - - def get_bucket_num(self): - return int(self._read_attr('bucket_num')) - - def read(self): - return self._read_attr('data') - remote_read = read diff --git a/allmydata/chunk.py b/allmydata/chunk.py deleted file mode 100644 index ec904191..00000000 --- a/allmydata/chunk.py +++ /dev/null @@ -1,727 +0,0 @@ - -""" -Read and write chunks from files. - -Version 1.0.0. - -A file is divided into blocks, each of which has size L{BLOCK_SIZE} -(except for the last block, which may be smaller). Blocks are encoded -into chunks. One publishes the hash of the entire file. Clients -who want to download the file first obtain the hash, then the clients -can receive chunks in any order. Cryptographic hashing is used to -verify each received chunk before writing to disk. Thus it is -impossible to download corrupt data if one has the correct file hash. - -One obtains the hash of a complete file via -L{CompleteChunkFile.file_hash}. One can read chunks from a complete -file by the sequence operations of C{len()} and subscripting on a -L{CompleteChunkFile} object. One can open an empty or partially -downloaded file with L{PartialChunkFile}, and read and write chunks -to this file. A chunk will fail to write if its contents and index -are not consistent with the overall file hash passed to -L{PartialChunkFile} when the partial chunk file was first created. - -The chunks have an overhead of less than 4% for files of size -less than C{10**20} bytes. - -Benchmarks: - - - On a 3 GHz Pentium 3, it took 3.4 minutes to first make a - L{CompleteChunkFile} object for a 4 GB file. Up to 10 MB of - memory was used as the constructor ran. A metafile filename - was passed to the constructor, and so the hash information was - written to the metafile. The object used a negligible amount - of memory after the constructor was finished. - - Creation of L{CompleteChunkFile} objects in future runs of the - program took negligible time, since the hash information was - already stored in the metafile. - -@var BLOCK_SIZE: Size of a block. See L{BlockFile}. -@var MAX_CHUNK_SIZE: Upper bound on the size of a chunk. - See L{CompleteChunkFile}. - -free (adj.): unencumbered; not under the control of others -Written by Connelly Barnes in 2005 and released into the -public domain with no warranty of any kind, either expressed -or implied. It probably won't make your computer catch on fire, -or eat your children, but it might. Use at your own risk. -""" - -import sha -import os -#import os.path - -from allmydata.util import bencode - -__all__ = ['CompleteChunkFile', 'PartialChunkFile'] - -__version__ = '1.0.0' - -BLOCK_SIZE = 65536 -MAX_CHUNK_SIZE = BLOCK_SIZE + 4096 - -def hash(s): - """ - Cryptographic hash function used by this module. - """ - return sha.new(s).digest() - - -def roundup_pow2(x): - """ - Round integer C{x} up to the nearest power of 2. - """ - ans = 1 - while ans < x: - ans *= 2 - return ans - - -class CompleteBinaryTreeMixin: - """ - Adds convenience methods to a complete binary tree. - - Assumes the total number of elements in the binary tree may be - accessed via C{__len__}, and that each element can be retrieved - using list subscripting. - - Tree is indexed like so:: - - - 0 - / \ - 1 2 - / \ / \ - 3 4 5 6 - / \ / \ / \ / \ - 7 8 9 10 11 12 13 14 - - """ - def parent(self, i): - """ - Index of the parent of C{i}. - """ - if i < 1 or (hasattr(self, '__len__') and i >= len(self)): - raise IndexError('index out of range: ' + repr(i)) - return (i - 1) // 2 - - def lchild(self, i): - """ - Index of the left child of C{i}. - """ - ans = 2 * i + 1 - if i < 0 or (hasattr(self, '__len__') and ans >= len(self)): - raise IndexError('index out of range: ' + repr(i)) - return ans - - def rchild(self, i): - """ - Index of right child of C{i}. - """ - ans = 2 * i + 2 - if i < 0 or (hasattr(self, '__len__') and ans >= len(self)): - raise IndexError('index out of range: ' + repr(i)) - return ans - - def sibling(self, i): - """ - Index of sibling of C{i}. - """ - parent = self.parent(i) - if self.lchild(parent) == i: - return self.rchild(parent) - else: - return self.lchild(parent) - - def needed(self, i): - """ - Return a list of nodes that are necessary for the hash chain. - """ - if i < 0 or i >= len(self): - raise IndexError('index out of range: ' + repr(i)) - needed = [] - here = i - while here != 0: - needed.append(self.sibling(here)) - here = self.parent(here) - return needed - - -class HashTree(CompleteBinaryTreeMixin, list): - """ - Compute Merkle hashes at any node in a complete binary tree. - - Tree is indexed like so:: - - - 0 - / \ - 1 2 - / \ / \ - 3 4 5 6 - / \ / \ / \ / \ - 7 8 9 10 11 12 13 14 <- List passed to constructor. - - """ - def __init__(self, L): - """ - Create complete binary tree from list of hash strings. - - The list is augmented by hashes so its length is a power of 2, and - then this is used as the bottom row of the hash tree. - - The augmenting is done so that if the augmented element is at - index C{i}, then its value is C{hash(bencode.bencode((i, '')))}. - """ - # Augment the list. - start = len(L) - end = roundup_pow2(len(L)) - L = L + [None] * (end - start) - for i in range(start, end): - L[i] = hash(bencode.bencode((i, ''))) - # Form each row of the tree. - rows = [L] - while len(rows[-1]) != 1: - last = rows[-1] - rows += [[hash(last[2*i] + last[2*i+1]) for i in xrange(len(last)//2)]] - # Flatten the list of rows into a single list. - rows.reverse() - self[:] = sum(rows, []) - - -class BlockFile: - """ - Reads and writes blocks of data to a binary file. - - It is assumed that the binary file does not change in size. - - @ivar file_name: Full path to file. - @ivar file_size: Size of file in bytes. - @ivar block_size: Size of each block. - """ - def __init__(self, file_name, mode, block_size, file_size=None): - """ - Initialize block reader or writer on given file name. - - If mode is 'r', the file must already exist and it is opened for - reading only. If mode is 'w', the file will be created with size - C{file_size} if it does not exist, and it is opened for reading - and writing. - - Note that C{file_size} is ignored if the file already exists. - """ - self.mode = mode - self.file_name = os.path.abspath(file_name) - assert self.mode in ['r', 'w'] - - if mode == 'r': - f = open(self.file_name, 'rb') - f.close() - - # Create file if it doesn't exist. - created = False - if mode == 'w' and not os.path.exists(self.file_name): - created = True - buf = ' ' * 1024 - f = open(self.file_name, 'wb') - for i in xrange(file_size // len(buf)): - f.write(buf) - f.write(' ' * (file_size % len(buf))) - f.close() - - self.file_size = os.stat(self.file_name).st_size - if created: - assert self.file_size == file_size - self.block_size = block_size - self.__block_count = self.file_size // self.block_size - if self.file_size % self.block_size == 0: - self.last_block_size = self.block_size - else: - self.last_block_size = self.file_size % self.block_size - self.__block_count += 1 - - def __getitem__(self, i): - """ - Get block i. - """ - if i < 0 or i >= len(self): - raise IndexError('block index out of range: ' + repr(i)) - f = open(self.file_name, 'rb') - try: - f.seek(i * self.block_size) - ans = f.read(self.block_size) - finally: - f.close() - return ans - - def __setitem__(self, i, s): - """ - Set block i. - """ - if self.mode != 'w': - raise ValueError('file opened for reading only') - if i < 0 or i >= len(self): - raise IndexError('block index out of range: ' + repr(i)) - if i < len(self) - 1: - if len(s) != self.block_size: - raise ValueError('length of value must equal block_size') - else: - if len(s) != self.last_block_size: - raise ValueError('length of value must equal last_block_size') - f = open(self.file_name, 'rb+') - try: - f.seek(i * self.block_size) - f.write(s) - finally: - f.close() - - def __len__(self): - """ - Get number of blocks. - """ - return int(self.__block_count) - - -class MetaFile(CompleteBinaryTreeMixin): - """ - A L{HashTree} stored on disk, with a timestamp. - - The list of hashes can be accessed using subscripting and - C{__len__}, in the same manner as for L{HashTree}. - - Note that the constructor takes the entire list associated with - the L{HashTree}, not just the bottom row of the tree. - - @ivar meta_name: Full path to metafile. - """ - def __init__(self, meta_name, mode, L=None): - """ - Open an existing meta-file for reading or writing. - - If C{mode} is 'r', the meta-file must already exist and it is - opened for reading only, and the list C{L} is ignored. If C{mode} - is 'w', the file will be created if it does not exist (from the - list of hashes given in C{L}), and it is opened for reading and - writing. - """ - self.meta_name = os.path.abspath(meta_name) - self.mode = mode - assert self.mode in ['r', 'w'] - - # A timestamp is stored at index 0. The MetaFile instance - # offsets all indices passed to __getitem__, __setitem__ by - # this offset, and pretends it has length equal to - # self.sublength. - self.offset = 1 - - if self.mode == 'w': - suggested_length = len(hash('')) * (len(L)+self.offset) - else: - suggested_length = None - - created = False - if self.mode == 'w' and not os.path.exists(self.meta_name): - created = True - - self.block_file = BlockFile(self.meta_name, self.mode, - len(hash('')), - suggested_length) - self.sublength = len(self.block_file) - self.offset - - if created: - for i in xrange(len(L)): - self.block_file[i + self.offset] = L[i] - - def __getitem__(self, i): - if i < 0 or i >= self.sublength: - raise IndexError('bad meta-file block index') - return self.block_file[i + self.offset] - - def __setitem__(self, i, value): - if i < 0 or i >= self.sublength: - raise IndexError('bad meta-file block index') - self.block_file[i + self.offset] = value - - def __len__(self): - return self.sublength - - def set_timestamp(self, file_name): - """ - Set meta file's timestamp equal to the timestamp for C{file_name}. - """ - st = os.stat(file_name) - timestamp = bencode.bencode((st.st_size, st.st_mtime)) - self.block_file[0] = sha.new(timestamp).digest() - - def check_timestamp(self, file_name): - """ - True if meta file's timestamp equals timestamp for C{file_name}. - """ - st = os.stat(file_name) - timestamp = bencode.bencode((st.st_size, st.st_mtime)) - return self.block_file[0] == sha.new(timestamp).digest() - - -class CompleteChunkFile(BlockFile): - """ - Reads chunks from a fully-downloaded file. - - A chunk C{i} is created from block C{i}. Block C{i} is unencoded - data read from the file by the L{BlockFile}. Chunk C{i} is - an encoded string created from block C{i}. - - Chunks can be read using list subscripting. The total number of - chunks (equals the total number of blocks) is given by L{__len__}. - - @ivar file_name: Full path to file. - @ivar file_size: Size of file in bytes. - @ivar file_hash: Hash of file. - @ivar meta_name: Full path to metafile, or C{None}. - @ivar tree: L{HashTree} or L{MetaFile} instance for the file. - One can extract a hash from any node in the hash - tree. - """ - - def __init__(self, file_name, meta_name=None, callback=None): - """ - Initialize reader on the given file name. - - The entire file will be read and the hash will be computed from - the file. This may take a long time, so C{callback()} is called - frequently during this process. This allows you to reduce CPU - usage if you wish. - - The C{meta_name} argument is optional. If it is specified, then the - hashes for C{file_name} will be stored under the file - C{meta_name}. If a C{CompleteChunkFile} is created on the same - file and metafile in the future, then the hashes will not need to - be recomputed and the constructor will return instantly. The - metafile contains a file and date stamp, so that if the file stored - in C{file_name} is modified, then the hashes will be recomputed. - """ - BlockFile.__init__(self, file_name, 'r', block_size=65536) - - # Whether we need to compute the hash tree - compute_tree = False - - self.meta_name = meta_name - if self.meta_name != None: - self.meta_name = os.path.abspath(self.meta_name) - self.meta = None - if self.meta_name == None: - compute_tree = True - else: - try: - meta = MetaFile(self.meta_name, 'r') - assert meta.check_timestamp(self.file_name) - except (IOError, AssertionError): - compute_tree = True - - # Compute the hash tree if needed. - if compute_tree: - chunk_hashes = [None] * len(self) - for i in xrange(len(self)): - triple = (self.file_size, i, BlockFile.__getitem__(self, i)) - chunk_hashes[i] = hash(bencode.bencode(triple)) - if callback: - callback() - self.tree = HashTree(chunk_hashes) - del chunk_hashes - - # If a meta-file was given, make self.tree be a MetaFile instance. - if self.meta_name != None: - if compute_tree: - # Did we compute the hash tree? Then store it to disk. - self.tree = MetaFile(self.meta_name, 'w', self.tree) - # Update its timestamp to be consistent with the file we - # just hashed. - self.tree.set_timestamp(self.file_name) - else: - # Read existing file from disk. - self.tree = MetaFile(self.meta_name, 'r') - - self.file_hash = self.tree[0] - - def __getitem__(self, i): - """ - Get chunk C{i}. - - Raises C{ValueError} if the file's contents changed since the - CompleteFileChunkReader was instantiated. - """ - return encode_chunk(BlockFile.__getitem__(self, i), i, - self.file_size, self.tree) - - -def encode_chunk(block, index, file_size, tree): - """ - Encode a chunk. - - Given a block at index C{index} in a file with size C{file_size}, - and a L{HashTree} or L{MetaFile} instance C{tree}, computes and - returns a chunk string for the given block. - - The C{tree} argument needs to have correct hashes only at certain - indices. Check out the code for details. In any case, if a hash - is wrong an exception will be raised. - """ - block_count = (len(tree) + 1) // 2 - if index < 0 or index >= block_count: - raise IndexError('block index out of range: ' + repr(index)) - - suffix = bencode.bencode((file_size, index, block)) - current = len(tree) - block_count + index - prefix = [] - while current > 0: - sibling = tree.sibling(current) - prefix += [tree[current], tree[sibling]] - current = tree.parent(current) - prefix = ''.join(prefix) - - # Encode the chunk - chunk = bencode.bencode((prefix, suffix)) - - # Check to make sure it decodes properly. - decode_chunk(chunk, file_size, tree) - return chunk - - -def decode_chunk(chunk, file_size, tree): - """ - Decode a chunk. - - Given file with size C{file_size} and a L{HashTree} or L{MetaFile} - instance C{tree}, return C{(index, block, tree_items)}. Here - C{index} is the block index where string C{block} should be placed - in the file. Also C{tree_items} is a dict mapping indices within - the L{HashTree} or L{MetaFile} tree object associated with the - given file to the corresponding hashes at those indices. These - have been verified against the file's hash, so it is known that - they are correct. - - Raises C{ValueError} if chunk verification fails. - """ - file_hash = tree[0] - block_count = (len(tree) + 1) // 2 - try: - # Decode the chunk - try: - (prefix, suffix) = bencode.bdecode(chunk) - except: - raise AssertionError() - - assert isinstance(prefix, str) - assert isinstance(suffix, str) - - # Verify the suffix against the hashes in the prefix. - hash_len = len(hash('')) - L = [prefix[hash_len*i:hash_len*(i+1)] for i in range(len(prefix)//hash_len)] - L += [file_hash] - assert L[0] == hash(suffix) - branches = [] - for i in range(0, len(L)-1, 2): - if hash(L[i] + L[i+1]) == L[i+2]: - branches += [0] - elif hash(L[i+1] + L[i]) == L[i+2]: - branches += [1] - else: - raise AssertionError() - - # Decode the suffix - try: - (claim_file_size, claim_index, block) = bencode.bdecode(suffix) - except: - raise AssertionError() - - assert isinstance(claim_file_size, int) or isinstance(claim_file_size, long) - assert isinstance(claim_index, int) or isinstance(claim_index, long) - assert isinstance(block, str) - - assert file_size == claim_file_size - - # Compute the index of the block, and check it. - found_index = sum([branches[i]*2**i for i in range(len(branches))]) - assert found_index == claim_index - - # Now fill in the tree_items dict. - tree_items = {} - current = (len(tree) - block_count) + found_index - i = 0 - while current > 0 and i + 1 < len(L): - tree_items[current] = L[i] - # Next item is our sibling. - tree_items[tree.sibling(current)] = L[i+1] - i += 2 - current = tree.parent(current) - - return (found_index, block, tree_items) - except AssertionError: - raise ValueError('corrupt chunk') - - -class PartialChunkFile(BlockFile): - """ - Reads and writes chunks to a partially downloaded file. - - @ivar file_name: Full path to file. - @ivar file_size: Size of file in bytes. - @ivar file_hash: Hash of file. - @ivar meta_name: Full path to metafile. - @ivar tree: L{MetaFile} instance for the file. - The hashes in this hash tree are valid only for - nodes that we have been sent hashes for. - """ - def __init__(self, file_name, meta_name, file_hash=None, file_size=None): - """ - Initialize reader/writer for the given file name and metafile name. - - If neither C{file_name} nor C{meta_file} exist, then both are - created. The C{file_hash} and C{file_size} arguments are used to - initialize the two files. - - If both C{file_name} and C{meta_file} exist, then the hash and - file size arguments are ignored, and those values are instead read - from the files. - - If one file exists and the other does not, an C{IOError} is raised. - """ - self.meta_name = os.path.abspath(meta_name) - meta_exists = os.path.exists(self.meta_name) - file_exists = os.path.exists(os.path.abspath(file_name)) - - BlockFile.__init__(self, os.path.abspath(file_name), 'w', - BLOCK_SIZE, file_size) - - if file_exists and not meta_exists: - raise IOError('metafile ' + repr(self.meta_name) + - ' missing for file ' + repr(self.file_name)) - if meta_exists and not file_exists: - raise IOError('file ' + repr(self.file_name) + - ' missing for metafile ' + repr(self.meta_name)) - tree_count = 2 * roundup_pow2(len(self)) - 1 - self.tree = MetaFile(self.meta_name, 'w', [hash('')] * tree_count) - - if not meta_exists and not file_exists: - self.tree[0] = file_hash - - self.file_hash = self.tree[0] - - def __getitem__(self, i): - """ - Get chunk C{i}. - - Raises C{ValueError} if chunk has not yet been downloaded or is - corrupted. - """ - return encode_chunk(BlockFile.__getitem__(self, i), i, - self.file_size, self.tree) - - def __setitem__(self, i, chunk): - """ - Set chunk C{i}. - - Raises C{ValueError} if the chunk is invalid. - """ - (index, block, tree_items) = decode_chunk(chunk, - self.file_size, self.tree) - if index != i: - raise ValueError('incorrect index for chunk') - BlockFile.__setitem__(self, index, block) - for (tree_index, tree_value) in tree_items.items(): - self.tree[tree_index] = tree_value - - -def test(filename1='temp-out', metaname1='temp-out.meta', - filename2='temp-out2', metaname2='temp-out2.meta'): - """ - Unit tests. - """ - print 'Testing:' - - import random - ntests = 100 - max_file_size = 200000 - - # Test CompleteChunkFile. - - if os.path.exists(metaname1): - os.remove(metaname1) - - for i in range(ntests): - fsize = random.randrange(max_file_size) - # Make some random string of size 'fsize' to go in the file. - s = ''.join([sha.new(str(j)).digest() for j in range(fsize//20+1)]) - assert len(s) >= fsize - s = s[:fsize] - f = open(filename1, 'wb') - f.write(s) - f.close() - C = CompleteChunkFile(filename1) - for j in range(len(C)): - C[j] - C = CompleteChunkFile(filename1, metaname1) - for j in range(len(C)): - C[j] - C = CompleteChunkFile(filename1, metaname1) - for j in range(len(C)): - C[j] - os.remove(metaname1) - - os.remove(filename1) - - print ' CompleteChunkFile: OK' - - # Test PartialChunkFile - - for i in range(ntests): - fsize = random.randrange(max_file_size) - # Make some random string of size 'fsize' to go in the file. - s = ''.join([sha.new(str(j)).digest() for j in range(fsize//20+1)]) - assert len(s) >= fsize - s = s[:fsize] - f = open(filename1, 'wb') - f.write(s) - f.close() - C1 = CompleteChunkFile(filename1) - if os.path.exists(filename2): - os.remove(filename2) - - if os.path.exists(metaname2): - os.remove(metaname2) - C2 = PartialChunkFile(filename2, metaname2, C1.file_hash, C1.file_size) - assert len(C1) == len(C2) - assert C2.tree[0] == C1.tree[0] - for j in range(len(C2)): - try: - C2[j] - ok = False - except ValueError: - ok = True - if not ok: - raise AssertionError() - for j in range(len(C2)//2): - k = random.randrange(len(C2)) - if len(C1) > 1: - assert C1[k] != C1[(k+1)%len(C1)] - try: - C2[k] = C1[(k+1)%len(C1)] - ok = False - except ValueError: - ok = True - if not ok: - raise AssertionError() - C2[k] = C1[k] - assert C2[k] == C1[k] - for j in range(len(C2)): - C2[j] = C1[j] - assert C2[j] == C1[j] - - os.remove(filename1) - os.remove(filename2) - os.remove(metaname2) - - print ' PartialChunkFile: OK' - - -if __name__ == '__main__': - test() diff --git a/allmydata/client.py b/allmydata/client.py deleted file mode 100644 index 360cdc93..00000000 --- a/allmydata/client.py +++ /dev/null @@ -1,149 +0,0 @@ - -import os, sha -from foolscap import Referenceable -from twisted.application import service -from twisted.python import log -from zope.interface import implements -from allmydata.interfaces import RIClient -from allmydata import node - -from twisted.internet import defer - -from allmydata.util import idlib -from allmydata.storageserver import StorageServer -from allmydata.upload import Uploader -from allmydata.download import Downloader -from allmydata.vdrive import VDrive -from allmydata.webish import WebishServer - -class Client(node.Node, Referenceable): - implements(RIClient) - CERTFILE = "client.pem" - PORTNUMFILE = "client.port" - STOREDIR = 'storage' - NODETYPE = "client" - WEBPORTFILE = "webport" - QUEEN_PBURL_FILE = "roster_pburl" - - def __init__(self, basedir="."): - node.Node.__init__(self, basedir) - self.queen = None # self.queen is either None or a RemoteReference - self.all_peers = set() - self.connections = {} - self.add_service(StorageServer(os.path.join(basedir, self.STOREDIR))) - self.add_service(Uploader()) - self.add_service(Downloader()) - self.add_service(VDrive()) - WEBPORTFILE = os.path.join(self.basedir, self.WEBPORTFILE) - if os.path.exists(WEBPORTFILE): - f = open(WEBPORTFILE, "r") - webport = f.read() # strports string - f.close() - self.add_service(WebishServer(webport)) - self.queen_pburl = None - QUEEN_PBURL_FILE = os.path.join(self.basedir, self.QUEEN_PBURL_FILE) - if os.path.exists(QUEEN_PBURL_FILE): - f = open(QUEEN_PBURL_FILE, "r") - self.queen_pburl = f.read().strip() - f.close() - self.queen_connector = None - - def tub_ready(self): - self.my_pburl = self.tub.registerReference(self) - self.maybe_connect_to_queen() - - def set_queen_pburl(self, queen_pburl): - self.queen_pburl = queen_pburl - self.maybe_connect_to_queen() - - def maybe_connect_to_queen(self): - if not self.running: - return - if not self.my_pburl: - return - if self.queen_connector: - return - if not self.queen_pburl: - self.log("no queen_pburl, cannot connect") - return - self.queen_connector = self.tub.connectTo(self.queen_pburl, - self._got_queen) - - def stopService(self): - if self.queen_connector: - self.queen_connector.stopConnecting() - self.queen_connector = None - return service.MultiService.stopService(self) - - def _got_queen(self, queen): - self.log("connected to queen") - self.queen = queen - queen.notifyOnDisconnect(self._lost_queen) - d = queen.callRemote("hello", - nodeid=self.nodeid, - node=self, - pburl=self.my_pburl) - d.addCallback(self._got_vdrive_root) - - def _got_vdrive_root(self, root): - self.getServiceNamed("vdrive").set_root(root) - if "webish" in self.namedServices: - self.getServiceNamed("webish").set_root_dirnode(root) - - def _lost_queen(self): - self.log("lost connection to queen") - self.queen = None - - def remote_get_service(self, name): - # TODO: 'vdrive' should not be public in the medium term - return self.getServiceNamed(name) - - def remote_add_peers(self, new_peers): - for nodeid, pburl in new_peers: - if nodeid == self.nodeid: - continue - self.log("adding peer %s" % idlib.b2a(nodeid)) - if nodeid in self.all_peers: - self.log("weird, I already had an entry for them") - return - self.all_peers.add(nodeid) - if nodeid not in self.connections: - d = self.tub.getReference(pburl) - def _got_reference(ref, which_nodeid): - self.log("connected to %s" % idlib.b2a(which_nodeid)) - if which_nodeid in self.all_peers: - self.connections[which_nodeid] = ref - else: - log.msg(" ignoring it because we no longer want to talk to them") - d.addCallback(_got_reference, nodeid) - - def remote_lost_peers(self, lost_peers): - for nodeid in lost_peers: - self.log("lost peer %s" % idlib.b2a(nodeid)) - if nodeid in self.all_peers: - self.all_peers.remove(nodeid) - else: - self.log("weird, I didn't have an entry for them") - if nodeid in self.connections: - del self.connections[nodeid] - - def get_remote_service(self, nodeid, servicename): - if nodeid not in self.connections: - return defer.fail(IndexError("no connection to that peer")) - peer = self.connections[nodeid] - d = peer.callRemote("get_service", name=servicename) - return d - - - def permute_peerids(self, key, max_count=None): - # TODO: eventually reduce memory consumption by doing an insertion - # sort of at most max_count elements - results = [] - for nodeid in self.all_peers: - permuted = sha.new(key + nodeid).digest() - results.append((permuted, nodeid)) - results.sort() - results = [r[1] for r in results] - if max_count is None: - return results - return results[:max_count] diff --git a/allmydata/debugshell.py b/allmydata/debugshell.py deleted file mode 100644 index 130c9099..00000000 --- a/allmydata/debugshell.py +++ /dev/null @@ -1,17 +0,0 @@ -import os - -def get_random_bucket_on(nodeid, size=200): - d = app.get_remote_service(nodeid, 'storageserver') - def get_bucket(rss): - return rss.callRemote('allocate_bucket', - verifierid=os.urandom(20), - bucket_num=26, - size=size, - leaser=app.tub.tubID, - ) - d.addCallback(get_bucket) - return d - -def write_to_bucket(bucket, bytes=100): - return bucket.callRemote('write', data=os.urandom(bytes)) - diff --git a/allmydata/download.py b/allmydata/download.py deleted file mode 100644 index a344d039..00000000 --- a/allmydata/download.py +++ /dev/null @@ -1,229 +0,0 @@ - -import os -from zope.interface import Interface, implements -from twisted.python import failure, log -from twisted.internet import defer -from twisted.application import service - -from allmydata.util import idlib -from allmydata import encode - -class NotEnoughPeersError(Exception): - pass - -class HaveAllPeersError(Exception): - # we use this to jump out of the loop - pass - -class FileDownloader: - debug = False - - def __init__(self, peer, verifierid): - self._peer = peer - assert isinstance(verifierid, str) - self._verifierid = verifierid - - def set_download_target(self, target): - self._target = target - self._target.register_canceller(self._cancel) - - def _cancel(self): - pass - - def make_decoder(self): - n = self._shares = 4 - k = self._desired_shares = 2 - self._target.open() - self._decoder = encode.Decoder(self._target, k, n, - self._verifierid) - - def start(self): - log.msg("starting download") - if self.debug: - print "starting download" - # first step: who should we download from? - - # maybe limit max_peers to 2*len(self.shares), to reduce memory - # footprint - max_peers = None - - self.permuted = self._peer.permute_peerids(self._verifierid, max_peers) - for p in self.permuted: - assert isinstance(p, str) - self.landlords = [] # list of (peerid, bucket_num, remotebucket) - - d = defer.maybeDeferred(self._check_next_peer) - d.addCallback(self._got_all_peers) - return d - - def _check_next_peer(self): - if len(self.permuted) == 0: - # there are no more to check - raise NotEnoughPeersError - peerid = self.permuted.pop(0) - - d = self._peer.get_remote_service(peerid, "storageserver") - def _got_peer(service): - bucket_num = len(self.landlords) - if self.debug: print "asking %s" % idlib.b2a(peerid) - d2 = service.callRemote("get_buckets", verifierid=self._verifierid) - def _got_response(buckets): - if buckets: - bucket_nums = [num for (num,bucket) in buckets] - if self.debug: - print " peerid %s has buckets %s" % (idlib.b2a(peerid), - bucket_nums) - - self.landlords.append( (peerid, buckets) ) - if len(self.landlords) >= self._desired_shares: - if self.debug: print " we're done!" - raise HaveAllPeersError - # otherwise we fall through to search more peers - d2.addCallback(_got_response) - return d2 - d.addCallback(_got_peer) - - def _done_with_peer(res): - if self.debug: print "done with peer %s:" % idlib.b2a(peerid) - if isinstance(res, failure.Failure): - if res.check(HaveAllPeersError): - if self.debug: print " all done" - # we're done! - return - if res.check(IndexError): - if self.debug: print " no connection" - else: - if self.debug: print " other error:", res - else: - if self.debug: print " they had data for us" - # we get here for either good peers (when we still need more), or - # after checking a bad peer (and thus still need more). So now we - # need to grab a new peer. - return self._check_next_peer() - d.addBoth(_done_with_peer) - return d - - def _got_all_peers(self, res): - all_buckets = [] - for peerid, buckets in self.landlords: - all_buckets.extend(buckets) - d = self._decoder.start(all_buckets) - def _done(res): - self._target.close() - return self._target.finish() - def _fail(res): - self._target.fail() - return res - d.addCallbacks(_done, _fail) - return d - -def netstring(s): - return "%d:%s," % (len(s), s) - -class IDownloadTarget(Interface): - def open(): - """Called before any calls to write() or close().""" - def write(data): - pass - def close(): - pass - def fail(): - """fail() is called to indicate that the download has failed. No - further methods will be invoked on the IDownloadTarget after fail().""" - def register_canceller(cb): - """The FileDownloader uses this to register a no-argument function - that the target can call to cancel the download. Once this canceller - is invoked, no further calls to write() or close() will be made.""" - def finish(self): - """When the FileDownloader is done, this finish() function will be - called. Whatever it returns will be returned to the invoker of - Downloader.download. - """ - -class FileName: - implements(IDownloadTarget) - def __init__(self, filename): - self._filename = filename - def open(self): - self.f = open(self._filename, "wb") - return self.f - def write(self, data): - self.f.write(data) - def close(self): - self.f.close() - def fail(self): - self.f.close() - os.unlink(self._filename) - def register_canceller(self, cb): - pass # we won't use it - def finish(self): - pass - -class Data: - implements(IDownloadTarget) - def __init__(self): - self._data = [] - def open(self): - pass - def write(self, data): - self._data.append(data) - def close(self): - self.data = "".join(self._data) - del self._data - def fail(self): - del self._data - def register_canceller(self, cb): - pass # we won't use it - def finish(self): - return self.data - -class FileHandle: - implements(IDownloadTarget) - def __init__(self, filehandle): - self._filehandle = filehandle - def open(self): - pass - def write(self, data): - self._filehandle.write(data) - def close(self): - # the originator of the filehandle reserves the right to close it - pass - def fail(self): - pass - def register_canceller(self, cb): - pass - def finish(self): - pass - -class IDownloader(Interface): - def download(verifierid, target): - pass - -class Downloader(service.MultiService): - """I am a service that allows file downloading. - """ - implements(IDownloader) - name = "downloader" - - def download(self, verifierid, t): - assert self.parent - assert self.running - assert isinstance(verifierid, str) - t = IDownloadTarget(t) - assert t.write - assert t.close - dl = FileDownloader(self.parent, verifierid) - dl.set_download_target(t) - dl.make_decoder() - d = dl.start() - return d - - # utility functions - def download_to_data(self, verifierid): - return self.download(verifierid, Data()) - def download_to_filename(self, verifierid, filename): - return self.download(verifierid, FileName(filename)) - def download_to_filehandle(self, verifierid, filehandle): - return self.download(verifierid, FileHandle(filehandle)) - - diff --git a/allmydata/encode.py b/allmydata/encode.py deleted file mode 100644 index ea54fbd2..00000000 --- a/allmydata/encode.py +++ /dev/null @@ -1,50 +0,0 @@ -from twisted.internet import defer -import sha -from allmydata.util import idlib - -def netstring(s): - return "%d:%s," % (len(s), s) - -class Encoder(object): - def __init__(self, infile, m): - self.infile = infile - self.k = 2 - self.m = m - - def do_upload(self, landlords): - dl = [] - data = self.infile.read() - for (peerid, bucket_num, remotebucket) in landlords: - dl.append(remotebucket.callRemote('write', data)) - dl.append(remotebucket.callRemote('close')) - - return defer.DeferredList(dl) - -class Decoder(object): - def __init__(self, outfile, k, m, verifierid): - self.outfile = outfile - self.k = 2 - self.m = m - self._verifierid = verifierid - - def start(self, buckets): - assert len(buckets) >= self.k - dl = [] - for bucketnum, bucket in buckets[:self.k]: - d = bucket.callRemote("read") - dl.append(d) - d2 = defer.DeferredList(dl) - d2.addCallback(self._got_all_data) - return d2 - - def _got_all_data(self, resultslist): - shares = [results for success,results in resultslist if success] - assert len(shares) >= self.k - # here's where the Reed-Solomon magic takes place - self.outfile.write(shares[0]) - hasher = sha.new(netstring("allmydata_v1_verifierid")) - hasher.update(shares[0]) - vid = hasher.digest() - if self._verifierid: - assert self._verifierid == vid, "%s != %s" % (idlib.b2a(self._verifierid), idlib.b2a(vid)) - diff --git a/allmydata/encode_new.py b/allmydata/encode_new.py deleted file mode 100644 index f2ff0ad1..00000000 --- a/allmydata/encode_new.py +++ /dev/null @@ -1,206 +0,0 @@ -#! /usr/bin/python - -import math -from twisted.internet import defer -from allmydata.chunk import HashTree -from Crypto.Cipher import AES -import sha - -def hash(data): - return sha.new(data).digest() - -""" - -The goal of the encoder is to turn the original file into a series of -'shares'. Each share is going to a 'shareholder' (nominally each shareholder -is a different host, but for small meshes there may be overlap). The number -of shares is chosen to hit our reliability goals (more shares on more -machines means more reliability), and is limited by overhead (proportional to -numshares or log(numshares)) and the encoding technology in use (Reed-Solomon -only permits 256 shares total). It is also constrained by the amount of data -we want to send to each host. For estimating purposes, think of 100 shares -out of which we need 25 to reconstruct the file. - -The encoder starts by cutting the original file into segments. All segments -except the last are of equal size. The segment size is chosen to constrain -the memory footprint (which will probably vary between 1x and 4x segment -size) and to constrain the overhead (which will be proportional to either the -number of segments or log(number of segments)). - - -Each segment (A,B,C) is read into memory, encrypted, and encoded into -subshares. The 'share' (say, share #1) that makes it out to a host is a -collection of these subshares (subshare A1, B1, C1), plus some hash-tree -information necessary to validate the data upon retrieval. Only one segment -is handled at a time: all subshares for segment A are delivered before any -work is begun on segment B. - -As subshares are created, we retain the hash of each one. The list of -subshare hashes for a single share (say, hash(A1), hash(B1), hash(C1)) is -used to form the base of a Merkle hash tree for that share (hashtrees[1]). -This hash tree has one terminal leaf per subshare. The complete subshare hash -tree is sent to the shareholder after all the data has been sent. At -retrieval time, the decoder will ask for specific pieces of this tree before -asking for subshares, whichever it needs to validate those subshares. - -[TODO: we don't really need to generate this whole subshare hash tree -ourselves. It would be sufficient to have the shareholder generate it and -just tell us the root. This gives us an extra level of validation on the -transfer, though, and it is relatively cheap to compute.] - -Each of these subshare hash trees has a root hash. The collection of these -root hashes for all shares are collected into the 'share hash tree', which -has one terminal leaf per share. After sending the subshares and the complete -subshare hash tree to each shareholder, we send them the portion of the share -hash tree that is necessary to validate their share. The root of the share -hash tree is put into the URI. - -""" - - - - -class Encoder(object): - - def setup(self, infile): - self.infile = infile - infile.seek(0, 2) - self.file_size = infile.tell() - infile.seek(0, 0) - fsize = 1.0 * self.file_size - self.segment_size = 1024 - self.num_segments = int(math.ceil(fsize / self.segment_size)) - - self.num_shares = 100 - self.share_size = self.file_size / 25 - - def get_reservation_size(self): - self.num_shares = 100 - self.share_size = self.file_size / 25 - overhead = self.compute_overhead() - return self.share_size + overhead - - def setup_encryption(self): - self.key = "\x00"*16 - self.cryptor = AES.new(key=self.key, mode=AES.MODE_CTR, - counterstart="\x00"*16) - self.segment_num = 0 - self.subshare_hashes = [[]] * self.num_shares - # subshare_hashes[i] is a list that will be accumulated and then send - # to landlord[i]. This list contains a hash of each segment_share - # that we sent to that landlord. - self.share_root_hashes = [None] * self.num_shares - - def start(self): - self.setup_encryption() - d = defer.succeed(None) - for i in range(self.num_segments): - d.addCallback(lambda res: self.do_segment(i)) - d.addCallback(lambda res: self.send_all_subshare_hash_trees()) - d.addCallback(lambda res: self.send_all_share_hash_trees()) - d.addCallback(lambda res: self.close_all_shareholders()) - d.addCallback(lambda res: self.done()) - return d - - def encode_segment(self, crypttext): - shares = [crypttext] * self.num_shares - return shares - - def do_segment(self, segnum): - segment_plaintext = self.infile.read(self.segment_size) - segment_crypttext = self.cryptor.encrypt(segment_plaintext) - del segment_plaintext - subshares_for_this_segment = self.encode_segment(segment_crypttext) - del segment_crypttext - dl = [] - for share_num,subshare in enumerate(subshares_for_this_segment): - d = self.send_subshare(share_num, self.segment_num, subshare) - dl.append(d) - self.subshare_hashes[share_num].append(hash(subshare)) - self.segment_num += 1 - return defer.DeferredList(dl) - - def send_subshare(self, share_num, segment_num, subshare): - #if False: - # offset = hash_size + segment_num * segment_size - # return self.send(share_num, "write", subshare, offset) - return self.send(share_num, "put_subshare", segment_num, subshare) - - def send(self, share_num, methname, *args, **kwargs): - ll = self.landlords[share_num] - return ll.callRemote(methname, *args, **kwargs) - - def send_all_subshare_hash_trees(self): - dl = [] - for share_num,hashes in enumerate(self.subshare_hashes): - # hashes is a list of the hashes of all subshares that were sent - # to shareholder[share_num]. - dl.append(self.send_one_subshare_hash_tree(share_num, hashes)) - return defer.DeferredList(dl) - - def send_one_subshare_hash_tree(self, share_num, subshare_hashes): - t = HashTree(subshare_hashes) - all_hashes = list(t) - # all_hashes[0] is the root hash, == hash(ah[1]+ah[2]) - # all_hashes[1] is the left child, == hash(ah[3]+ah[4]) - # all_hashes[n] == hash(all_hashes[2*n+1] + all_hashes[2*n+2]) - self.share_root_hashes[share_num] = t[0] - ll = self.landlords[share_num] - if False: - block = "".join(all_hashes) - return ll.callRemote("write", block, offset=0) - return ll.callRemote("put_subshare_hashes", all_hashes) - - def send_all_share_hash_trees(self): - dl = [] - for h in self.share_root_hashes: - assert h - # create the share hash tree - t = HashTree(self.share_root_hashes) - # the root of this hash tree goes into our URI - self.root_hash = t[0] - # now send just the necessary pieces out to each shareholder - for i in range(self.num_shares): - needed_hash_indices = t.needed_for(i) - dl.append(self.send_one_share_hash_tree(i, needed_hash_indices)) - return defer.DeferredList(dl) - - def send_one_share_hash_tree(self, share_num, needed_hashes): - ll = self.landlords[share_num] - return ll.callRemote("put_share_hashes", needed_hashes) - - def close_all_shareholders(self): - dl = [] - for ll in self.landlords: - dl.append(ll.callRemote("close")) - return defer.DeferredList(dl) - - def done(self): - return self.root_hash - - -from foolscap import RemoteInterface -from foolscap.schema import ListOf, TupleOf, Nothing -_None = Nothing() - - -class RIStorageBucketWriter(RemoteInterface): - def put_subshare(segment_number=int, subshare=str): - return _None - def put_segment_hashes(all_hashes=ListOf(str)): - return _None - def put_share_hashes(needed_hashes=ListOf(TupleOf(int,str))): - return _None - #def write(data=str, offset=int): - # return _None -class RIStorageBucketReader(RemoteInterface): - def get_share_hashes(): - return ListOf(TupleOf(int,str)) - def get_segment_hashes(which=ListOf(int)): - return ListOf(str) - def get_subshare(segment_number=int): - return str - #def read(size=int, offset=int): - # return str - -"figleaf doesn't like the last line of the file to be a comment" diff --git a/allmydata/filetable.py b/allmydata/filetable.py deleted file mode 100644 index b52c367d..00000000 --- a/allmydata/filetable.py +++ /dev/null @@ -1,138 +0,0 @@ - -import os, shutil -from zope.interface import implements -from foolscap import Referenceable -from allmydata.interfaces import RIMutableDirectoryNode -from twisted.application import service -from twisted.python import log - -class DeadDirectoryNodeError(Exception): - """The directory referenced by this node has been deleted.""" - -class BadDirectoryError(Exception): - """There was a problem with the directory being referenced.""" -class BadFileError(Exception): - """The file being referenced does not exist.""" - -class MutableDirectoryNode(Referenceable): - implements(RIMutableDirectoryNode) - - def __init__(self, basedir): - self._basedir = basedir - - def make_subnode(self, basedir): - return self.__class__(basedir) - - def validate_name(self, name): - if name == "." or name == ".." or "/" in name: - raise DeadDirectoryNodeError("bad filename component") - - # these are the public methods, available to anyone who holds a reference - - def list(self): - log.msg("Dir(%s).list" % self._basedir) - results = [] - if not os.path.isdir(self._basedir): - raise DeadDirectoryNodeError("This directory has been deleted") - for name in os.listdir(self._basedir): - absname = os.path.join(self._basedir, name) - if os.path.isdir(absname): - results.append( (name, self.make_subnode(absname)) ) - elif os.path.isfile(absname): - f = open(absname, "rb") - data = f.read() - f.close() - results.append( (name, data) ) - # anything else is ignored - return results - remote_list = list - - def get(self, name): - self.validate_name(name) - absname = os.path.join(self._basedir, name) - if os.path.isdir(absname): - return self.make_subnode(absname) - elif os.path.isfile(absname): - f = open(absname, "rb") - data = f.read() - f.close() - return data - else: - raise BadFileError("there is nothing named '%s' in this directory" - % name) - remote_get = get - - def add_directory(self, name): - self.validate_name(name) - absname = os.path.join(self._basedir, name) - if os.path.isdir(absname): - raise BadDirectoryError("the directory '%s' already exists" % name) - if os.path.exists(absname): - raise BadDirectoryError("the directory '%s' already exists " - "(but isn't a directory)" % name) - os.mkdir(absname) - return self.make_subnode(absname) - remote_add_directory = add_directory - - def add_file(self, name, data): - self.validate_name(name) - f = open(os.path.join(self._basedir, name), "wb") - f.write(data) - f.close() - remote_add_file = add_file - - def remove(self, name): - self.validate_name(name) - absname = os.path.join(self._basedir, name) - if os.path.isdir(absname): - shutil.rmtree(absname) - elif os.path.isfile(absname): - os.unlink(absname) - else: - raise BadFileError("Cannot delete non-existent file '%s'" % name) - remote_remove = remove - - -class GlobalVirtualDrive(service.MultiService): - name = "filetable" - VDRIVEDIR = "vdrive" - - def __init__(self, basedir="."): - service.MultiService.__init__(self) - vdrive_dir = os.path.join(basedir, self.VDRIVEDIR) - if not os.path.exists(vdrive_dir): - os.mkdir(vdrive_dir) - self._root = MutableDirectoryNode(vdrive_dir) - - def get_root(self): - return self._root - - -class Node: - pass - -class MutableFileNode(Node): - """I hold an SSK identifier for a mutable file. My 'contents' are - defined to be the most recent version of the SSK's payload that can - be found. This SSK identifier must be dereferenced to get the - contents.""" - pass -class ImmutableFileNode(Node): - """I hold a CHK identifier for an immutable file. I may have some - metadata as well: ctime, mtime, content-type, and filesize.""" - pass -class ImmutableDirectoryNode(Node): - """I hold a list of child nodes.""" - pass -class MutableDirectoryNode2(Node): - """I hold an SSK identifier for a mutable directory. When - dereferenced, I will have a list of child nodes.""" - pass - -# interesting feature ideas: -# pubsub for MutableDirectoryNode: get rapid notification of changes -# caused by someone else -# -# bind a local physical directory to the MutableDirectoryNode contents: -# each time the vdrive changes, update the local drive to match, and -# vice versa. diff --git a/allmydata/interfaces.py b/allmydata/interfaces.py deleted file mode 100644 index 14d081e3..00000000 --- a/allmydata/interfaces.py +++ /dev/null @@ -1,75 +0,0 @@ - -from foolscap.schema import StringConstraint, ListOf, TupleOf, Any, Nothing -from foolscap import RemoteInterface - -Nodeid = StringConstraint(20) # binary format 20-byte SHA1 hash -PBURL = StringConstraint(150) -Verifierid = StringConstraint(20) -ShareData = StringConstraint(100000) -# these four are here because Foolscap does not yet support the kind of -# restriction I really want to apply to these. -RIClient_ = Any() -Referenceable_ = Any() -RIBucketWriter_ = Any() -RIBucketReader_ = Any() -RIMutableDirectoryNode_ = Any() -RIMutableFileNode_ = Any() - -class RIQueenRoster(RemoteInterface): - def hello(nodeid=Nodeid, node=RIClient_, pburl=PBURL): - return RIMutableDirectoryNode_ # the virtual drive root - -class RIClient(RemoteInterface): - def get_service(name=str): - return Referenceable_ - def add_peers(new_peers=ListOf(TupleOf(Nodeid, PBURL), maxLength=100)): - return Nothing() - def lost_peers(lost_peers=ListOf(Nodeid)): - return Nothing() - -class RIStorageServer(RemoteInterface): - def allocate_bucket(verifierid=Verifierid, bucket_num=int, size=int, - leaser=Nodeid, canary=Referenceable_): - # if the canary is lost before close(), the bucket is deleted - return RIBucketWriter_ - def get_buckets(verifierid=Verifierid): - return ListOf(TupleOf(int, RIBucketReader_)) - -class RIBucketWriter(RemoteInterface): - def write(data=ShareData): - return Nothing() - - def close(): - return Nothing() - - -class RIBucketReader(RemoteInterface): - def read(): - return ShareData - - -class RIMutableDirectoryNode(RemoteInterface): - def list(): - return ListOf( TupleOf(str, # name, relative to directory - (RIMutableDirectoryNode_, Verifierid)), - maxLength=100, - ) - - def get(name=str): - return (RIMutableDirectoryNode_, Verifierid) - - def add_directory(name=str): - return RIMutableDirectoryNode_ - - def add_file(name=str, data=Verifierid): - return Nothing() - - def remove(name=str): - return Nothing() - - # need more to move directories - -# TODO: figleaf gets confused when the last line of a file is a comment. I -# suspect an off-by-one error in the code that decides which lines are code -# and which are not. -pass diff --git a/allmydata/manhole.py b/allmydata/manhole.py deleted file mode 100644 index c0858dc9..00000000 --- a/allmydata/manhole.py +++ /dev/null @@ -1,278 +0,0 @@ - -# this is adapted from my code in Buildbot -warner - -import os.path -import binascii, base64 -from twisted.python import log -from twisted.application import service, strports -from twisted.cred import checkers, portal -from twisted.conch import manhole, telnet, manhole_ssh, checkers as conchc -from twisted.conch.insults import insults -from twisted.internet import protocol - -from zope.interface import implements - -# makeTelnetProtocol and _TelnetRealm are for the TelnetManhole - -class makeTelnetProtocol: - # this curries the 'portal' argument into a later call to - # TelnetTransport() - def __init__(self, portal): - self.portal = portal - - def __call__(self): - auth = telnet.AuthenticatingTelnetProtocol - return telnet.TelnetTransport(auth, self.portal) - -class _TelnetRealm: - implements(portal.IRealm) - - def __init__(self, namespace_maker): - self.namespace_maker = namespace_maker - - def requestAvatar(self, avatarId, *interfaces): - if telnet.ITelnetProtocol in interfaces: - namespace = self.namespace_maker() - p = telnet.TelnetBootstrapProtocol(insults.ServerProtocol, - manhole.ColoredManhole, - namespace) - return (telnet.ITelnetProtocol, p, lambda: None) - raise NotImplementedError() - - -class chainedProtocolFactory: - # this curries the 'namespace' argument into a later call to - # chainedProtocolFactory() - def __init__(self, namespace): - self.namespace = namespace - - def __call__(self): - return insults.ServerProtocol(manhole.ColoredManhole, self.namespace) - -class AuthorizedKeysChecker(conchc.SSHPublicKeyDatabase): - """Accept connections using SSH keys from a given file. - - SSHPublicKeyDatabase takes the username that the prospective client has - requested and attempts to get a ~/.ssh/authorized_keys file for that - username. This requires root access, so it isn't as useful as you'd - like. - - Instead, this subclass looks for keys in a single file, given as an - argument. This file is typically kept in the buildmaster's basedir. The - file should have 'ssh-dss ....' lines in it, just like authorized_keys. - """ - - def __init__(self, authorized_keys_file): - self.authorized_keys_file = os.path.expanduser(authorized_keys_file) - - def checkKey(self, credentials): - f = open(self.authorized_keys_file) - for l in f.readlines(): - l2 = l.split() - if len(l2) < 2: - continue - try: - if base64.decodestring(l2[1]) == credentials.blob: - return 1 - except binascii.Error: - continue - return 0 - -class ModifiedColoredManhole(manhole.ColoredManhole): - def connectionMade(self): - manhole.ColoredManhole.connectionMade(self) - # look in twisted.conch.recvline.RecvLine for hints - self.keyHandlers["\x08"] = self.handle_BACKSPACE - self.keyHandlers["\x15"] = self.handle_KILLLINE - self.keyHandlers["\x01"] = self.handle_HOME - self.keyHandlers["\x04"] = self.handle_DELETE - self.keyHandlers["\x05"] = self.handle_END - self.keyHandlers["\x0b"] = self.handle_KILLLINE # really kill-to-end - #self.keyHandlers["\xe2"] = self.handle_BACKWARDS_WORD # M-b - #self.keyHandlers["\xe6"] = self.handle_FORWARDS_WORD # M-f - - def handle_KILLLINE(self): - self.handle_END() - for i in range(len(self.lineBuffer)): - self.handle_BACKSPACE() - -class _BaseManhole(service.MultiService): - """This provides remote access to a python interpreter (a read/exec/print - loop) embedded in the buildmaster via an internal SSH server. This allows - detailed inspection of the buildmaster state. It is of most use to - buildbot developers. Connect to this by running an ssh client. - """ - - def __init__(self, port, checker, using_ssh=True): - """ - @type port: string or int - @param port: what port should the Manhole listen on? This is a - strports specification string, like 'tcp:12345' or - 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a - simple tcp port. - - @type checker: an object providing the - L{twisted.cred.checkers.ICredentialsChecker} interface - @param checker: if provided, this checker is used to authenticate the - client instead of using the username/password scheme. You must either - provide a username/password or a Checker. Some useful values are:: - import twisted.cred.checkers as credc - import twisted.conch.checkers as conchc - c = credc.AllowAnonymousAccess # completely open - c = credc.FilePasswordDB(passwd_filename) # file of name:passwd - c = conchc.UNIXPasswordDatabase # getpwnam() (probably /etc/passwd) - - @type using_ssh: bool - @param using_ssh: If True, accept SSH connections. If False, accept - regular unencrypted telnet connections. - """ - - # unfortunately, these don't work unless we're running as root - #c = credc.PluggableAuthenticationModulesChecker: PAM - #c = conchc.SSHPublicKeyDatabase() # ~/.ssh/authorized_keys - # and I can't get UNIXPasswordDatabase to work - - service.MultiService.__init__(self) - if type(port) is int: - port = "tcp:%d" % port - self.port = port # for comparison later - self.checker = checker # to maybe compare later - - def makeNamespace(): - # close over 'self' so we can get access to .parent later - from allmydata import debugshell - debugshell.app = self.parent # make client/queen accesible via 'app' - namespace = {} - for sym in dir(debugshell): - if sym.startswith('__') and sym.endswith('__'): - continue - namespace[sym] = getattr(debugshell, sym) - return namespace - - def makeProtocol(): - namespace = makeNamespace() - p = insults.ServerProtocol(ModifiedColoredManhole, namespace) - return p - - self.using_ssh = using_ssh - if using_ssh: - r = manhole_ssh.TerminalRealm() - r.chainedProtocolFactory = makeProtocol - p = portal.Portal(r, [self.checker]) - f = manhole_ssh.ConchFactory(p) - else: - r = _TelnetRealm(makeNamespace) - p = portal.Portal(r, [self.checker]) - f = protocol.ServerFactory() - f.protocol = makeTelnetProtocol(p) - s = strports.service(self.port, f) - s.setServiceParent(self) - - - def startService(self): - service.MultiService.startService(self) - if self.using_ssh: - via = "via SSH" - else: - via = "via telnet" - log.msg("Manhole listening %s on port %s" % (via, self.port)) - - -class TelnetManhole(_BaseManhole): - """This Manhole accepts unencrypted (telnet) connections, and requires a - username and password authorize access. You are encouraged to use the - encrypted ssh-based manhole classes instead.""" - - def __init__(self, port, username, password): - """ - @type port: string or int - @param port: what port should the Manhole listen on? This is a - strports specification string, like 'tcp:12345' or - 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a - simple tcp port. - - @param username: - @param password: username= and password= form a pair of strings to - use when authenticating the remote user. - """ - - self.username = username - self.password = password - - c = checkers.InMemoryUsernamePasswordDatabaseDontUse() - c.addUser(username, password) - - _BaseManhole.__init__(self, port, c, using_ssh=False) - -class PasswordManhole(_BaseManhole): - """This Manhole accepts encrypted (ssh) connections, and requires a - username and password to authorize access. - """ - - def __init__(self, port, username, password): - """ - @type port: string or int - @param port: what port should the Manhole listen on? This is a - strports specification string, like 'tcp:12345' or - 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a - simple tcp port. - - @param username: - @param password: username= and password= form a pair of strings to - use when authenticating the remote user. - """ - - self.username = username - self.password = password - - c = checkers.InMemoryUsernamePasswordDatabaseDontUse() - c.addUser(username, password) - - _BaseManhole.__init__(self, port, c) - -class AuthorizedKeysManhole(_BaseManhole): - """This Manhole accepts ssh connections, and requires that the - prospective client have an ssh private key that matches one of the public - keys in our authorized_keys file. It is created with the name of a file - that contains the public keys that we will accept.""" - - def __init__(self, port, keyfile): - """ - @type port: string or int - @param port: what port should the Manhole listen on? This is a - strports specification string, like 'tcp:12345' or - 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a - simple tcp port. - - @param keyfile: the name of a file (relative to the buildmaster's - basedir) that contains SSH public keys of authorized - users, one per line. This is the exact same format - as used by sshd in ~/.ssh/authorized_keys . - """ - - # TODO: expanduser this, and make it relative to the buildmaster's - # basedir - self.keyfile = keyfile - c = AuthorizedKeysChecker(keyfile) - _BaseManhole.__init__(self, port, c) - -class ArbitraryCheckerManhole(_BaseManhole): - """This Manhole accepts ssh connections, but uses an arbitrary - user-supplied 'checker' object to perform authentication.""" - - def __init__(self, port, checker): - """ - @type port: string or int - @param port: what port should the Manhole listen on? This is a - strports specification string, like 'tcp:12345' or - 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a - simple tcp port. - - @param checker: an instance of a twisted.cred 'checker' which will - perform authentication - """ - - _BaseManhole.__init__(self, port, checker) - - - diff --git a/allmydata/node.py b/allmydata/node.py deleted file mode 100644 index bbb03e33..00000000 --- a/allmydata/node.py +++ /dev/null @@ -1,95 +0,0 @@ - -from twisted.application import service -import os.path -from foolscap import Tub -from allmydata.util.iputil import get_local_ip_for -from allmydata.util import idlib -from twisted.python import log - -class Node(service.MultiService): - # this implements common functionality of both Client nodes and the Queen - # node. - NODETYPE = "unknown NODETYPE" - PORTNUMFILE = None - CERTFILE = None - LOCAL_IP_FILE = "local_ip" - NODEIDFILE = "my_nodeid" - - def __init__(self, basedir="."): - service.MultiService.__init__(self) - self.basedir = os.path.abspath(basedir) - assert self.CERTFILE, "Your node.Node subclass must provide CERTFILE" - certfile = os.path.join(self.basedir, self.CERTFILE) - if os.path.exists(certfile): - f = open(certfile, "rb") - self.tub = Tub(certData=f.read()) - f.close() - else: - self.tub = Tub() - f = open(certfile, "wb") - f.write(self.tub.getCertData()) - f.close() - self.nodeid = idlib.a2b(self.tub.tubID) - f = open(os.path.join(self.basedir, self.NODEIDFILE), "w") - f.write(idlib.b2a(self.nodeid) + "\n") - f.close() - self.short_nodeid = self.tub.tubID[:4] # ready for printing - portnum = 0 - assert self.PORTNUMFILE, "Your node.Node subclass must provide PORTNUMFILE" - self._portnumfile = os.path.join(self.basedir, self.PORTNUMFILE) - if os.path.exists(self._portnumfile): - portnum = int(open(self._portnumfile, "r").read()) - self.tub.listenOn("tcp:%d" % portnum) - # we must wait until our service has started before we can find out - # our IP address and thus do tub.setLocation, and we can't register - # any services with the Tub until after that point - self.tub.setServiceParent(self) - - AUTHKEYSFILEBASE = "authorized_keys." - for f in os.listdir(self.basedir): - if f.startswith(AUTHKEYSFILEBASE): - keyfile = os.path.join(self.basedir, f) - portnum = int(f[len(AUTHKEYSFILEBASE):]) - from allmydata import manhole - m = manhole.AuthorizedKeysManhole(portnum, keyfile) - m.setServiceParent(self) - self.log("AuthorizedKeysManhole listening on %d" % portnum) - - def log(self, msg): - log.msg(self.short_nodeid + ": " + msg) - - def _setup_tub(self, local_ip): - # we can't get a dynamically-assigned portnum until our Tub is - # running, which means after startService. - l = self.tub.getListeners()[0] - portnum = l.getPortnum() - local_ip_filename = os.path.join(self.basedir, self.LOCAL_IP_FILE) - if os.path.exists(local_ip_filename): - f = open(local_ip_filename, "r") - local_ip = f.read() - f.close() - self.tub.setLocation("%s:%d" % (local_ip, portnum)) - if not os.path.exists(self._portnumfile): - # record which port we're listening on, so we can grab the same - # one next time - f = open(self._portnumfile, "w") - f.write("%d\n" % portnum) - f.close() - self.tub.setLocation("%s:%d" % (local_ip, l.getPortnum())) - return self.tub - - def tub_ready(self): - # called when the Tub is available for registerReference - pass - - def add_service(self, s): - s.setServiceParent(self) - return s - - def startService(self): - # note: this class can only be started and stopped once. - service.MultiService.startService(self) - local_ip = get_local_ip_for() - self._setup_tub(local_ip) - self.tub_ready() - self.log("%s running" % self.NODETYPE) diff --git a/allmydata/queen.py b/allmydata/queen.py deleted file mode 100644 index 011d57b5..00000000 --- a/allmydata/queen.py +++ /dev/null @@ -1,76 +0,0 @@ - -import os.path -from foolscap import Referenceable -from foolscap.eventual import eventually -from twisted.application import service -from twisted.python import log -from allmydata.util import idlib -from zope.interface import implements -from allmydata.interfaces import RIQueenRoster -from allmydata import node -from allmydata.filetable import GlobalVirtualDrive - -class Roster(service.MultiService, Referenceable): - implements(RIQueenRoster) - - def __init__(self): - service.MultiService.__init__(self) - self.phonebook = {} - self.connections = {} - self.gvd_root = None - - def set_gvd_root(self, root): - self.gvd_root = root - - def remote_hello(self, nodeid, node, pburl): - log.msg("roster: contact from %s" % idlib.b2a(nodeid)) - eventually(self._educate_the_new_peer, - nodeid, node, list(self.phonebook.items())) - eventually(self._announce_new_peer, - nodeid, pburl, list(self.connections.values())) - self.phonebook[nodeid] = pburl - self.connections[nodeid] = node - node.notifyOnDisconnect(self._lost_node, nodeid) - return self.gvd_root - - def _educate_the_new_peer(self, nodeid, node, new_peers): - log.msg("roster: educating %s (%d)" % (idlib.b2a(nodeid)[:4], len(new_peers))) - node.callRemote("add_peers", new_peers=new_peers) - - def _announce_new_peer(self, new_nodeid, new_node_pburl, peers): - log.msg("roster: announcing %s to everybody (%d)" % (idlib.b2a(new_nodeid)[:4], len(peers))) - for targetnode in peers: - targetnode.callRemote("add_peers", - new_peers=[(new_nodeid, new_node_pburl)]) - - def _lost_node(self, nodeid): - log.msg("roster: lost contact with %s" % idlib.b2a(nodeid)) - del self.phonebook[nodeid] - del self.connections[nodeid] - eventually(self._announce_lost_peer, nodeid) - - def _announce_lost_peer(self, lost_nodeid): - for targetnode in self.connections.values(): - targetnode.callRemote("lost_peers", lost_peers=[lost_nodeid]) - - - -class Queen(node.Node): - CERTFILE = "queen.pem" - PORTNUMFILE = "queen.port" - NODETYPE = "queen" - - def __init__(self, basedir="."): - node.Node.__init__(self, basedir) - self.gvd = self.add_service(GlobalVirtualDrive(basedir)) - self.urls = {} - - def tub_ready(self): - r = self.add_service(Roster()) - self.urls["roster"] = self.tub.registerReference(r, "roster") - self.log(" roster is at %s" % self.urls["roster"]) - f = open(os.path.join(self.basedir, "roster_pburl"), "w") - f.write(self.urls["roster"] + "\n") - f.close() - r.set_gvd_root(self.gvd.get_root()) - diff --git a/allmydata/scripts/__init__.py b/allmydata/scripts/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/allmydata/scripts/runner.py b/allmydata/scripts/runner.py deleted file mode 100644 index ecff3201..00000000 --- a/allmydata/scripts/runner.py +++ /dev/null @@ -1,184 +0,0 @@ -#! /usr/bin/python - -import os, sys, signal, time -from twisted.python import usage - -class StartOptions(usage.Options): - optParameters = [ - ["basedir", "C", ".", "which directory to start the node in"], - ] - -class StopOptions(usage.Options): - optParameters = [ - ["basedir", "C", ".", "which directory to stop the node in"], - ] - -class RestartOptions(usage.Options): - optParameters = [ - ["basedir", "C", ".", "which directory to restart the node in"], - ] - -class CreateClientOptions(usage.Options): - optParameters = [ - ["basedir", "C", None, "which directory to create the client in"], - ] - - def parseArgs(self, *args): - if len(args) > 0: - self['basedir'] = args[0] - if len(args) > 1: - raise usage.UsageError("I wasn't expecting so many arguments") - - def postOptions(self): - if self['basedir'] is None: - raise usage.UsageError(" parameter is required") - self['basedir'] = os.path.abspath(self['basedir']) - -class CreateQueenOptions(usage.Options): - optParameters = [ - ["basedir", "C", None, "which directory to create the queen in"], - ] - - def parseArgs(self, *args): - if len(args) > 0: - self['basedir'] = args[0] - if len(args) > 1: - raise usage.UsageError("I wasn't expecting so many arguments") - - def postOptions(self): - if self['basedir'] is None: - raise usage.UsageError(" parameter is required") - self['basedir'] = os.path.abspath(self['basedir']) - -client_tac = """ -# -*- python -*- - -from allmydata import client -from twisted.application import service - -c = client.Client() - -application = service.Application("allmydata_client") -c.setServiceParent(application) -""" - -queen_tac = """ -# -*- python -*- - -from allmydata import queen -from twisted.application import service - -c = queen.Queen() - -application = service.Application("allmydata_queen") -c.setServiceParent(application) -""" - -class Options(usage.Options): - synopsis = "Usage: allmydata [command options]" - - subCommands = [ - ["create-client", None, CreateClientOptions, "Create a client node."], - ["create-queen", None, CreateQueenOptions, "Create a queen node."], - ["start", None, StartOptions, "Start a node (of any type)."], - ["stop", None, StopOptions, "Stop a node."], - ["restart", None, RestartOptions, "Restart a node."], - ] - - def postOptions(self): - if not hasattr(self, 'subOptions'): - raise usage.UsageError("must specify a command") - -def run(): - config = Options() - try: - config.parseOptions() - except usage.error, e: - print "%s: %s" % (sys.argv[0], e) - print - c = getattr(config, 'subOptions', config) - print str(c) - sys.exit(1) - - command = config.subCommand - so = config.subOptions - - if command == "create-client": - rc = create_client(so) - elif command == "create-queen": - rc = create_queen(so) - elif command == "start": - rc = start(so) - elif command == "stop": - rc = stop(so) - elif command == "restart": - rc = restart(so) - rc = rc or 0 - sys.exit(rc) - -def create_client(config): - basedir = config['basedir'] - os.mkdir(basedir) - f = open(os.path.join(basedir, "client.tac"), "w") - f.write(client_tac) - f.close() - print "client created in %s, please copy roster_pburl into the directory" % basedir - -def create_queen(config): - basedir = config['basedir'] - os.mkdir(basedir) - f = open(os.path.join(basedir, "queen.tac"), "w") - f.write(queen_tac) - f.close() - print "queen created in %s" % basedir - -def start(config): - basedir = config['basedir'] - if os.path.exists(os.path.join(basedir, "client.tac")): - tac = "client.tac" - type = "client" - elif os.path.exists(os.path.join(basedir, "queen.tac")): - tac = "queen.tac" - type = "queen" - else: - print "%s does not look like a node directory" % basedir - sys.exit(1) - os.chdir(basedir) - rc = os.system("twistd -y %s" % tac) - if rc == 0: - print "node probably started" - return 0 - else: - print "node probably not started" - return 1 - -def stop(config): - basedir = config['basedir'] - pidfile = os.path.join(basedir, "twistd.pid") - if not os.path.exists(pidfile): - print "%s does not look like a running node directory (no twistd.pid)" % basedir - return 1 - pid = open(pidfile, "r").read() - pid = int(pid) - - timer = 0 - os.kill(pid, signal.SIGTERM) - time.sleep(0.1) - while timer < 5: - # poll once per second until twistd.pid goes away, up to 5 seconds - try: - os.kill(pid, 0) - except OSError: - print "process %d is dead" % pid - return - timer += 1 - time.sleep(1) - print "never saw process go away" - return 1 - -def restart(config): - rc = stop(config) - if rc: - print "not restarting" - return rc - return start(config) diff --git a/allmydata/storageserver.py b/allmydata/storageserver.py deleted file mode 100644 index 868dc99a..00000000 --- a/allmydata/storageserver.py +++ /dev/null @@ -1,34 +0,0 @@ -import os - -from foolscap import Referenceable -from twisted.application import service - -from allmydata.bucketstore import BucketStore -from zope.interface import implements -from allmydata.interfaces import RIStorageServer -from allmydata.util import idlib - -class BucketAlreadyExistsError(Exception): - pass - -class StorageServer(service.MultiService, Referenceable): - implements(RIStorageServer) - name = 'storageserver' - - def __init__(self, store_dir): - if not os.path.isdir(store_dir): - os.mkdir(store_dir) - service.MultiService.__init__(self) - self._bucketstore = BucketStore(store_dir) - self._bucketstore.setServiceParent(self) - - def remote_allocate_bucket(self, verifierid, bucket_num, size, leaser, - canary): - if self._bucketstore.has_bucket(verifierid): - raise BucketAlreadyExistsError() - lease = self._bucketstore.allocate_bucket(verifierid, bucket_num, size, - idlib.b2a(leaser), canary) - return lease - - def remote_get_buckets(self, verifierid): - return self._bucketstore.get_buckets(verifierid) diff --git a/allmydata/test/__init__.py b/allmydata/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/allmydata/test/figleaf.excludes b/allmydata/test/figleaf.excludes deleted file mode 100644 index 0b779a91..00000000 --- a/allmydata/test/figleaf.excludes +++ /dev/null @@ -1,2 +0,0 @@ -^/home/warner/stuff/python/twisted/Twisted/ -^/var/lib diff --git a/allmydata/test/test_client.py b/allmydata/test/test_client.py deleted file mode 100644 index c067c303..00000000 --- a/allmydata/test/test_client.py +++ /dev/null @@ -1,19 +0,0 @@ - -from twisted.trial import unittest - -from allmydata import client - -class Basic(unittest.TestCase): - def test_loadable(self): - c = client.Client("") - c.startService() - return c.stopService() - - def test_permute(self): - c = client.Client("") - c.all_peers = ["%d" % i for i in range(5)] - self.failUnlessEqual(c.permute_peerids("one"), ['3','1','0','4','2']) - self.failUnlessEqual(c.permute_peerids("one", 3), ['3','1','0']) - self.failUnlessEqual(c.permute_peerids("two"), ['0','4','2','1','3']) - c.all_peers = [] - self.failUnlessEqual(c.permute_peerids("one"), []) diff --git a/allmydata/test/test_encode.py b/allmydata/test/test_encode.py deleted file mode 100644 index 9e8b42c3..00000000 --- a/allmydata/test/test_encode.py +++ /dev/null @@ -1,19 +0,0 @@ -#! /usr/bin/python - -from twisted.trial import unittest -from twisted.internet import defer -from allmydata import encode_new -from cStringIO import StringIO - -class MyEncoder(encode_new.Encoder): - def send(self, share_num, methname, *args, **kwargs): - return defer.succeed(None) - -class Encode(unittest.TestCase): - def OFFtest_1(self): - e = MyEncoder() - data = StringIO("some data to encode\n") - e.setup(data) - d = e.start() - return d - diff --git a/allmydata/test/test_filetable.py b/allmydata/test/test_filetable.py deleted file mode 100644 index f72a9d31..00000000 --- a/allmydata/test/test_filetable.py +++ /dev/null @@ -1,57 +0,0 @@ - -import os -from twisted.trial import unittest -from allmydata.filetable import MutableDirectoryNode, \ - DeadDirectoryNodeError, BadDirectoryError, BadFileError - - -class FileTable(unittest.TestCase): - def test_files(self): - os.mkdir("filetable") - root = MutableDirectoryNode(os.path.abspath("filetable")) - self.failUnlessEqual(root.list(), []) - root.add_file("one", "vid-one") - root.add_file("two", "vid-two") - self.failUnlessEqual(root.list(), [("one", "vid-one"), - ("two", "vid-two")]) - root.remove("two") - self.failUnlessEqual(root.list(), [("one", "vid-one")]) - self.failUnlessRaises(BadFileError, root.remove, "two") - self.failUnlessRaises(BadFileError, root.remove, "three") - - self.failUnlessEqual(root.get("one"), "vid-one") - self.failUnlessRaises(BadFileError, root.get, "missing") - - # now play with directories - subdir1 = root.add_directory("subdir1") - self.failUnless(isinstance(subdir1, MutableDirectoryNode)) - subdir1a = root.get("subdir1") - self.failUnless(isinstance(subdir1a, MutableDirectoryNode)) - self.failUnlessEqual(subdir1a._basedir, subdir1._basedir) - entries = root.list() - self.failUnlessEqual(len(entries), 2) - one_index = entries.index( ("one", "vid-one") ) - subdir_index = 1 - one_index - self.failUnlessEqual(entries[subdir_index][0], "subdir1") - subdir2 = entries[subdir_index][1] - self.failUnless(isinstance(subdir2, MutableDirectoryNode)) - - self.failUnlessEqual(subdir1.list(), []) - self.failUnlessEqual(subdir2.list(), []) - - subdir1.add_file("subone", "vid-subone") - self.failUnlessEqual(subdir1.list(), [("subone", "vid-subone")]) - self.failUnlessEqual(subdir2.list(), [("subone", "vid-subone")]) - - self.failUnlessEqual(len(root.list()), 2) - - self.failUnlessRaises(BadDirectoryError, root.add_directory, "subdir1") - self.failUnlessRaises(BadDirectoryError, root.add_directory, "one") - - root.remove("subdir1") - self.failUnlessEqual(root.list(), [("one", "vid-one")]) - - # should our (orphaned) subdir1/subdir2 node still be able to do - # anything? - self.failUnlessRaises(DeadDirectoryNodeError, subdir1.list) - diff --git a/allmydata/test/test_queen.py b/allmydata/test/test_queen.py deleted file mode 100644 index 7e12917a..00000000 --- a/allmydata/test/test_queen.py +++ /dev/null @@ -1,10 +0,0 @@ - -from twisted.trial import unittest - -from allmydata import queen - -class Basic(unittest.TestCase): - def test_loadable(self): - q = queen.Queen() - q.startService() - return q.stopService() diff --git a/allmydata/test/test_storage.py b/allmydata/test/test_storage.py deleted file mode 100644 index 6e7b57d1..00000000 --- a/allmydata/test/test_storage.py +++ /dev/null @@ -1,147 +0,0 @@ - -import os -import random - -from twisted.trial import unittest -from twisted.application import service -from twisted.internet import defer -from foolscap import Tub, Referenceable -from foolscap.eventual import flushEventualQueue - -from allmydata import client - -class Canary(Referenceable): - pass - -class StorageTest(unittest.TestCase): - - def setUp(self): - self.svc = service.MultiService() - self.node = client.Client('') - self.node.setServiceParent(self.svc) - self.tub = Tub() - self.tub.setServiceParent(self.svc) - return self.svc.startService() - - def test_create_bucket(self): - """ - Check that the storage server can return bucket data accurately. - """ - vid = os.urandom(20) - bnum = random.randrange(0, 256) - data = os.urandom(random.randint(1024, 16384)) - - rssd = self.tub.getReference(self.node.my_pburl) - def get_storageserver(node): - return node.callRemote('get_service', name='storageserver') - rssd.addCallback(get_storageserver) - - def create_bucket(storageserver): - return storageserver.callRemote('allocate_bucket', - verifierid=vid, - bucket_num=bnum, - size=len(data), - leaser=self.node.nodeid, - canary=Canary(), - ) - rssd.addCallback(create_bucket) - - def write_to_bucket(bucket): - def write_some(junk, bytes): - return bucket.callRemote('write', data=bytes) - def finalise(junk): - return bucket.callRemote('close') - off1 = len(data) / 2 - off2 = 3 * len(data) / 4 - d = defer.succeed(None) - d.addCallback(write_some, data[:off1]) - d.addCallback(write_some, data[off1:off2]) - d.addCallback(write_some, data[off2:]) - d.addCallback(finalise) - return d - rssd.addCallback(write_to_bucket) - - def get_node_again(junk): - return self.tub.getReference(self.node.my_pburl) - rssd.addCallback(get_node_again) - rssd.addCallback(get_storageserver) - - def get_buckets(storageserver): - return storageserver.callRemote('get_buckets', verifierid=vid) - rssd.addCallback(get_buckets) - - def read_buckets(buckets): - self.failUnlessEqual(len(buckets), 1) - bucket_num, bucket = buckets[0] - self.failUnlessEqual(bucket_num, bnum) - - def check_data(bytes_read): - self.failUnlessEqual(bytes_read, data) - d = bucket.callRemote('read') - d.addCallback(check_data) - return d - rssd.addCallback(read_buckets) - - return rssd - - def test_overwrite(self): - """ - Check that the storage server rejects an attempt to write too much data. - """ - vid = os.urandom(20) - bnum = random.randrange(0, 256) - data = os.urandom(random.randint(1024, 16384)) - - rssd = self.tub.getReference(self.node.my_pburl) - def get_storageserver(node): - return node.callRemote('get_service', name='storageserver') - rssd.addCallback(get_storageserver) - - def create_bucket(storageserver): - return storageserver.callRemote('allocate_bucket', - verifierid=vid, - bucket_num=bnum, - size=len(data), - leaser=self.node.nodeid, - canary=Canary(), - ) - rssd.addCallback(create_bucket) - - def write_to_bucket(bucket): - def write_some(junk, bytes): - return bucket.callRemote('write', data=bytes) - def finalise(junk): - return bucket.callRemote('close') - off1 = len(data) / 2 - off2 = 3 * len(data) / 4 - d = defer.succeed(None) - d.addCallback(write_some, data[:off1]) - d.addCallback(write_some, data[off1:off2]) - d.addCallback(write_some, data[off2:]) - # and then overwrite - d.addCallback(write_some, data[off1:off2]) - d.addCallback(finalise) - return d - rssd.addCallback(write_to_bucket) - - self.deferredShouldFail(rssd, ftype=AssertionError) - return rssd - - def deferredShouldFail(self, d, ftype=None, checker=None): - - def _worked(res): - self.fail("hey, this was supposed to fail, not return %s" % res) - if not ftype and not checker: - d.addCallbacks(_worked, - lambda f: None) - elif ftype and not checker: - d.addCallbacks(_worked, - lambda f: f.trap(ftype) or None) - else: - d.addCallbacks(_worked, - checker) - - def tearDown(self): - d = self.svc.stopService() - d.addCallback(lambda res: flushEventualQueue()) - return d diff --git a/allmydata/test/test_system.py b/allmydata/test/test_system.py deleted file mode 100644 index 165e42d8..00000000 --- a/allmydata/test/test_system.py +++ /dev/null @@ -1,143 +0,0 @@ - -from twisted.trial import unittest -from twisted.internet import defer, reactor -from twisted.application import service -from allmydata import client, queen -import os -from foolscap.eventual import flushEventualQueue -from twisted.python import log -from allmydata.util import idlib -from twisted.web.client import getPage - -class SystemTest(unittest.TestCase): - def setUp(self): - self.sparent = service.MultiService() - self.sparent.startService() - def tearDown(self): - d = self.sparent.stopService() - d.addCallback(lambda res: flushEventualQueue()) - def _done(res): - d1 = defer.Deferred() - reactor.callLater(0.1, d1.callback, None) - return d1 - d.addCallback(_done) - return d - - def add_service(self, s): - s.setServiceParent(self.sparent) - return s - - def set_up_nodes(self, NUMCLIENTS=5): - self.numclients = NUMCLIENTS - if not os.path.isdir("queen"): - os.mkdir("queen") - q = self.queen = self.add_service(queen.Queen(basedir="queen")) - self.queen_pburl = q.urls["roster"] - self.clients = [] - for i in range(NUMCLIENTS): - basedir = "client%d" % i - if not os.path.isdir(basedir): - os.mkdir(basedir) - if i == 0: - f = open(os.path.join(basedir, "webport"), "w") - f.write("tcp:0:interface=127.0.0.1") - f.close() - c = self.add_service(client.Client(basedir=basedir)) - c.set_queen_pburl(self.queen_pburl) - self.clients.append(c) - log.msg("STARTING") - d = self.wait_for_connections() - def _connected(res): - # now find out where the web port was - l = self.clients[0].getServiceNamed("webish").listener - port = l._port.getHost().port - self.webish_url = "http://localhost:%d/" % port - d.addCallback(_connected) - return d - - def wait_for_connections(self, ignored=None): - for c in self.clients: - if len(c.connections) != self.numclients - 1: - d = defer.Deferred() - d.addCallback(self.wait_for_connections) - reactor.callLater(0.05, d.callback, None) - return d - return defer.succeed(None) - - def test_connections(self): - d = self.set_up_nodes() - def _check(res): - for c in self.clients: - self.failUnlessEqual(len(c.connections), 4) - d.addCallback(_check) - return d - test_connections.timeout = 20 - - def test_upload_and_download(self): - DATA = "Some data to upload\n" - d = self.set_up_nodes() - def _do_upload(res): - log.msg("UPLOADING") - u = self.clients[0].getServiceNamed("uploader") - d1 = u.upload_data(DATA) - return d1 - d.addCallback(_do_upload) - def _upload_done(verifierid): - log.msg("upload finished: verifierid=%s" % idlib.b2a(verifierid)) - dl = self.clients[1].getServiceNamed("downloader") - d1 = dl.download_to_data(verifierid) - return d1 - d.addCallback(_upload_done) - def _download_done(data): - log.msg("download finished") - self.failUnlessEqual(data, DATA) - d.addCallback(_download_done) - return d - test_upload_and_download.timeout = 20 - - def test_vdrive(self): - self.data = DATA = "Some data to publish to the virtual drive\n" - d = self.set_up_nodes() - def _do_publish(res): - log.msg("PUBLISHING") - v0 = self.clients[0].getServiceNamed("vdrive") - d1 = v0.make_directory("/", "subdir1") - d1.addCallback(lambda subdir1: - v0.put_file_by_data(subdir1, "mydata567", DATA)) - return d1 - d.addCallback(_do_publish) - def _publish_done(res): - log.msg("publish finished") - v1 = self.clients[1].getServiceNamed("vdrive") - d1 = v1.get_file_to_data("/subdir1/mydata567") - return d1 - d.addCallback(_publish_done) - def _get_done(data): - log.msg("get finished") - self.failUnlessEqual(data, DATA) - d.addCallback(_get_done) - d.addCallback(self._test_web) - return d - test_vdrive.timeout = 20 - - def _test_web(self, res): - base = self.webish_url - d = getPage(base) - def _got_welcome(page): - expected = "Connected Peers: %d" % (self.numclients-1) - self.failUnless(expected in page, - "I didn't see the right 'connected peers' message " - "in: %s" % page - ) - d.addCallback(_got_welcome) - d.addCallback(lambda res: getPage(base + "vdrive/subdir1")) - def _got_subdir1(page): - # there ought to be an href for our file - self.failUnless(">mydata567" in page) - d.addCallback(_got_subdir1) - d.addCallback(lambda res: getPage(base + "vdrive/subdir1/mydata567")) - def _got_data(page): - self.failUnlessEqual(page, self.data) - d.addCallback(_got_data) - return d - diff --git a/allmydata/test/test_upload.py b/allmydata/test/test_upload.py deleted file mode 100644 index 9d3e44c8..00000000 --- a/allmydata/test/test_upload.py +++ /dev/null @@ -1,173 +0,0 @@ - -from twisted.trial import unittest -from twisted.internet import defer -from cStringIO import StringIO - -from allmydata import upload - -class StringBucketProxy: - # This is for unit tests: make a StringIO look like a RIBucketWriter. - - def __init__(self): - self.data = StringIO() - self.size = None - self.done = False - - def callRemote(self, methname, **kwargs): - if methname == "write": - return defer.maybeDeferred(self.write, **kwargs) - elif methname == "close": - return defer.maybeDeferred(self.close, **kwargs) - else: - return defer.fail(NameError("no such method named %s" % methname)) - - def write(self, data): - self.data.write(data) - def close(self): - self.done = True - - -class FakePeer: - def __init__(self, peerid, response): - self.peerid = peerid - self.response = response - - def callRemote(self, methname, *args, **kwargs): - assert not args - return defer.maybeDeferred(self._callRemote, methname, **kwargs) - - def _callRemote(self, methname, **kwargs): - assert methname == "allocate_bucket" - assert kwargs["size"] == 100 - assert kwargs["leaser"] == "fakeclient" - if self.response == "good": - return self - raise upload.TooFullError() - -class FakeClient: - nodeid = "fakeclient" - def __init__(self, responses): - self.peers = [] - for peerid,r in enumerate(responses): - if r == "disconnected": - self.peers.append(None) - else: - self.peers.append(FakePeer(str(peerid), r)) - - def permute_peerids(self, key, max_peers): - assert max_peers == None - return [str(i) for i in range(len(self.peers))] - - def get_remote_service(self, peerid, name): - peer = self.peers[int(peerid)] - if not peer: - return defer.fail(IndexError("no connection to that peer")) - return defer.succeed(peer) - -class NextPeerUploader(upload.FileUploader): - def _got_all_peers(self, res): - return res - -class NextPeer(unittest.TestCase): - responses = ["good", # 0 - "full", # 1 - "full", # 2 - "disconnected", # 3 - "good", # 4 - ] - - def compare_landlords(self, u, c, expected): - exp = [(str(peerid), bucketnum, c.peers[peerid]) - for peerid, bucketnum in expected] - self.failUnlessEqual(u.landlords, exp) - - def test_0(self): - c = FakeClient([]) - u = NextPeerUploader(c) - u._verifierid = "verifierid" - u._shares = 2 - u._share_size = 100 - d = u.start() - def _check(f): - f.trap(upload.NotEnoughPeersError) - d.addCallbacks(lambda res: self.fail("this was supposed to fail"), - _check) - return d - - def test_1(self): - c = FakeClient(self.responses) - u = NextPeerUploader(c) - u._verifierid = "verifierid" - u._shares = 2 - u._share_size = 100 - d = u.start() - def _check(res): - self.failUnlessEqual(u.goodness_points, 2) - self.compare_landlords(u, c, [(0, 0), - (4, 1), - ]) - d.addCallback(_check) - return d - - def test_2(self): - c = FakeClient(self.responses) - u = NextPeerUploader(c) - u._verifierid = "verifierid" - u._shares = 3 - u._share_size = 100 - d = u.start() - def _check(res): - self.failUnlessEqual(u.goodness_points, 3) - self.compare_landlords(u, c, [(0, 0), - (4, 1), - (0, 2), - ]) - d.addCallback(_check) - return d - - responses2 = ["good", # 0 - "full", # 1 - "full", # 2 - "good", # 3 - "full", # 4 - ] - - def test_3(self): - c = FakeClient(self.responses2) - u = NextPeerUploader(c) - u._verifierid = "verifierid" - u._shares = 3 - u._share_size = 100 - d = u.start() - def _check(res): - self.failUnlessEqual(u.goodness_points, 3) - self.compare_landlords(u, c, [(0, 0), - (3, 1), - (0, 2), - ]) - d.addCallback(_check) - return d - - responses3 = ["good", # 0 - "good", # 1 - "good", # 2 - "good", # 3 - "good", # 4 - ] - - def test_4(self): - c = FakeClient(self.responses3) - u = NextPeerUploader(c) - u._verifierid = "verifierid" - u._shares = 4 - u._share_size = 100 - d = u.start() - def _check(res): - self.failUnlessEqual(u.goodness_points, 4) - self.compare_landlords(u, c, [(0, 0), - (1, 1), - (2, 2), - (3, 3), - ]) - d.addCallback(_check) - return d diff --git a/allmydata/test/test_vdrive.py b/allmydata/test/test_vdrive.py deleted file mode 100644 index 3610a66b..00000000 --- a/allmydata/test/test_vdrive.py +++ /dev/null @@ -1,68 +0,0 @@ - -import os -from twisted.trial import unittest -from twisted.internet import defer -from allmydata import vdrive, filetable - -class LocalDirNode(filetable.MutableDirectoryNode): - def callRemote(self, methname, *args, **kwargs): - def _call(): - meth = getattr(self, methname) - return meth(*args, **kwargs) - return defer.maybeDeferred(_call) - - -class Traverse(unittest.TestCase): - def make_tree(self, basedir): - os.makedirs(basedir) - root = LocalDirNode(basedir) - self.d1 = d1 = root.add_directory("d1") - self.d2 = d2 = root.add_directory("d2") - root.add_file("a", "a") - root.add_file("b", "b") - d1.add_file("1.a", "1.a") - d1.add_file("1.b", "1.b") - d2.add_file("2.a", "2.a") - d2.add_file("2.b", "2.b") - return root - - def test_one(self): - basedir = "test_vdrive/one" - root = self.make_tree(basedir) - v = vdrive.VDrive() - v.set_root(root) - - d = v.get_dir("") - d.addCallback(lambda dir: self.failUnlessEqual(dir, root)) - d.addCallback(lambda res: v.get_dir("/d1")) - def _check(dir): - self.failUnless(isinstance(dir, LocalDirNode)) - self.failUnlessEqual(dir._basedir, self.d1._basedir) - d.addCallback(_check) - - - d.addCallback(lambda res: v.listdir("")) - d.addCallback(lambda files: - self.failUnlessEqual(sorted(files), - ["a", "b", "d1", "d2"])) - d.addCallback(lambda res: v.listdir("/")) - d.addCallback(lambda files: - self.failUnlessEqual(sorted(files), - ["a", "b", "d1", "d2"])) - d.addCallback(lambda res: v.listdir("d1")) - d.addCallback(lambda files: - self.failUnlessEqual(sorted(files), - ["1.a", "1.b"])) - - d.addCallback(lambda res: v.make_directory("", "d3")) - d.addCallback(lambda res: v.listdir("")) - d.addCallback(lambda files: - self.failUnlessEqual(sorted(files), - ["a", "b", "d1", "d2", "d3"])) - - d.addCallback(lambda res: v.make_directory("d2", "d2.1")) - d.addCallback(lambda res: v.listdir("/d2")) - d.addCallback(lambda files: - self.failUnlessEqual(sorted(files), - ["2.a", "2.b", "d2.1"])) - return d diff --git a/allmydata/test/trial_figleaf.py b/allmydata/test/trial_figleaf.py deleted file mode 100644 index 05780476..00000000 --- a/allmydata/test/trial_figleaf.py +++ /dev/null @@ -1,127 +0,0 @@ - -"""A Trial IReporter plugin that gathers figleaf code-coverage information. - -Once this plugin is installed, trial can be invoked with one of two new ---reporter options: - - trial --reporter=verbose-figleaf ARGS - trial --reporter-bwverbose-figleaf ARGS - -Once such a test run has finished, there will be a .figleaf file in the -top-level directory. This file can be turned into a directory of .html files -(with index.html as the starting point) by running: - - figleaf2html -d OUTPUTDIR [-x EXCLUDEFILE] - -Figleaf thinks of everyting in terms of absolute filenames rather than -modules. The EXCLUDEFILE may be necessary to keep it from providing reports -on non-Code-Under-Test files that live in unusual locations. In particular, -if you use extra PYTHONPATH arguments to point at some alternate version of -an upstream library (like Twisted), or if something like debian's -python-support puts symlinks to .py files in sys.path but not the .py files -themselves, figleaf will present coverage information on both of these. The -EXCLUDEFILE option might help to inhibit these. - -Other figleaf problems: - - the annotated code files are written to BASENAME(file).html, which results - in collisions between similarly-named source files. - - The line-wise coverage information isn't quite right. Blank lines are - counted as unreached code, lambdas aren't quite right, and some multiline - comments (docstrings?) aren't quite right. - -""" - -# TODO: pull some of figleaf into our tree so we can customize it more -# easily. - -from twisted.trial.reporter import TreeReporter, VerboseTextReporter - -# These plugins are registered via twisted/plugins/allmydata_trial.py . See -# the notes there for an explanation of how that works. - - - -# Reporters don't really get told about the suite starting and stopping. - -# The Reporter class is imported before the test classes are. - -# The test classes are imported before the Reporter is created. To get -# control earlier than that requires modifying twisted/scripts/trial.py . - -# Then Reporter.__init__ is called. - -# Then tests run, calling things like write() and addSuccess(). Each test is -# framed by a startTest/stopTest call. - -# Then the results are emitted, calling things like printErrors, -# printSummary, and wasSuccessful. - -# So for code-coverage (not including import), start in __init__ and finish -# in printSummary. To include import, we have to start in our own import and -# finish in printSummary. - -import figleaf -figleaf.start() - -class FigleafReporter(TreeReporter): - def __init__(self, *args, **kwargs): - TreeReporter.__init__(self, *args, **kwargs) - - def printSummary(self): - figleaf.stop() - figleaf.write_coverage(".figleaf") - print "Figleaf results written to .figleaf" - return TreeReporter.printSummary(self) - -class FigleafTextReporter(VerboseTextReporter): - def __init__(self, *args, **kwargs): - VerboseTextReporter.__init__(self, *args, **kwargs) - - def printSummary(self): - figleaf.stop() - figleaf.write_coverage(".figleaf") - print "Figleaf results written to .figleaf" - return VerboseTextReporter.printSummary(self) - -class not_FigleafReporter(object): - # this class, used as a reporter on a fully-passing test suite, doesn't - # trigger exceptions. So it is a guide to what methods are invoked on a - # Reporter. - def __init__(self, *args, **kwargs): - print "FIGLEAF HERE" - self.r = TreeReporter(*args, **kwargs) - self.shouldStop = self.r.shouldStop - self.separator = self.r.separator - self.testsRun = self.r.testsRun - self._starting2 = False - - def write(self, *args): - if not self._starting2: - self._starting2 = True - print "FIRST WRITE" - return self.r.write(*args) - - def startTest(self, *args, **kwargs): - return self.r.startTest(*args, **kwargs) - - def stopTest(self, *args, **kwargs): - return self.r.stopTest(*args, **kwargs) - - def addSuccess(self, *args, **kwargs): - return self.r.addSuccess(*args, **kwargs) - - def printErrors(self, *args, **kwargs): - return self.r.printErrors(*args, **kwargs) - - def writeln(self, *args, **kwargs): - return self.r.writeln(*args, **kwargs) - - def printSummary(self, *args, **kwargs): - print "PRINT SUMMARY" - return self.r.printSummary(*args, **kwargs) - - def wasSuccessful(self, *args, **kwargs): - return self.r.wasSuccessful(*args, **kwargs) - diff --git a/allmydata/upload.py b/allmydata/upload.py deleted file mode 100644 index 5b8588ab..00000000 --- a/allmydata/upload.py +++ /dev/null @@ -1,209 +0,0 @@ - -from zope.interface import Interface, implements -from twisted.python import failure, log -from twisted.internet import defer -from twisted.application import service -from foolscap import Referenceable - -from allmydata.util import idlib -from allmydata import encode - -from cStringIO import StringIO -import sha - -class NotEnoughPeersError(Exception): - pass - -class HaveAllPeersError(Exception): - # we use this to jump out of the loop - pass - -# this wants to live in storage, not here -class TooFullError(Exception): - pass - -class FileUploader: - debug = False - - def __init__(self, peer): - self._peer = peer - - def set_filehandle(self, filehandle): - self._filehandle = filehandle - filehandle.seek(0, 2) - self._size = filehandle.tell() - filehandle.seek(0) - - def make_encoder(self): - self._needed_shares = 4 - self._shares = 4 - self._encoder = encode.Encoder(self._filehandle, self._shares) - self._share_size = self._size - - def set_verifierid(self, vid): - assert isinstance(vid, str) - self._verifierid = vid - - - def start(self): - log.msg("starting upload") - if self.debug: - print "starting upload" - # first step: who should we upload to? - - # maybe limit max_peers to 2*len(self.shares), to reduce memory - # footprint - max_peers = None - - self.permuted = self._peer.permute_peerids(self._verifierid, max_peers) - self._total_peers = len(self.permuted) - for p in self.permuted: - assert isinstance(p, str) - # we will shrink self.permuted as we give up on peers - self.peer_index = 0 - self.goodness_points = 0 - self.target_goodness = self._shares - self.landlords = [] # list of (peerid, bucket_num, remotebucket) - - d = defer.maybeDeferred(self._check_next_peer) - d.addCallback(self._got_all_peers) - return d - - def _check_next_peer(self): - if len(self.permuted) == 0: - # there are no more to check - raise NotEnoughPeersError("%s goodness, want %s, have %d " - "landlords, %d total peers" % - (self.goodness_points, - self.target_goodness, - len(self.landlords), - self._total_peers)) - if self.peer_index >= len(self.permuted): - self.peer_index = 0 - - peerid = self.permuted[self.peer_index] - - d = self._peer.get_remote_service(peerid, "storageserver") - def _got_peer(service): - bucket_num = len(self.landlords) - if self.debug: print "asking %s" % idlib.b2a(peerid) - d2 = service.callRemote("allocate_bucket", - verifierid=self._verifierid, - bucket_num=bucket_num, - size=self._share_size, - leaser=self._peer.nodeid, - canary=Referenceable()) - def _allocate_response(bucket): - if self.debug: - print " peerid %s will grant us a lease" % idlib.b2a(peerid) - self.landlords.append( (peerid, bucket_num, bucket) ) - self.goodness_points += 1 - if self.goodness_points >= self.target_goodness: - if self.debug: print " we're done!" - raise HaveAllPeersError() - # otherwise we fall through to allocate more peers - d2.addCallback(_allocate_response) - return d2 - d.addCallback(_got_peer) - def _done_with_peer(res): - if self.debug: print "done with peer %s:" % idlib.b2a(peerid) - if isinstance(res, failure.Failure): - if res.check(HaveAllPeersError): - if self.debug: print " all done" - # we're done! - return - if res.check(TooFullError): - if self.debug: print " too full" - elif res.check(IndexError): - if self.debug: print " no connection" - else: - if self.debug: print " other error:", res - self.permuted.remove(peerid) # this peer was unusable - else: - if self.debug: print " they gave us a lease" - # we get here for either good peers (when we still need - # more), or after checking a bad peer (and thus still need - # more). So now we need to grab a new peer. - self.peer_index += 1 - return self._check_next_peer() - d.addBoth(_done_with_peer) - return d - - def _got_all_peers(self, res): - d = self._encoder.do_upload(self.landlords) - d.addCallback(lambda res: self._verifierid) - return d - -def netstring(s): - return "%d:%s," % (len(s), s) - -class IUploadable(Interface): - def get_filehandle(): - pass - def close_filehandle(f): - pass - -class FileName: - implements(IUploadable) - def __init__(self, filename): - self._filename = filename - def get_filehandle(self): - return open(self._filename, "rb") - def close_filehandle(self, f): - f.close() - -class Data: - implements(IUploadable) - def __init__(self, data): - self._data = data - def get_filehandle(self): - return StringIO(self._data) - def close_filehandle(self, f): - pass - -class FileHandle: - implements(IUploadable) - def __init__(self, filehandle): - self._filehandle = filehandle - def get_filehandle(self): - return self._filehandle - def close_filehandle(self, f): - # the originator of the filehandle reserves the right to close it - pass - -class Uploader(service.MultiService): - """I am a service that allows file uploading. - """ - name = "uploader" - - def _compute_verifierid(self, f): - hasher = sha.new(netstring("allmydata_v1_verifierid")) - f.seek(0) - hasher.update(f.read()) - f.seek(0) - # note: this is only of the plaintext data, no encryption yet - return hasher.digest() - - def upload(self, f): - assert self.parent - assert self.running - f = IUploadable(f) - fh = f.get_filehandle() - u = FileUploader(self.parent) - u.set_filehandle(fh) - u.set_verifierid(self._compute_verifierid(fh)) - u.make_encoder() - d = u.start() - def _done(res): - f.close_filehandle(fh) - return res - d.addBoth(_done) - return d - - # utility functions - def upload_data(self, data): - return self.upload(Data(data)) - def upload_filename(self, filename): - return self.upload(FileName(filename)) - def upload_filehandle(self, filehandle): - return self.upload(FileHandle(filehandle)) diff --git a/allmydata/util/__init__.py b/allmydata/util/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/allmydata/util/assertutil.py b/allmydata/util/assertutil.py deleted file mode 100644 index 2adae8d6..00000000 --- a/allmydata/util/assertutil.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (c) 2003-2006 Bryce "Zooko" Wilcox-O'Hearn -# mailto:zooko@zooko.com -# http://zooko.com/ -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this work to deal in this work without restriction (including the -# rights to use, modify, distribute, sublicense, and/or sell copies) - -""" -Tests useful in assertion checking, prints out nicely formated messages too. -""" - -from humanreadable import hr - -from twisted.python import log - -def _assert(___cond=False, *___args, **___kwargs): - if ___cond: - return True - msgbuf=[] - if ___args: - msgbuf.append("%s %s" % tuple(map(hr, (___args[0], type(___args[0]),)))) - msgbuf.extend([", %s %s" % tuple(map(hr, (arg, type(arg),))) for arg in ___args[1:]]) - if ___kwargs: - msgbuf.append(", %s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) - else: - if ___kwargs: - msgbuf.append("%s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) - msgbuf.extend([", %s: %s %s" % tuple(map(hr, (k, v, type(v),))) for k, v in ___kwargs.items()[1:]]) - - raise AssertionError, "".join(msgbuf) - - return False - -def precondition(___cond=False, *___args, **___kwargs): - try: - if ___cond: - return True - msgbuf=["precondition", ] - if ___args or ___kwargs: - msgbuf.append(": ") - if ___args: - msgbuf.append("%s %s" % tuple(map(hr, (___args[0], type(___args[0]),)))) - msgbuf.extend([", %s %s" % tuple(map(hr, (arg, type(arg),))) for arg in ___args[1:]]) - if ___kwargs: - msgbuf.append(", %s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) - else: - if ___kwargs: - msgbuf.append("%s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) - msgbuf.extend([", %s: %s %s" % tuple(map(hr, (k, v, type(v),))) for k, v in ___kwargs.items()[1:]]) - except Exception, le: - log.msg("assertutil.precondition(): INTERNAL ERROR IN pyutil.assertutil. %s %s %s" % (type(le), repr(le), le.args,)) - log.err() - raise le - except: - log.msg("assertutil.precondition(): INTERNAL ERROR IN pyutil.assertutil.") - log.err() - raise - - raise AssertionError, "".join(msgbuf) - - return False - -def postcondition(___cond=False, *___args, **___kwargs): - if ___cond: - return True - msgbuf=["postcondition", ] - if ___args or ___kwargs: - msgbuf.append(": ") - if ___args: - msgbuf.append("%s %s" % tuple(map(hr, (___args[0], type(___args[0]),)))) - msgbuf.extend([", %s %s" % tuple(map(hr, (arg, type(arg),))) for arg in ___args[1:]]) - if ___kwargs: - msgbuf.append(", %s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) - else: - if ___kwargs: - msgbuf.append("%s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) - msgbuf.extend([", %s: %s %s" % tuple(map(hr, (k, v, type(v),))) for k, v in ___kwargs.items()[1:]]) - - raise AssertionError, "".join(msgbuf) - - return False - diff --git a/allmydata/util/bencode.py b/allmydata/util/bencode.py deleted file mode 100644 index d507a6ce..00000000 --- a/allmydata/util/bencode.py +++ /dev/null @@ -1,433 +0,0 @@ -#!/usr/bin/env python -# -*- coding: MacRoman -*- -""" -A library for streaming and unstreaming of simple objects, designed -for speed, compactness, and ease of implementation. - -The basic functions are bencode and bdecode. bencode takes an object -and returns a string, bdecode takes a string and returns an object. -bdecode raises a ValueError if you give it an invalid string. - -The objects passed in may be nested dicts, lists, ints, floats, strings, -and Python boolean and None types. For example, all of the following -may be bencoded - - -{'a': [0, 1], 'b': None} - -[None, ['a', 2, ['c', None]]] - -{'spam': (2,3,4)} - -{'name': 'Cronus', 'spouse': 'Rhea', 'children': ['Hades', 'Poseidon']} - -In general bdecode(bencode(spam)) == spam, but tuples and lists are -encoded the same, so bdecode(bencode((0, 1))) is [0, 1] rather -than (0, 1). Longs and ints are also encoded the same way, so -bdecode(bencode(4)) is a long. - -Dict keys are required to be basestrings (byte strings or unicode objects), -to avoid a mess of potential implementation incompatibilities. bencode is -intended to be used for protocols which are going to be re-implemented many -times, so it's very conservative in that regard. - -Which type is encoded is determined by the first character, 'i', 'n', 'f', -'d', 'l', 'b', 'u', and any digit. They indicate integer, null, float, -dict, list, boolean, unicode string, and string, respectively. - -Strings are length-prefixed in base 10, followed by a colon. - -bencode('spam') == '4:spam' - -Unicode string objects are indicated with an initial u, a base 10 -length-prefix, and the remaining bytes in utf-8 encoding. - -bencode(u'\u00bfHabla espa\u00f1ol?') == 'ËHabla espaÐol?' - -Nulls are indicated by a single 'n'. - -bencode(None) == 'n' - -Integers are encoded base 10 and terminated with an 'e' - - -bencode(3) == 'i3e' -bencode(-20) == 'i-20e' - -Floats are encoded in base 10 and terminated with an 'e' - - -bencode(3.2) == 'f3.2e' -bencode(-23.4532) == 'f-23.4532e' - -Lists are encoded in list order, terminated by an 'e' - - -bencode(['abc', 'd']) == 'l3:abc1:de' -bencode([2, 'f']) == 'li2e1:fe' - -Dicts are encoded by containing alternating keys and values. -The keys are encoded in sorted order, but sort order is not -enforced on the decode. Dicts are terminated by an 'e'. Dict -keys can be either bytestrings or unicode strings. For example - - -bencode({'spam': 'eggs'}) == 'd4:spam4:eggse' -bencode({'ab': 2, 'a': None}) == 'd1:an2:abi2ee' -bencode({'a' : 1, u'\xab': 2}) == 'd1:ai1eu4:\xfe\xff\x00\xa8i2ee' - -Truncated strings come first, so in sort order 'a' comes before 'abc'. -""" - -# This file is licensed under the GNU Lesser General Public License v2.1. -# -# Originally written by Mojo Nation. -# Rewritten by Bram Cohen. -# Further enhanced by Allmydata to support additional Python types (Boolean -# None, Float, and Unicode strings.) - -from types import IntType, LongType, FloatType, ListType, TupleType, DictType, StringType, UnicodeType, BooleanType, NoneType -from cStringIO import StringIO -import string - -def bencode(data): - """ - encodes objects as strings, see module documentation for more info - """ - result = StringIO() - bwrite(data, result) - return result.getvalue() - -def bwrite(data, result): - # a generic using pje's type dispatch will be faster here - try: - encoder = encoders[type(data)] - except KeyError: - encoder = None - # Catch subclasses of built-in types - for t,coder in encoders.items(): - if isinstance(data, t): - encoder = coder - break - if not encoder: - raise ValueError("unsupported data type: %s" % type(data)) - encoder(data, result) - -encoders = {} - -def encode_int(data, result): - result.write('i' + str(data) + 'e') - -encoders[IntType] = encode_int -encoders[LongType] = encode_int - -def encode_float(data, result): - result.write('f' + str(data) + 'e') - -encoders[FloatType] = encode_float - -def encode_bool(data, result): - if data: - result.write('b1') - else: - result.write('b0') - -encoders[BooleanType] = encode_bool - -def encode_list(data, result): - result.write('l') - _bwrite = bwrite - for item in data: - _bwrite(item, result) - result.write('e') - -encoders[TupleType] = encode_list -encoders[ListType] = encode_list -encoders[set] = encode_list - -def encode_string(data, result): - result.write(str(len(data)) + ':' + data) - -encoders[StringType] = encode_string - -def encode_unicode(data, result): - payload = data.encode('utf-8') - result.write('u' + str(len(payload)) + ':' + payload) - -encoders[UnicodeType] = encode_unicode - -def encode_dict(data, result): - result.write('d') - _bwrite = bwrite - keylist = data.keys() - keylist.sort() - for key in keylist: - _bwrite(key, result) - _bwrite(data[key], result) - result.write('e') - -encoders[DictType] = encode_dict - -encoders[NoneType] = lambda data, result: result.write('n') - -def bdecode(s): - """ - Does the opposite of bencode. Raises a ValueError if there's a problem. - """ - try: - result, index = bread(s, 0) - if index != len(s): - raise ValueError('left over stuff at end: %s' % s[index:]) - return result - except IndexError, e: - raise ValueError(str(e)) - except KeyError, e: - raise ValueError(str(e)) - -def bread(s, index): - return decoders[s[index]](s, index) - -decoders = {} - -def decode_raw_string(s, index): - ci = s.index(":", index) - ei = ci + int(s[index:ci]) + 1 - if ei > len(s): - raise ValueError('length encoding indicates premature end of string') - return (s[ci+1:ei], ei) - -for c in string.digits: - decoders[c] = decode_raw_string - -def decode_unicode_string(s, index): - ci = s.index(":", index) - ei = ci + int(s[index+1:ci]) + 1 - if ei > len(s): - raise ValueError('length encoding indicates premature end of string') - return (unicode(s[ci+1:ei], 'utf-8'), ei) - -decoders['u'] = decode_unicode_string - -def decode_int(s, index): - ei = s.index('e', index) - return (long(s[index+1:ei]), ei+1) - -decoders['i'] = decode_int - -def decode_float(s, index): - ei = s.index('e', index) - return (float(s[index+1:ei]), ei+1) - -decoders['f'] = decode_float - -def decode_bool(s, index): - val = s[index+1] - if val == '1': - return True, index+2 - elif val == '0': - return False, index+2 - else: - raise ValueError('invalid boolean encoding: %s' % s[index:index+2]) - -decoders['b'] = decode_bool - -# decoders['n'] = lambda s, index: decoders_n.inc('n') or (None, index + 1) -decoders['n'] = lambda s, index: (None, index + 1) - -def decode_list(s, index): - # decoders_n.inc('l') - result = [] - index += 1 - _bread = bread - while s[index] != 'e': - next, index = _bread(s, index) - result.append(next) - return result, index + 1 - -decoders['l'] = decode_list - -def decode_dict(s, index): - # decoders_n.inc('d') - result = {} - index += 1 - _decode_string = decode_raw_string - _decode_unicode = decode_unicode_string - _bread = bread - while s[index] != 'e': - if s[index] in string.digits: - key, index = _decode_string(s, index) - elif s[index] == "u": - key, index = _decode_unicode(s, index) - else: - raise ValueError("dict key must be basestring") - if key in result: - raise ValueError("dict key was repeated") - value, index = _bread(s, index) - result[key] = value - return result, index + 1 - -decoders['d'] = decode_dict - -def test_decode_raw_string(): - assert decode_raw_string('1:a', 0) == ('a', 3) - assert decode_raw_string('0:', 0) == ('', 2) - assert decode_raw_string('10:aaaaaaaaaaaaaaaaaaaaaaaaa', 0) == ('aaaaaaaaaa', 13) - assert decode_raw_string('10:', 1) == ('', 3) -# non-reexp version does not check for this case -# try: -# decode_raw_string('01:a', 0) -# assert 0, 'failed' -# except ValueError: -# pass - try: - decode_raw_string('--1:a', 0) - assert 0, 'failed' - except ValueError: - pass - try: - decode_raw_string('h', 0) - assert 0, 'failed' - except ValueError: - pass - try: - decode_raw_string('h:', 0) - assert 0, 'failed' - except ValueError: - pass - try: - decode_raw_string('1', 0) - assert 0, 'failed' - except ValueError: - pass - try: - decode_raw_string('', 0) - assert 0, 'failed' - except ValueError: - pass - try: - decode_raw_string('5:a', 0) - assert 0, 'failed' - except ValueError: - pass - -def test_encode_and_decode_unicode_results_in_unicode_type(): - assert bdecode(bencode(u'\u00bfHabla espa\u00f1ol?')) == u'\u00bfHabla espa\u00f1ol?' - -def test_encode_and_decode_unicode_at_least_preserves_the_content_even_if_it_flattens_the_type(): - test_string = bdecode(bencode(u'\u00bfHabla espa\u00f1ol?')) - if isinstance(test_string, unicode): - assert test_string == u'\u00bfHabla espa\u00f1ol?' - elif isinstance(test_string, str): - assert test_string.decode('utf-8') == u'\u00bfHabla espa\u00f1ol?' - else: - assert 0, 'flunked' - -def test_dict_forbids_non_string_key(): - try: - bdecode('di3ene') - assert 0, 'failed' - except ValueError: - pass - -def test_dict_forbids_key_repeat(): - try: - bdecode('d1:an1:ane') - assert 0, 'failed' - except ValueError: - pass - -def test_empty_dict(): - assert bdecode('de') == {} - -def test_dict_allows_unicode_keys(): - assert bdecode(bencode({'a': 1, u'\xa8': 2})) == {'a': 1L, u'\xa8': 2L} - -def test_ValueError_in_decode_unknown(): - try: - bdecode('x') - assert 0, 'flunked' - except ValueError: - pass - -def test_encode_and_decode_none(): - assert bdecode(bencode(None)) == None - -def test_encode_and_decode_long(): - assert bdecode(bencode(-23452422452342L)) == -23452422452342L - -def test_encode_and_decode_int(): - assert bdecode(bencode(2)) == 2 - -def test_encode_and_decode_float(): - assert bdecode(bencode(3.4)) == 3.4 - assert bdecode(bencode(0.0)) == 0.0 - assert bdecode(bencode(-4.56)) == -4.56 - assert bdecode(bencode(-0.0)) == -0.0 - -def test_encode_and_decode_bool(): - assert bdecode(bencode(True)) == True - assert bdecode(bencode(False)) == False - -# the non-regexp methods no longer check for canonical ints, but we -# don't parse input we did not generate using bencode, so I will leave -# these commented out for now -#def test_decode_noncanonical_int(): -# try: -# bdecode('i03e') -# assert 0 -# except ValueError: -# pass -# try: -# bdecode('i3 e') -# assert 0 -# except ValueError: -# pass -# try: -# bdecode('i 3e') -# assert 0 -# except ValueError: -# pass -# try: -# bdecode('i-0e') -# assert 0 -# except ValueError: -# pass - -def test_encode_and_decode_dict(): - x = {'42': 3} - assert bdecode(bencode(x)) == x - -def test_encode_and_decode_list(): - assert bdecode(bencode([])) == [] - -def test_encode_and_decode_tuple(): - assert bdecode(bencode(())) == [] - -def test_encode_and_decode_empty_dict(): - assert bdecode(bencode({})) == {} - -def test_encode_and_decode_complex_object(): - spam = [[], 0, -3, -345234523543245234523L, {}, 'spam', None, {'a': [3]}, {}, {'a': 1L, u'\xa8': 2L}] - assert bencode(bdecode(bencode(spam))) == bencode(spam) - assert bdecode(bencode(spam)) == spam - -def test_unfinished_list(): - try: - bdecode('ln') - assert 0 - except ValueError: - pass - -def test_unfinished_dict(): - try: - bdecode('d') - assert 0 - except ValueError: - pass - try: - bdecode('d1:a') - assert 0 - except ValueError: - pass - -def test_unsupported_type(): - try: - bencode(lambda: None) - assert 0 - except ValueError: - pass \ No newline at end of file diff --git a/allmydata/util/humanreadable.py b/allmydata/util/humanreadable.py deleted file mode 100644 index bae826c5..00000000 --- a/allmydata/util/humanreadable.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (c) 2001 Autonomous Zone Industries -# Copyright (c) 2002-2005 Bryce "Zooko" Wilcox-O'Hearn -# This file is licensed under the -# GNU Lesser General Public License v2.1. -# See the file COPYING or visit http://www.gnu.org/ for details. - -import exceptions, os -from repr import Repr - -class BetterRepr(Repr): - def __init__(self): - Repr.__init__(self) - - # Note: These levels can get adjusted dynamically! My goal is to get - # more info when printing important debug stuff like exceptions and - # stack traces and less info when logging normal events. - # --Zooko 2000-10-14 - if 0: # DEBUG MODE - self.maxlevel = 24 - self.maxdict = 24 - self.maxlist = 24 - self.maxtuple = 24 - self.maxstring = 800 - self.maxother = 800 - else: - self.maxlevel = 6 - self.maxdict = 6 - self.maxlist = 6 - self.maxtuple = 6 - self.maxstring = 300 - self.maxother = 300 - - def repr_function(self, obj, level): - if hasattr(obj, 'func_code'): - return '<' + obj.func_name + '() at ' + os.path.basename(obj.func_code.co_filename) + ':' + str(obj.func_code.co_firstlineno) + '>' - else: - return '<' + obj.func_name + '() at (builtin)' - - def repr_instance_method(self, obj, level): - if hasattr(obj, 'func_code'): - return '<' + obj.im_class.__name__ + '.' + obj.im_func.__name__ + '() at ' + os.path.basename(obj.im_func.func_code.co_filename) + ':' + str(obj.im_func.func_code.co_firstlineno) + '>' - else: - return '<' + obj.im_class.__name__ + '.' + obj.im_func.__name__ + '() at (builtin)' - - def repr_long(self, obj, level): - s = `obj` # XXX Hope this isn't too slow... - if len(s) > self.maxlong: - i = max(0, (self.maxlong-3)/2) - j = max(0, self.maxlong-3-i) - s = s[:i] + '...' + s[len(s)-j:] - if s[-1] == 'L': - return s[:-1] - return s - - def repr_instance(self, obj, level): - """ - If it is an instance of Exception, format it nicely (trying to emulate - the format that you see when an exception is actually raised, plus - bracketing '<''s). If it is an instance of dict call self.repr_dict() - on it. If it is an instance of list call self.repr_list() on it. Else - call Repr.repr_instance(). - """ - if isinstance(obj, exceptions.Exception): - # Don't cut down exception strings so much. - tms = self.maxstring - self.maxstring = max(512, tms * 4) - tml = self.maxlist - self.maxlist = max(12, tml * 4) - try: - if hasattr(obj, 'args'): - if len(obj.args) == 1: - return '<' + obj.__class__.__name__ + ': ' + self.repr1(obj.args[0], level-1) + '>' - else: - return '<' + obj.__class__.__name__ + ': ' + self.repr1(obj.args, level-1) + '>' - else: - return '<' + obj.__class__.__name__ + '>' - finally: - self.maxstring = tms - self.maxlist = tml - - if isinstance(obj, dict): - return self.repr_dict(obj, level) - - if isinstance(obj, list): - return self.repr_list(obj, level) - - return Repr.repr_instance(self, obj, level) - - def repr_list(self, obj, level): - """ - copied from standard repr.py and fixed to work on multithreadedly mutating lists. - """ - if level <= 0: return '[...]' - n = len(obj) - myl = obj[:min(n, self.maxlist)] - s = '' - for item in myl: - entry = self.repr1(item, level-1) - if s: s = s + ', ' - s = s + entry - if n > self.maxlist: s = s + ', ...' - return '[' + s + ']' - - def repr_dict(self, obj, level): - """ - copied from standard repr.py and fixed to work on multithreadedly mutating dicts. - """ - if level <= 0: return '{...}' - s = '' - n = len(obj) - items = obj.items()[:min(n, self.maxdict)] - items.sort() - for key, val in items: - entry = self.repr1(key, level-1) + ':' + self.repr1(val, level-1) - if s: s = s + ', ' - s = s + entry - if n > self.maxdict: s = s + ', ...' - return '{' + s + '}' - -# This object can be changed by other code updating this module's "brepr" -# variables. This is so that (a) code can use humanreadable with -# "from humanreadable import hr; hr(mything)", and (b) code can override -# humanreadable to provide application-specific human readable output -# (e.g. libbase32's base32id.AbbrevRepr). -brepr = BetterRepr() - -def hr(x): - return brepr.repr(x) diff --git a/allmydata/util/idlib.py b/allmydata/util/idlib.py deleted file mode 100644 index b447a08d..00000000 --- a/allmydata/util/idlib.py +++ /dev/null @@ -1,7 +0,0 @@ -from base64 import b32encode, b32decode - -def b2a(i): - return b32encode(i).lower() - -def a2b(i): - return b32decode(i.upper()) diff --git a/allmydata/util/iputil.py b/allmydata/util/iputil.py deleted file mode 100644 index 9b87b1c0..00000000 --- a/allmydata/util/iputil.py +++ /dev/null @@ -1,21 +0,0 @@ - -# adapted from nattraverso.ipdiscover - -import socket -from twisted.internet import reactor -from twisted.internet.protocol import DatagramProtocol - -def get_local_ip_for(target='A.ROOT-SERVERS.NET'): - """Find out what our IP address is for use by a given target. - - Returns a string that holds the IP address which could be used by - 'target' to connect to us. It might work for them, it might not. - """ - target_ipaddr = socket.gethostbyname(target) - udpprot = DatagramProtocol() - port = reactor.listenUDP(0, udpprot) - udpprot.transport.connect(target_ipaddr, 7) - localip = udpprot.transport.getHost().host - port.stopListening() # note, this returns a Deferred - return localip - diff --git a/allmydata/vdrive.py b/allmydata/vdrive.py deleted file mode 100644 index 22e012d0..00000000 --- a/allmydata/vdrive.py +++ /dev/null @@ -1,176 +0,0 @@ - -"""This is the client-side facility to manipulate virtual drives.""" - -from twisted.application import service -from twisted.internet import defer -from twisted.python import log -from allmydata import upload, download - -class VDrive(service.MultiService): - name = "vdrive" - - def set_root(self, root): - self.gvd_root = root - - def dirpath(self, dir_or_path): - if isinstance(dir_or_path, str): - return self.get_dir(dir_or_path) - return defer.succeed(dir_or_path) - - def get_dir(self, path): - """Return a Deferred that fires with a RemoteReference to a - MutableDirectoryNode at the given /-delimited path.""" - d = defer.succeed(self.gvd_root) - if path.startswith("/"): - path = path[1:] - if path == "": - return d - for piece in path.split("/"): - d.addCallback(lambda parent: parent.callRemote("list")) - def _find(table, subdir): - for name,target in table: - if name == subdir: - return target - else: - raise KeyError("no such directory '%s' in '%s'" % - (subdir, [t[0] for t in table])) - d.addCallback(_find, piece) - def _check(subdir): - assert not isinstance(subdir, str), "Hey, %s shouldn't be a string" % subdir - return subdir - d.addCallback(_check) - return d - - def get_verifierid_from_parent(self, parent, filename): - assert not isinstance(parent, str), "'%s' isn't a directory node" % (parent,) - d = parent.callRemote("list") - def _find(table): - for name,target in table: - if name == filename: - assert isinstance(target, str), "Hey, %s isn't a file" % filename - return target - else: - raise KeyError("no such file '%s' in '%s'" % - (filename, [t[0] for t in table])) - d.addCallback(_find) - return d - - def get_root(self): - return self.gvd_root - - def listdir(self, dir_or_path): - d = self.dirpath(dir_or_path) - d.addCallback(lambda parent: parent.callRemote("list")) - def _list(table): - return [t[0] for t in table] - d.addCallback(_list) - return d - - def put_file(self, dir_or_path, name, uploadable): - """Upload an IUploadable and add it to the virtual drive (as an entry - called 'name', in 'dir_or_path') 'dir_or_path' must either be a - string like 'root/subdir1/subdir2', or a directory node (either the - root directory node returned by get_root(), or a subdirectory - returned by list() ). - - The uploadable can be an instance of allmydata.upload.Data, - FileHandle, or FileName. - - I return a deferred that will fire when the operation is complete. - """ - - log.msg("putting file to '%s'" % name) - ul = self.parent.getServiceNamed("uploader") - d = self.dirpath(dir_or_path) - def _got_dir(dirnode): - d1 = ul.upload(uploadable) - d1.addCallback(lambda vid: - dirnode.callRemote("add_file", name, vid)) - return d1 - d.addCallback(_got_dir) - def _done(res): - log.msg("finished putting file to '%s'" % name) - return res - d.addCallback(_done) - return d - - def put_file_by_filename(self, dir_or_path, name, filename): - return self.put_file(dir_or_path, name, upload.FileName(filename)) - def put_file_by_data(self, dir_or_path, name, data): - return self.put_file(dir_or_path, name, upload.Data(data)) - def put_file_by_filehandle(self, dir_or_path, name, filehandle): - return self.put_file(dir_or_path, name, upload.FileHandle(filehandle)) - - def make_directory(self, dir_or_path, name): - d = self.dirpath(dir_or_path) - d.addCallback(lambda parent: parent.callRemote("add_directory", name)) - return d - - def remove(self, parent, name): - assert not isinstance(parent, str) - log.msg("vdrive removing %s" % name) - # first find the verifierid - d = self.get_verifierid_from_parent(parent, name) - def _got_verifierid(vid): - # TODO: delete the file's shares using this - pass - d.addCallback(_got_verifierid) - def _delete_from_parent(res): - return parent.callRemote("remove", name) - d.addCallback(_delete_from_parent) - def _done(res): - log.msg("vdrive done removing %s" % name) - d.addCallback(_done) - return d - - - def get_file(self, dir_and_name_or_path, download_target): - """Retrieve a file from the virtual drive and put it somewhere. - - The file to be retrieved may either be specified as a (dir, name) - tuple or as a full /-delimited pathname. In the former case, 'dir' - can be either a DirectoryNode or a pathname. - - The download target must be an IDownloadTarget instance like - allmydata.download.Data, .FileName, or .FileHandle . - """ - - log.msg("getting file from %s" % (dir_and_name_or_path,)) - dl = self.parent.getServiceNamed("downloader") - - if isinstance(dir_and_name_or_path, tuple): - dir_or_path, name = dir_and_name_or_path - d = self.dirpath(dir_or_path) - def _got_dir(dirnode): - return self.get_verifierid_from_parent(dirnode, name) - d.addCallback(_got_dir) - else: - rslash = dir_and_name_or_path.rfind("/") - if rslash == -1: - # we're looking for a file in the root directory - dir = self.gvd_root - name = dir_and_name_or_path - d = self.get_verifierid_from_parent(dir, name) - else: - dirpath = dir_and_name_or_path[:rslash] - name = dir_and_name_or_path[rslash+1:] - d = self.dirpath(dirpath) - d.addCallback(lambda dir: - self.get_verifierid_from_parent(dir, name)) - - def _got_verifierid(verifierid): - return dl.download(verifierid, download_target) - d.addCallback(_got_verifierid) - def _done(res): - log.msg("finished getting file") - return res - d.addCallback(_done) - return d - - def get_file_to_filename(self, from_where, filename): - return self.get_file(from_where, download.FileName(filename)) - def get_file_to_data(self, from_where): - return self.get_file(from_where, download.Data()) - def get_file_to_filehandle(self, from_where, filehandle): - return self.get_file(from_where, download.FileHandle(filehandle)) - diff --git a/allmydata/web/directory.xhtml b/allmydata/web/directory.xhtml deleted file mode 100644 index 38a09c9c..00000000 --- a/allmydata/web/directory.xhtml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - -
FilenameTypefileid
directory is empty!
- -
- - - - - diff --git a/allmydata/web/welcome.xhtml b/allmydata/web/welcome.xhtml deleted file mode 100644 index 7adb96ae..00000000 --- a/allmydata/web/welcome.xhtml +++ /dev/null @@ -1,39 +0,0 @@ - - - Welcome To AllMyData (tahoe2) - - - - - - -

Welcome To AllMyData! (tahoe2)

- -

To view the global shared filestore, Click Here!

- -

Mesh Status

- -
Queen:
-
Connected to queen?:
-
Known Peers:
-
Connected Peers:
- -
- - - - - - - - - - -
PeerIDConnected?
no peers!
-
- -
- - - diff --git a/allmydata/webish.py b/allmydata/webish.py deleted file mode 100644 index 4de899db..00000000 --- a/allmydata/webish.py +++ /dev/null @@ -1,331 +0,0 @@ - -from twisted.application import service, strports -from twisted.web import static, resource, server, html -from twisted.python import util, log -from nevow import inevow, rend, loaders, appserver, url, tags as T -from allmydata.util import idlib -from allmydata.download import IDownloadTarget#, IDownloader -from allmydata import upload -from zope.interface import implements, Interface -import urllib -from formless import annotate, webform - -def getxmlfile(name): - return loaders.xmlfile(util.sibpath(__file__, "web/%s" % name)) - -class IClient(Interface): - pass - -def get_downloader_service(ctx): - return IClient(ctx).getServiceNamed("downloader") -def get_uploader_service(ctx): - return IClient(ctx).getServiceNamed("uploader") -def get_vdrive_service(ctx): - return IClient(ctx).getServiceNamed("vdrive") - -class Welcome(rend.Page): - addSlash = True - docFactory = getxmlfile("welcome.xhtml") - - def data_queen_pburl(self, ctx, data): - return IClient(ctx).queen_pburl - def data_connected_to_queen(self, ctx, data): - if IClient(ctx).queen: - return "yes" - return "no" - def data_num_peers(self, ctx, data): - #client = inevow.ISite(ctx)._client - client = IClient(ctx) - return len(client.all_peers) - def data_num_connected_peers(self, ctx, data): - return len(IClient(ctx).connections) - def data_peers(self, ctx, data): - return sorted(IClient(ctx).all_peers) - def render_row(self, ctx, data): - if data in IClient(ctx).connections: - connected = "yes" - else: - connected = "no" - ctx.fillSlots("peerid", idlib.b2a(data)) - ctx.fillSlots("connected", connected) - return ctx.tag - - # this is a form where users can download files by URI - - def bind_download(self, ctx): - uriarg = annotate.Argument("uri", - annotate.String("URI of file to download: ")) - namearg = annotate.Argument("filename", - annotate.String("Filename to download as: ")) - ctxarg = annotate.Argument("ctx", annotate.Context()) - meth = annotate.Method(arguments=[uriarg, namearg, ctxarg], - label="Download File by URI") - # buttons always use value=data.label - # MethodBindingRenderer uses value=(data.action or data.label) - return annotate.MethodBinding("download", meth, action="Download") - - def download(self, uri, filename, ctx): - log.msg("webish downloading URI") - target = url.here.sibling("download_uri").add("uri", uri) - if filename: - target = target.add("filename", filename) - return target - - def render_forms(self, ctx, data): - return webform.renderForms() - - -class Directory(rend.Page): - addSlash = True - docFactory = getxmlfile("directory.xhtml") - - def __init__(self, dirnode, dirname): - self._dirnode = dirnode - self._dirname = dirname - - def childFactory(self, ctx, name): - if name.startswith("freeform"): # ick - return None - if self._dirname == "/": - dirname = "/" + name - else: - dirname = self._dirname + "/" + name - d = self._dirnode.callRemote("get", name) - def _got_child(res): - if isinstance(res, str): - dl = get_downloader_service(ctx) - return Downloader(dl, name, res) - return Directory(res, dirname) - d.addCallback(_got_child) - return d - - def render_title(self, ctx, data): - return ctx.tag["Directory of '%s':" % self._dirname] - - def render_header(self, ctx, data): - return "Directory of '%s':" % self._dirname - - def data_children(self, ctx, data): - d = self._dirnode.callRemote("list") - return d - - def render_row(self, ctx, data): - name, target = data - if isinstance(target, str): - # file - dlurl = urllib.quote(name) - ctx.fillSlots("filename", - T.a(href=dlurl)[html.escape(name)]) - ctx.fillSlots("type", "FILE") - uri = idlib.b2a(target) - dl_uri_url = url.root.child("download_uri").child(uri) - # add a filename= query argument to give it a Content-Type - dl_uri_url = dl_uri_url.add("filename", name) - ctx.fillSlots("fileid", T.a(href=dl_uri_url)[html.escape(uri)]) - - # this creates a button which will cause our child__delete method - # to be invoked, which deletes the file and then redirects the - # browser back to this directory - del_url = url.here.child("_delete") - #del_url = del_url.add("verifierid", idlib.b2a(target)) - del_url = del_url.add("name", name) - delete = T.form(action=del_url, method="post")[ - T.input(type='submit', value='del', name="del"), - ] - ctx.fillSlots("delete", delete) - else: - # directory - subdir_url = urllib.quote(name) - ctx.fillSlots("filename", - T.a(href=subdir_url)[html.escape(name)]) - ctx.fillSlots("type", "DIR") - ctx.fillSlots("fileid", "-") - ctx.fillSlots("delete", "-") - return ctx.tag - - def render_forms(self, ctx, data): - return webform.renderForms() - - def bind_upload(self, ctx): - """upload1""" - # Note: this comment is no longer accurate, as it reflects the older - # (apparently deprecated) formless.autocallable / - # annotate.TypedInterface approach. - - # Each method gets a box. The string in the autocallable(action=) - # argument is put on the border of the box, as well as in the submit - # button. The top-most contents of the box are the method's - # docstring, if any. Each row contains a string for the argument - # followed by the argument's input box. If you do not provide an - # action= argument to autocallable, the method name is capitalized - # and used instead. - up = annotate.FileUpload(label="Choose a file to upload: ", - required=True, - requiredFailMessage="Do iT!") - contentsarg = annotate.Argument("contents", up) - - ctxarg = annotate.Argument("ctx", annotate.Context()) - meth = annotate.Method(arguments=[contentsarg, ctxarg], - label="Upload File to this directory") - return annotate.MethodBinding("upload", meth, action="Upload") - - def upload(self, contents, ctx): - # contents is a cgi.FieldStorage instance - log.msg("starting webish upload") - - uploader = get_uploader_service(ctx) - d = uploader.upload(upload.Data(contents.value)) - name = contents.filename - d.addCallback(lambda vid: - self._dirnode.callRemote("add_file", name, vid)) - def _done(res): - log.msg("webish upload complete") - return res - d.addCallback(_done) - return d - return url.here.add("results", - "upload of '%s' complete!" % contents.filename) - - def bind_mkdir(self, ctx): - """Make new directory 1""" - namearg = annotate.Argument("name", - annotate.String("New directory name: ")) - meth = annotate.Method(arguments=[namearg], label="Make New Subdirectory") - return annotate.MethodBinding("mkdir", meth, action="Create Directory") - - def mkdir(self, name): - """mkdir2""" - log.msg("making new webish directory") - d = self._dirnode.callRemote("add_directory", name) - def _done(res): - log.msg("webish mkdir complete") - return res - d.addCallback(_done) - return d - - def child__delete(self, ctx): - # perform the delete, then redirect back to the directory page - args = inevow.IRequest(ctx).args - vdrive = get_vdrive_service(ctx) - d = vdrive.remove(self._dirnode, args["name"][0]) - def _deleted(res): - return url.here.up() - d.addCallback(_deleted) - return d - -class WebDownloadTarget: - implements(IDownloadTarget) - def __init__(self, req): - self._req = req - def open(self): - pass - def write(self, data): - self._req.write(data) - def close(self): - self._req.finish() - def fail(self): - self._req.finish() - def register_canceller(self, cb): - pass - def finish(self): - pass - -class TypedFile(static.File): - # serve data from a named file, but using a Content-Type derived from a - # different filename - isLeaf = True - def __init__(self, path, requested_filename): - static.File.__init__(self, path) - gte = static.getTypeAndEncoding - self.type, self.encoding = gte(requested_filename, - self.contentTypes, - self.contentEncodings, - self.defaultType) - -class Downloader(resource.Resource): - def __init__(self, downloader, name, verifierid): - self._downloader = downloader - self._name = name - self._verifierid = verifierid - - def render(self, ctx): - req = inevow.IRequest(ctx) - gte = static.getTypeAndEncoding - type, encoding = gte(self._name, - static.File.contentTypes, - static.File.contentEncodings, - defaultType="text/plain") - req.setHeader("content-type", type) - if encoding: - req.setHeader('content-encoding', encoding) - - t = WebDownloadTarget(req) - #dl = IDownloader(ctx) - dl = self._downloader - dl.download(self._verifierid, t) - return server.NOT_DONE_YET - - - -class Root(rend.Page): - def locateChild(self, ctx, segments): - if segments[0] == "download_uri": - req = inevow.IRequest(ctx) - dl = get_downloader_service(ctx) - filename = "unknown_filename" - if "filename" in req.args: - filename = req.args["filename"][0] - if len(segments) > 1: - # http://host/download_uri/URIGOESHERE - uri_a = segments[1] - elif "uri" in req.args: - # http://host/download_uri?uri=URIGOESHERE - uri_a = req.args["uri"][0] - else: - return rend.NotFound - child = Downloader(dl, filename, idlib.a2b(uri_a)) - return child, () - return rend.Page.locateChild(self, ctx, segments) - - child_webform_css = webform.defaultCSS - - child_welcome = Welcome() - - -class WebishServer(service.MultiService): - name = "webish" - - def __init__(self, webport): - service.MultiService.__init__(self) - self.root = Root() - placeholder = static.Data("sorry, still initializing", "text/plain") - self.root.putChild("vdrive", placeholder) - self.root.putChild("", url.here.child("welcome"))#Welcome()) - - self.site = site = appserver.NevowSite(self.root) - s = strports.service(webport, site) - s.setServiceParent(self) - self.listener = s # stash it so the tests can query for the portnum - - def startService(self): - service.MultiService.startService(self) - # to make various services available to render_* methods, we stash a - # reference to the client on the NevowSite. This will be available by - # adapting the 'context' argument to a special marker interface named - # IClient. - self.site.remember(self.parent, IClient) - # I thought you could do the same with an existing interface, but - # apparently 'ISite' does not exist - #self.site._client = self.parent - - def set_root_dirnode(self, dirnode): - self.root.putChild("vdrive", Directory(dirnode, "/")) - # I tried doing it this way and for some reason it didn't seem to work - #print "REMEMBERING", self.site, dl, IDownloader - #self.site.remember(dl, IDownloader) - - -# TODO: figleaf gets confused when the last line of a file is a comment. I -# suspect an off-by-one error in the code that decides which lines are code -# and which are not. -pass diff --git a/setup.py b/setup.py index 765990cd..0eddb778 100644 --- a/setup.py +++ b/setup.py @@ -17,11 +17,11 @@ if sys.platform == 'win32': plat_ext = [ Extension("Crypto.Util.winrandom", libraries = HTONS_LIBS + ['advapi32'], - include_dirs=['Crypto/src/'], + include_dirs=['src/Crypto/src/'], extra_compile_args=['-O0 -g',], extra_link_args=['-g',], undef_macros=['NDEBUG',], - sources=["Crypto/src/winrand.c"], + sources=["src/Crypto/src/winrand.c"], **debug_build_kw) ] else: @@ -81,48 +81,48 @@ class PCTBuildExt (build_ext): self.extensions += [ # Hash functions Extension("allmydata.Crypto.Hash.MD4", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/MD4.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/MD4.c"], **debug_build_kw), Extension("allmydata.Crypto.Hash.SHA256", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/SHA256.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/SHA256.c"], **debug_build_kw), # Block encryption algorithms Extension("allmydata.Crypto.Cipher.AES", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/AES.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/AES.c"], **debug_build_kw), Extension("allmydata.Crypto.Cipher.ARC2", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/ARC2.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/ARC2.c"], **debug_build_kw), Extension("allmydata.Crypto.Cipher.Blowfish", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/Blowfish.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/Blowfish.c"], **debug_build_kw), Extension("allmydata.Crypto.Cipher.CAST", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/CAST.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/CAST.c"], **debug_build_kw), Extension("allmydata.Crypto.Cipher.DES", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/DES.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/DES.c"], **debug_build_kw), Extension("allmydata.Crypto.Cipher.DES3", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/DES3.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/DES3.c"], **debug_build_kw), # Stream ciphers Extension("allmydata.Crypto.Cipher.ARC4", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/ARC4.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/ARC4.c"], **debug_build_kw), Extension("allmydata.Crypto.Cipher.XOR", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/XOR.c"], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/XOR.c"], **debug_build_kw), ] @@ -140,9 +140,9 @@ class PCTBuildExt (build_ext): exts = [] if (self.compiler.find_library_file(lib_dirs, 'gmp')): exts.append(Extension("allmydata.Crypto.PublicKey._fastmath", - include_dirs=['Crypto/src/'], + include_dirs=['src/Crypto/src/'], libraries=['gmp'], - sources=["Crypto/src/_fastmath.c"])) + sources=["src/Crypto/src/_fastmath.c"])) self.extensions += exts @@ -183,13 +183,14 @@ setup( name="AllMyData", version="0.0.1", #packages=find_packages('.'), - packages=["allmydata", "allmydata/test", "allmydata/util", - "allmydata/scripts", + packages=["allmydata", "allmydata.test", "allmydata.util", + "allmydata.scripts", "allmydata.Crypto", "allmydata.Crypto.Hash", "allmydata.Crypto.Cipher", "allmydata.Crypto.Util", "allmydata.Crypto.Protocol", "allmydata.Crypto.PublicKey" ], - package_dir={ "allmydata.Crypto": "Crypto" }, + package_dir={ "allmydata": "src/allmydata", + "allmydata.Crypto": "src/Crypto" }, scripts = ["bin/allmydata"], package_data={ 'allmydata': ['web/*.xhtml'] }, @@ -197,8 +198,8 @@ setup( # One module is defined here, because build_ext won't be # called unless there's at least one extension module defined. ext_modules=[Extension("allmydata.Crypto.Hash.MD2", - include_dirs=['Crypto/src/'], - sources=["Crypto/src/MD2.c"])], + include_dirs=['src/Crypto/src/'], + sources=["src/Crypto/src/MD2.c"])], description="AllMyData (tahoe2)", ) diff --git a/src/Crypto/ACKS b/src/Crypto/ACKS new file mode 100644 index 00000000..2acfc304 --- /dev/null +++ b/src/Crypto/ACKS @@ -0,0 +1,34 @@ +Acknowledgements +---------------- + +This list is sorted in alphabetical order, and is probably incomplete. +I'd like to thank everybody who contributed in any way, with code, bug +reports, and comments. + +--amk + +Tim Berners-Lee +Ian Bicking +Joris Bontje +Antoon Bosselaers +Andrea Bottoni +Andrew Eland +Philippe Frycia +Peter Gutmann +Hirendra Hindocha +Nikhil Jhingan +Piers Lauder +M.-A. Lemburg +Wim Lewis +Mark Moraes +Lim Chee Siang +Bryan Olson +Wallace Owen +Colin Plumb +James P. Rutledge +Matt Schreiner +Peter Simmons +Paul Swartz +Kevin M. Turner +Eric Young + diff --git a/src/Crypto/ChangeLog b/src/Crypto/ChangeLog new file mode 100644 index 00000000..30e325c1 --- /dev/null +++ b/src/Crypto/ChangeLog @@ -0,0 +1,316 @@ + +2.0.1 +===== + + * Fix SHA256 and RIPEMD on AMD64 platform. + * Deleted Demo/ directory. + * Add PublicKey to Crypto.__all__ + + +2.0 +=== + + * Added SHA256 module contributed by Jeethu Rao, with test data + from Taylor Boon. + + * Fixed AES.c compilation problems with Borland C. + (Contributed by Jeethu Rao.) + + * Fix ZeroDivisionErrors on Windows, caused by the system clock + not having enough resolution. + + * Fix 2.1/2.2-incompatible use of (key not in dict), + pointed out by Ian Bicking. + + * Fix FutureWarning in Crypto.Util.randpool, noted by James P Rutledge. + + +1.9alpha6 +========= + + * Util.number.getPrime() would inadvertently round off the bit + size; if you asked for a 129-bit prime or 135-bit prime, you + got a 128-bit prime. + + * Added Util/test/prime_speed.py to measure the speed of prime + generation, and PublicKey/test/rsa_speed.py to measure + the speed of RSA operations. + + * Merged the _rsa.c and _dsa.c files into a single accelerator + module, _fastmath.c. + + * Speed improvements: Added fast isPrime() function to _fastmath, + cutting the time to generate a 1024-bit prime by a factor of 10. + Optimized the C version of RSA decryption to use a longer series + of operations that's roughly 3x faster than a single + exponentiation. (Contributed by Joris Bontje.) + + * Added support to RSA key objects for blinding and unblinding + data. (Contributed by Joris Bontje.) + + * Simplified RSA key generation: hard-wired the encryption + exponent to 65537 instead of generating a random prime; + generate prime factors in a loop until the product + is large enough. + + * Renamed cansign(), canencrypt(), hasprivate(), to + can_sign, can_encrypt, has_private. If people shriek about + this change very loudly, I'll add aliases for the old method + names that log a warning and call the new method. + + +1.9alpha5 +========= + + * Many randpool changes. RandomPool now has a + randomize(N:int) method that can be called to get N + bytes of entropy for the pool (N defaults to 0, + which 'fills up' the pool's entropy) KeyboardRandom + overloads this method. + + * Added src/winrand.c for Crypto.Util.winrandom and + now use winrandom for _randomize if possible. + (Calls Windows CryptoAPI CryptGenRandom) + + * Several additional places for stirring the pool, + capturing inter-event entropy when reading/writing, + stirring before and after saves. + + * RandomPool.add_event now returns the number of + estimated bits of added entropy, rather than the + pool entropy itself (since the pool entropy is + capped at the number of bits in the pool) + + * Moved termios code from KeyboardRandomPool into a + KeyboardEntry class, provided a version for Windows + using msvcrt. + + * Fix randpool.py crash on machines with poor timer resolution. + (Reported by Mark Moraes and others.) + + * If the GNU GMP library is available, two C extensions will be + compiled to speed up RSA and DSA operations. (Contributed by + Paul Swartz.) + + * DES3 with a 24-byte key was broken; now fixed. + (Patch by Philippe Frycia.) + + +1.9alpha4 +========= + + * Fix compilation problem on Windows. + + * HMAC.py fixed to work with pre-2.2 Pythons + + * setup.py now dies if built with Python 1.x + + +1.9alpha3 +========= + + * Fix a ref-counting bug that caused core dumps. + (Reported by Piers Lauder and an anonymous SF poster.) + + +1.9alpha2 +========= + + * (Backwards incompatible) The old Crypto.Hash.HMAC module is + gone, replaced by a copy of hmac.py from Python 2.2's standard + library. It will display a warning on interpreter versions + older than 2.2. + + * (Backwards incompatible) Restored the Crypto.Protocol package, + and modernized and tidied up the two modules in it, + AllOrNothing.py and Chaffing.py, renaming various methods + and changing the interface. + + * (Backwards incompatible) Changed the function names in + Crypto.Util.RFC1751. + + * Restored the Crypto.PublicKey package at user request. I + think I'll leave it in the package and warn about it in the + documentation. I hope that eventually I can point to + someone else's better public-key code, and at that point I + may insert warnings and begin the process of deprecating + this code. + + * Fix use of a Python 2.2 C function, replacing it with a + 2.1-compatible equivalent. (Bug report and patch by Andrew + Eland.) + + * Fix endianness bugs that caused test case failures on Sparc, + PPC, and doubtless other platforms. + + * Fixed compilation problem on FreeBSD and MacOS X. + + * Expanded the test suite (requires Sancho, from + http://www.mems-exchange.org/software/sancho/) + + * Added lots of docstrings, so 'pydoc Crypto' now produces + helpful output. (Open question: maybe *all* of the documentation + should be moved into docstrings?) + + * Make test.py automatically add the build/* directory to sys.path. + + * Removed 'inline' declaration from C functions. Some compilers + don't support it, and Python's pyconfig.h no longer tells you whether + it's supported or not. After this change, some ciphers got slower, + but others got faster. + + * The C-level API has been changed to reduce the amount of + memory-to-memory copying. This makes the code neater, but + had ambiguous performance effects; again, some ciphers got slower + and others became faster. Probably this is due to my compiler + optimizing slightly worse or better as a result. + + * Moved C source implementations into src/ from block/, hash/, + and stream/. Having Hash/ and hash/ directories causes problems + on case-insensitive filesystems such as Mac OS. + + * Cleaned up the C code for the extensions. + + +1.9alpha1 +========= + + * Added Crypto.Cipher.AES. + + * Added the CTR mode and the variable-sized CFB mode from the + NIST standard on feedback modes. + + * Removed Diamond, HAVAL, MD5, Sapphire, SHA, and Skipjack. MD5 + and SHA are included with Python; the others are all of marginal + usefulness in the real world. + + * Renamed the module-level constants ECB, CFB, &c., to MODE_ECB, + MODE_CFB, as part of making the block encryption modules + compliant with PEP 272. (I'm not sure about this change; + if enough users complain about it, I might back it out.) + + * Made the hashing modules compliant with PEP 247 (not backward + compatible -- the major changes are that the constructor is now + MD2.new and not MD2.MD2, and the size of the digest is now + given as 'digest_size', not 'digestsize'. + + * The Crypto.PublicKey package is no longer installed; the + interfaces are all wrong, and I have no idea what the right + interfaces should be. + + +1.1alpha2 +========= + * Most importantly, the distribution has been broken into two +parts: exportable, and export-controlled. The exportable part +contains all the hashing algorithms, signature-only public key +algorithms, chaffing & winnowing, random number generation, various +utility modules, and the documentation. + + The export-controlled part contains public-key encryption +algorithms such as RSA and ElGamal, and bulk encryption algorithms +like DES, IDEA, or Skipjack. Getting this code still requires that +you go through an access control CGI script, and denies you access if +you're outside the US or Canada. + + * Added the RIPEMD hashing algorithm. (Contributed by +Hirendra Hindocha.) + + * Implemented the recently declassified Skipjack block +encryption algorithm. My implementation runs at 864 K/sec on a +PII/266, which isn't particularly fast, but you're probably better off +using another algorithm anyway. :) + + * A simple XOR cipher has been added, mostly for use by the +chaffing/winnowing code. (Contributed by Barry Warsaw.) + + * Added Protocol.Chaffing and Hash.HMAC.py. (Contributed by +Barry Warsaw.) + + Protocol.Chaffing implements chaffing and winnowing, recently +proposed by R. Rivest, which hides a message (the wheat) by adding +many noise messages to it (the chaff). The chaff can be discarded by +the receiver through a message authentication code. The neat thing +about this is that it allows secret communication without actually +having an encryption algorithm, and therefore this falls within the +exportable subset. + + * Tidied up randpool.py, and removed its use of a block +cipher; this makes it work with only the export-controlled subset +available. + + * Various renamings and reorganizations, mostly internal. + + +1.0.2 +===== + + * Changed files to work with Python 1.5; everything has been +re-arranged into a hierarchical package. (Not backward compatible.) +The package organization is: +Crypto. + Hash. + MD2, MD4, MD5, SHA, HAVAL + Cipher. + ARC2, ARC4, Blowfish, CAST, DES, DES3, Diamond, + IDEA, RC5, Sapphire + PublicKey. + DSA, ElGamal, qNEW, RSA + Util. + number, randpool, RFC1751 + + Since this is backward-incompatible anyway, I also changed +module names from all lower-case to mixed-case: diamond -> Diamond, +rc5 -> RC5, etc. That had been an annoying inconsistency for a while. + + * Added CAST5 module contributed by . + + * Added qNEW digital signature algorithm (from the digisign.py +I advertised a while back). (If anyone would like to suggest new +algorithms that should be implemented, please do; I think I've got +everything that's really useful at the moment, but...) + + * Support for keyword arguments has been added. This allowed +removing the obnoxious key handling for Diamond and RC5, where the +first few bytes of the key indicated the number of rounds to use, and +various other parameters. Now you need only do something like: + +from Crypto.Cipher import RC5 +obj = RC5.new(key, RC5.ECB, rounds=8) + +(Not backward compatible.) + + * Various function names have been changed, and parameter +names altered. None of these were part of the public interface, so it +shouldn't really matter much. + + * Various bugs fixed, the test suite has been expanded, and +the build process simplified. + + * Updated the documentation accordingly. + + +1.0.1 +===== + + * Changed files to work with Python 1.4 . + + * The DES and DES3 modules now automatically correct the +parity of their keys. + + * Added R. Rivest's DES test (see http://theory.lcs.mit.edu/~rivest/destest.txt) + + +1.0.0 +===== + + * REDOC III succumbed to differential cryptanalysis, and has +been removed. + + * The crypt and rotor modules have been dropped; they're still +available in the standard Python distribution. + + * The Ultra-Fast crypt() module has been placed in a separate +distribution. + + * Various bugs fixed. diff --git a/src/Crypto/Cipher/__init__.py b/src/Crypto/Cipher/__init__.py new file mode 100644 index 00000000..9f8096ae --- /dev/null +++ b/src/Crypto/Cipher/__init__.py @@ -0,0 +1,33 @@ +"""Secret-key encryption algorithms. + +Secret-key encryption algorithms transform plaintext in some way that +is dependent on a key, producing ciphertext. This transformation can +easily be reversed, if (and, hopefully, only if) one knows the key. + +The encryption modules here all support the interface described in PEP +272, "API for Block Encryption Algorithms". + +If you don't know which algorithm to choose, use AES because it's +standard and has undergone a fair bit of examination. + +Crypto.Cipher.AES Advanced Encryption Standard +Crypto.Cipher.ARC2 Alleged RC2 +Crypto.Cipher.ARC4 Alleged RC4 +Crypto.Cipher.Blowfish +Crypto.Cipher.CAST +Crypto.Cipher.DES The Data Encryption Standard. Very commonly used + in the past, but today its 56-bit keys are too small. +Crypto.Cipher.DES3 Triple DES. +Crypto.Cipher.IDEA +Crypto.Cipher.RC5 +Crypto.Cipher.XOR The simple XOR cipher. +""" + +__all__ = ['AES', 'ARC2', 'ARC4', + 'Blowfish', 'CAST', 'DES', 'DES3', + 'XOR' + ] + +__revision__ = "$Id: __init__.py,v 1.7 2003/02/28 15:28:35 akuchling Exp $" + + diff --git a/src/Crypto/Demo/README b/src/Crypto/Demo/README new file mode 100644 index 00000000..0e48d7c3 --- /dev/null +++ b/src/Crypto/Demo/README @@ -0,0 +1,29 @@ +This directory contains demonstration files that use the modules +included in the Python Cryptography Toolkit. + +Note: These programs have version numbers of their own, which are not +necessarily the same as the version number of the Toolkit package. + +cipher Encrypt and decrypt sensitive files; type 'cipher -h' + for a usage message. + +voice Allows secure voice communication over a TCP/IP link. + Currently this is Linux-specific; changes to make it + run on other systems would be greatly appreciated. + +RSAgen.py Generates a new RSA key. Demonstrates using + randpool.py, and maintains a file of random data in + "randseed". Requires that the IDEA and MD5 modules + are installed. + +testkey.py RSA public/private key pair used by example programs. + +Secure importing of Python modules: + + sign.py Sign all *.pyc files in a directory, using the + key defined in testkey.py. + + secimp.py Implementation of the secure 'import' command. + + + diff --git a/src/Crypto/Demo/chaum.py b/src/Crypto/Demo/chaum.py new file mode 100644 index 00000000..119a1ed9 --- /dev/null +++ b/src/Crypto/Demo/chaum.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +""" Example of Chaumian blinding """ + +import time, pprint, os, sha +from allmydata.Crypto.PublicKey import * +from allmydata.Crypto.Util.randpool import RandomPool +from allmydata.Crypto.Util import number +import cPickle as pickle + +# Globals +pool = RandomPool() +pool.stir() + +# use SHA-1 by default, if you want to use SHA-256, SHA-384 or SHA-512 you +# need shax-py from http://philosophysw.com/software/ +digest = sha.sha + +KEYSIZE = 1024 +KEYFILE = "tokenkey.pickle" +HASHSIZE = sha.digestsize*8 + +### Initialization ### + +if os.path.isfile(KEYFILE): + # Load existing key """ + print "Server: load key..." + ff = file(KEYFILE, 'r') + key = pickle.load(ff) + rsa = RSA.construct(key) +else: + # Generate an RSA key-pair of KEYSIZE bits and store the key + print "Server: create key (will take a while, but only has to be done once)..." + begintime=time.time() + rsa=RSA.generate(KEYSIZE, pool.get_bytes) + endtime=time.time() + print "Server: Generate %d bit RSA key: %f s" % (KEYSIZE, endtime-begintime) + + key = (rsa.n, rsa.e, rsa.d, rsa.p, rsa.q, rsa.u) + ff = file(KEYFILE, 'w') + pickle.dump(key, ff) + +print "RSA key:" +print "n = %s" % pprint.pformat(rsa.n) # Public key +print "e = %s" % pprint.pformat(rsa.e) # Public key + +print "d = %s" % pprint.pformat(rsa.d) # Private key +# Values below are not really needed, but cause a big speedup since the Chinese Remainders Theorem can be used +print "p = %s" % pprint.pformat(rsa.p) # Private key +print "q = %s" % pprint.pformat(rsa.q) # Private key +print "u = %s" % pprint.pformat(rsa.u) # Private key +print + +### Client ### + +# Generate random tokenId of HASHSIZE bits +tokenId = number.getRandomNumber(HASHSIZE, pool.get_bytes) + +# Generate random blindingFactor of KEYSIZE-1 (so it can still be signed) bits +while 1: + blindingFactor = number.getRandomNumber(KEYSIZE-1, pool.get_bytes) + # Verify that GCD(r, n) ==1 + if number.GCD(blindingFactor, rsa.n)==1: + break + +# Calculate the hash of the tokenId +tokenHash = number.bytes_to_long(digest(number.long_to_bytes(tokenId)).digest()) + +print "tokenId = %s" % pprint.pformat(tokenId) +print "blindingFactor = %s" % pprint.pformat(blindingFactor) +print "tokenHash = %s" % pprint.pformat(tokenHash) +print + +# Blind the hashed tokenId with blindingFactor +begintime=time.time() +blindedToken=rsa.blind(tokenHash, blindingFactor) +endtime=time.time() +print "Client: Blinding: %f s" % (endtime-begintime) +print "blindedToken = %s" % pprint.pformat(blindedToken) + +# Send blindedToken to the server +print "Client -> Server: blindedToken" +print + +### Server ### + +# Sign the blindedToken +begintime=time.time() +blindedSignature=rsa.sign(blindedToken, None)[0] +endtime=time.time() +print "Server: Signing: %f s" % (endtime-begintime) +print "blindedSignature = %s" % pprint.pformat(blindedSignature) + +# Send the blindedSignature back to the client +print "Server -> Client: blindedSignature" +print + +### Client ### + +# Unblind the blindedSignature +begintime=time.time() +signature=rsa.unblind(blindedSignature, blindingFactor) +endtime=time.time() +print "Client: Unblinding: %f s" % (endtime-begintime) +print "signature = %s" % pprint.pformat(signature) +print + +# Token is ready +token = (tokenId, signature) +print "Client: token = %s" % pprint.pformat(token) + +print +print "... user can now use the token..." +print "Client -> Server: token" +print + +### Server ### + +# Verify that the signature of hash(tokenId) is right +begintime=time.time() +v=rsa.verify(number.bytes_to_long(digest(number.long_to_bytes(token[0])).digest()), (token[1],)) +endtime=time.time() +print "Server: Verifying: %f s" % (endtime-begintime) + +if v: + print "Server: SIGNATURE OK" +else: + print "Server: SIGNATURE NOT OK" + diff --git a/src/Crypto/Demo/cipher b/src/Crypto/Demo/cipher new file mode 100644 index 00000000..8533c87e --- /dev/null +++ b/src/Crypto/Demo/cipher @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# -*-Python-*- +# Cipher 1.00 +# +# Part of the Python Cryptography Toolkit +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# + +import sys, getopt, os + +# Determine the name of this executable +executable = os.path.basename(sys.argv[0]) +if executable=='': executable='cipher' +cipher = '' # Unknown ciphering algorithm +key = (0, '') # Empty key +magic = 'ctx\001' # Magic string prefixed to the data +NoInputFile = '' # Exceptions raised on file errors +NoOutputFile = '' + +def PrintUsage(): + print 'Usage: cipher [OPTIONS] file1 file2 ...' + print '\n -c ciphername Force use of ciphername to encrypt/decrypt' + print ' -k key Key to use for encryption/decryption' + print '\nThe default cipher algorithm is IDEA; if no key is set on the command' + print 'line, you will be prompted to enter a key.' + print 'Files are read completely into memory, so do not try to encrypt' + print 'very large files.' + +def GenerateIV(length): + import whrandom + IV='' + for i in range(0, length): + IV=IV + chr(int(256*whrandom.random())) + return IV + +def Encipher(filename, cipher, key): + if (cipher==''): cipher='IDEA' + try: + exec ('from Crypto.Cipher import '+cipher) + module=eval(cipher) + except ImportError: + print executable+ ':', cipher, ': Cipher does not exist.' + sys.exit(1) + import Crypto.Hash.MD5 + try: + input=open(filename, 'r') + except IOError: + raise NoInputFile + try: + output=open(filename+'.cip', 'w') + except IOError: + raise NoOutputFile, filename+'.cip' + + if (key[0]==0): + key=raw_input('Enter encryption key for '+ filename+ ':') + else: key=key[1] + key=Crypto.Hash.MD5.new(key).digest() + IV='' + for i in range(0, module.blocksize): IV=IV+'A' + if (module.keysize==0): + cipherobj=module.new(key, module.CBC, IV) + else: + cipherobj=module.new(key[0:module.keysize], module.CBC, IV) + output.write(magic+cipher+'\0') + data = GenerateIV(module.blocksize) + filedata=input.read() + data = data + magic + str(len(filedata))+'\0'+filename+'\0' + data = data + filedata + input.close() + padding=module.blocksize - (len(data) % module.blocksize) + for i in range(0, padding): + data = data + chr(i) + ciphertext=cipherobj.encrypt(data) + output.write(ciphertext) + output.close() + +def Decipher(filename, cipher, key): + import Crypto.Hash.MD5, string + try: + input=open(filename, 'r') + except IOError: + raise NoInputFile + if (input.read(len(magic))!=magic): + print executable+':', filename+': Does not seem to be a ciphered file' + return + t='' + while (1): + c=input.read(1) + if (ord(c)==0): break + t=t+c + if (cipher==''): cipher=t + try: + from Crypto.Cipher import * + module=eval(cipher) + except ImportError: + print executable+ ':', cipher, ': Cipher does not exist.' + sys.exit(1) + if (key[0]==0): + key=raw_input('Enter encryption key for '+ filename+ ':') + else: key=key[1] + key=Crypto.Hash.MD5.new(key).digest() + IV = '' + for i in range(0, module.blocksize): IV=IV+'A' + data=input.read() + if (module.keysize==0): + cipherobj=module.new(key, module.CBC, IV) + else: + cipherobj=module.new(key[0:module.keysize], module.CBC, IV) + plain=cipherobj.decrypt(data) # Decrypt the data + plain=plain[module.blocksize:] # Discard first block of random data + if (plain[0:len(magic)]!=magic): + print executable+':', filename+': Incorrect key or cipher algorithm' + return + else: plain=plain[len(magic):] + i=string.find(plain, '\0') + length=string.atoi(plain[0:i]) + j=string.find(plain, '\0', i+1) + newfilename=plain[i+1:j] + try: + output=open(newfilename, 'w') + except IOError: + raise NoOutputFile, newfilename + output.write(plain[j+1:j+1+length]) + output.close() + +if len(sys.argv)==1: PrintUsage() ; sys.exit(0) + +options, args=getopt.getopt(sys.argv[1:], 'c:k:hH') +for opt in options: + letter, param = opt + if (letter=='-c'): cipher = param + if (letter=='-k'): key = (1, param) + if (letter=='-h' or letter=='-H'): + PrintUsage() + sys.exit(0) + +for file in args: + try: + if (file[-4:]=='.cip'): + Decipher(file, cipher, key) + else: + Encipher(file, cipher, key) + except NoInputFile: + print executable+ ':', file+ ': No such file.' + except NoOutputFile, filename: + print executable+ ':', filename+ ': Cannot open file' + diff --git a/src/Crypto/Demo/enc.py b/src/Crypto/Demo/enc.py new file mode 100644 index 00000000..0a7228e7 --- /dev/null +++ b/src/Crypto/Demo/enc.py @@ -0,0 +1,334 @@ +#!/usr/local/bin/python -Ou + +""" enc - encrypt/decrypt files using one of SSLeay's ciphers. + + Copyright (c) 1998 by Marc-Andre Lemburg; All Rights Reserved; + mailto:mal@lemburg.com; See the documentation for further + copyright information or contact the author. + + DISCLAIMER & WARNING: This tool comes with NO WARRANTY. Use at + YOUR OWN RISK. It may destroy data ! There is NO way to recover a + forgotten pass phrase ! +""" +import exceptions,os,string,time,sys +from allmydata.CryptoWorld import Ciphers,Hashes,Utils +from CommandLine import Application,SwitchOption,ArgumentOption + +# Globals +verbose = 0 + +# Maximum block size used for en/decryption +MAX_BLOCKSIZE = 1024 * 1000 + +class OperationalError(exceptions.StandardError): + pass + +def filesize(file): + + oldpos = file.tell() + file.seek(0,2) + size = file.tell() + file.seek(oldpos) + return size + +def invisible_input(prompt='>>> '): + + """ Adapted from the Python 1.5.1 docs example getpass() + """ + import termios,TERMIOS + fd = sys.stdin.fileno() + old = termios.tcgetattr(fd) + new = termios.tcgetattr(fd) + new[3] = new[3] & ~TERMIOS.ECHO # fix lflags + try: + termios.tcsetattr(fd, TERMIOS.TCSADRAIN, new) + passwd = raw_input(prompt) + finally: + termios.tcsetattr(fd, TERMIOS.TCSADRAIN, old) + print + return passwd + +def tempfile(filename='tmp', + + maxint=sys.maxint,time=time.time,int=int,hex=hex, + exists=os.path.exists): + + """ Return a new filename for a temporary file (based on filename). + """ + temp = filename + '.' + hex(maxint % int(time())) + '.tmp' + if not exists(temp): + return temp + # Ok, find an alternative name + i = 0 + while 1: + temp = '%s.%s-%i.tmp' % (filename,hex(maxint % int(time())),i) + if not exists(temp): + return temp + i = i + 1 + +# Global key +_key = '' + +def get_cipher(name,check=0): + + global _key + + cc = getattr(Ciphers,name) + keysize = cc.keysize + if not _key: + while 1: + key1 = invisible_input('Please enter the key phrase: ') + if check: + key2 = invisible_input('Please reenter the phrase: ') + if key1 != key2: + print "Phrases don't match. Please start again..." + continue + if len(key1) == 0: + print "Empty key phrase. Please start again..." + else: + break + _key = key1 + key = _key + # Fit key + if keysize > 0: + if len(key) < keysize: + key = key + \ + 'Do not change this string, it is important !'\ + [:keysize - len(key)] + elif len(key) > keysize: + key = key[:keysize] + cipher = cc(key,Ciphers.CBC) + return cipher + +def reset_key(): + + global _key + + _key = '' + +### + +def encrypt(filename,ciphername,overwrite=0): + + if verbose: + print 'Encrypting:',filename + if filename[-4:] == '.enc': + raise OperationalError,'already encrypted' + if not os.path.isfile(filename): + raise OperationalError,'not a file or not found' + + # Check overwrites + if os.path.exists(filename + '.enc'): + if not overwrite: + raise OperationalError,'would overwrite an existing file' + elif os.path.samefile(filename, filename + '.enc'): + raise OperationalError,'would overwrite the original file' + + # Open plain file + f = open(filename,'rb') + size = filesize(f) + if verbose: + print ' total size: %i bytes' % size + + # Open work file + workfilename = tempfile(filename) + out = open(workfilename,'wb') + + try: + # Init cipher and write header + cipher = get_cipher(ciphername,check=1) + out.write('enc %s %s %i\n' % \ + (repr(filename),ciphername,size)) + + # Init hash and blocksize + hash = Hashes.MD5() + blocksize = size + if blocksize > MAX_BLOCKSIZE: + blocksize = MAX_BLOCKSIZE + blocksize = ((blocksize + cipher.blocksize - 1) / cipher.blocksize) \ + * cipher.blocksize + + # Write the encrypted data in blocks + bytesread = 0 + while bytesread < size: + if verbose: + print ' reading %i bytes...' % blocksize, + block = f.read(blocksize) + if verbose: + print 'read %i bytes' % len(block) + bytesread = bytesread + len(block) + hash.update(block) + if bytesread == size: + # Final block + offset = len(block) % cipher.blocksize + if offset: + padsize = cipher.blocksize - offset + block = block + '\0'*padsize + if verbose: + print ' padding with %i bytes' % (padsize) + encblock = cipher.encrypt(block) + out.write(encblock) + + # Write hash value + hash_value = hash.digest() + if verbose: + print ' hash value:',repr(hash_value) + out.write(hash_value) + + # Copy work file to .enc file + out.close() + f.close() + os.rename(workfilename,filename+'.enc') + workfilename = None + + finally: + if workfilename: + if not out.closed: + out.close() + os.remove(workfilename) + +### + +def decrypt(filename,overwrite=0): + + if verbose: + print 'Decrypting:',filename + if filename[-4:] != '.enc': + raise OperationalError,'decrypt a plain file' + if not os.path.isfile(filename): + raise OperationalError,'not a file or not found' + + # Read header from cipher file + f = open(filename,'rb') + header = string.split(f.readline()) + if len(header) != 4: + raise OperationalError,'wrong header format:'+ str(header) + origfilename = eval(header[1]) + ciphername = header[2] + size = string.atoi(header[3]) + if verbose: + print ' total size: %i bytes' % size + + # Check overwrites + if os.path.exists(origfilename): + if not overwrite: + raise OperationalError,'would overwrite an existing file' + elif os.path.samefile(origfilename, filename): + raise OperationalError,'would overwrite the encrypted file' + + # Open work file + workfilename = tempfile(filename) + out = open(workfilename,'wb') + + try: + + # Load cipher and init hash + cipher = get_cipher(ciphername) + hash = Hashes.MD5() + + # Read the encrypted data in blocks + blocksize = size + if blocksize > MAX_BLOCKSIZE: + blocksize = MAX_BLOCKSIZE + blocksize = ((blocksize + cipher.blocksize - 1) / cipher.blocksize) \ + * cipher.blocksize + bytesread = 0 + while bytesread < size: + if size - bytesread < blocksize: + # Read remaining data only + blocksize = size - bytesread + blocksize = ((blocksize + cipher.blocksize - 1) / \ + cipher.blocksize) * cipher.blocksize + if verbose: + print ' reading %i bytes...' % blocksize, + encblock = f.read(blocksize) + if verbose: + print 'read %i bytes' % len(encblock) + bytesread = bytesread + len(encblock) + block = cipher.decrypt(encblock) + if bytesread > size: + # Depad + padsize = bytesread - size + block = block[:-padsize] + if verbose: + print ' depadded last block by %i bytes' % (padsize) + hash.update(block) + out.write(block) + + # Check hash value + hash_value = f.read(hash.digestsize) + if verbose: + print ' hash value:',repr(hash_value) + if hash_value != hash.digest(): + raise OperationalError,'data corrupt' + + # Copy workfile to origfile + out.close() + f.close() + os.rename(workfilename,origfilename) + workfilename = None + + finally: + if workfilename: + if not out.closed: + out.close() + os.remove(workfilename) + +### + +class Encrypt(Application): + + header = "File encryption utility using the SSLeay ciphers" + + about = """\ +Encrypts or decrypts the files given on the command line. If no +options are given the filenames extensions are taken as hint: '.enc' +means encrypted, everything else not encrypted. The utility then goes +and switches the state of the files. Overwriting of files only takes +place in case the '-O' switch is set. + +The following ciphers are supported: + RC2, RC4, RC5, IDEA, Blowfish, DES, DES3, CAST + +This tool comes with NO WARRANTY. Use at YOUR OWN RISK. It may destroy +data ! There is NO way to recover a forgotten pass phrase ! +""" + + options = [SwitchOption('-e', 'encrypt'), + SwitchOption('-d', 'decyrpt'), + SwitchOption('-a', 'use the same key for all files'), + SwitchOption('-O', 'allow overwrites (use with care)'), + ArgumentOption('-c', 'cipher to use', 'RC5'), + ] + + def main(self): + + overwrite = self.values['-O'] + ciphername = self.values['-c'] + samekey = self.values['-a'] + for file in self.files: + if not samekey: + reset_key() + print '-'*78 + print 'Working on file:',file + try: + if self.values['-e']: + encrypt(file,ciphername,overwrite) + elif self.values['-d']: + decrypt(file,overwrite) + elif file[-4:] != '.enc': + encrypt(file,ciphername,overwrite) + else: + decrypt(file,overwrite) + except OperationalError,why: + print '%s skipped -- %s' % (file,why) + except IOError,(code,why): + print '%s skipped -- %s' % (file,why) + except os.error,why: + print '%s skipped -- %s' % (file,why) + except KeyboardInterrupt: + print '*user break*' + break + +if __name__ == '__main__': + Encrypt() diff --git a/src/Crypto/Demo/secimp/README b/src/Crypto/Demo/secimp/README new file mode 100644 index 00000000..94a6e30e --- /dev/null +++ b/src/Crypto/Demo/secimp/README @@ -0,0 +1,24 @@ + +This is a simple demonstration of adding an import hook that verifies +a digital signature on a Python code object before allowing it to be +imported. There are three files: + + * sign.py, which signs all the *.pyc files in the directories +listed on the command line. The contents of the .pyc file is stored +along with the signature in a file whose name ends with .pys . + + * secimp.py, which implements a secimport() function which +will use *.pys files. + + * testkey.py is the key used to sign and verify *.pys files. + +To try it out: + 1. Run "sign.py ." to compile and sign all the *.py files in +the current directory. + + 2. Run secimp.py from the command-line; it will try to +securely import testkey.pys, which should succeed. + + 3. Fire up your favorite editor, and change a single byte in a +string somewhere in testkey.pys. Run secimp.py again; it should raise +an exception when the signature can't be verified. diff --git a/src/Crypto/Demo/secimp/secimp.py b/src/Crypto/Demo/secimp/secimp.py new file mode 100644 index 00000000..451aa7e3 --- /dev/null +++ b/src/Crypto/Demo/secimp/secimp.py @@ -0,0 +1,84 @@ +#!/usr/local/bin/python + +import sys ; sys.path = ['../../../'] + sys.path + +import imp, os +from sys import modules + +# Secure import: +def secimport(name, globals=None, locals=None, fromlist=None): + # Fast path: let's see if it's already in sys.modules. + # Two speed optimizations are worth mentioning: + # - We use 'modules' instead of 'sys.modules'; this saves a + # dictionary look-up per call. + # - It's also faster to use a try-except statement than + # to use modules.has_key(name) to check if it's there. + try: + return modules[name] + except KeyError: + pass + + # See if it's a built-in module + m = imp.init_builtin(name) + if m: + return m + + # See if it's a frozen module + m = imp.init_frozen(name) + if m: + return m + + # Search the default path (i.e. sys.path). + # If this raises an exception, the module is not found -- + # let the caller handle the exception. + fp, pathname, (suffix, mode, type) = imp.find_module(name) + + # See what we got... + # Note that fp will be closed automatically when we return. + + # Extensions are written in C, and can just be loaded. + if type == imp.C_EXTENSION: + return imp.load_dynamic(name, pathname) + + # For a compiled or source file, we'll check if there is a *.pys file + # present in the same directory. + if type == imp.PY_COMPILED or type == imp.PY_SOURCE: + root, ext = os.path.splitext(pathname) + testfile = root + '.pys' + try: + print testfile + secfile=open(testfile, 'rb') + except IOError, tuple: + if (tuple[0]==2): pass # Ignore 'file not found' error + else: raise IOError, tuple + else: + # Check the signature (a signed hash of the code object). + # We could sign the whole code object, but that would + # require a huge key and would double the size of the + # *.pys file. + import marshal + from allmydata.Crypto.Hash import MD5 + fp.close() # Close the original *.pyc file + from testkey import * # Get the key for verification + signature=marshal.load(secfile) # Read signature + position=secfile.tell() # Save position + data=secfile.read() # Read code object + hash=MD5.new(data).digest() # Compute its hash value + ##print 'sigcheck:', key.verify(hash, signature) + if (not key.verify(hash, signature)): + raise ImportError, 'Signature check of '+ testfile + ' failed' + secfile.seek(position) # Rewind pointer to the + # beginning of the code object + fp=secfile + del secfile + # Now we can happily import the compiled code object. + return imp.load_compiled(name, pathname, fp) + + # Shouldn't get here at all. + raise ImportError, '%s: unknown module type (%d)' % (name, type) + +if __name__=='__main__': + # A sample invocation of the secure import looks like this: + print 'Attempting secure import' + r=secimport('testkey') + print 'Secure import succeeded' diff --git a/src/Crypto/Demo/secimp/sign.py b/src/Crypto/Demo/secimp/sign.py new file mode 100644 index 00000000..afc90166 --- /dev/null +++ b/src/Crypto/Demo/secimp/sign.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +# Using the public key defined in testkey.py, sign all *.pyc files in +# the listed directories. + +from testkey import * +from allmydata.Crypto.Hash import MD5 +import os, glob, sys +import marshal, compileall + +filelist = [] +if (len(sys.argv)>1): + for dir in sys.argv[1:]: + dir=os.path.join(dir, '') + compileall.compile_dir(dir) + filelist=filelist + glob.glob(dir + '*.pyc') +else: + print "Usage: sign.py dir1 dir2 dir3 ..." + print " All *.pyc files in the listed directories will be signed," + print "leaving the signatures in *.pys files." + sys.exit(0) + +if len(filelist)==0: + print "No *.pyc files found" + sys.exit(0) + +for file in filelist: + input=open(file, 'rb') + try: + os.unlink(file[:-4]+'.pys') # Delete any existing signed file + except os.error, tuple: + if (tuple[0]==2): pass # Ignore 'file not found' error + else: raise os.error, tuple + output=open(file[:-4]+'.pys', 'wb') + data=input.read() + hash=MD5.new(data).digest() # Compute hash of the code object + K = "random bytes" + signature=key.sign(hash, K) # Sign the hash value + marshal.dump(signature, output) # Save signature to the file + output.write(data) # Copy code object to signed file + input.close() + output.close() + print os.path.basename(file)+ ' processed.' + + + diff --git a/src/Crypto/Demo/secimp/testkey.py b/src/Crypto/Demo/secimp/testkey.py new file mode 100644 index 00000000..456b33ff --- /dev/null +++ b/src/Crypto/Demo/secimp/testkey.py @@ -0,0 +1,41 @@ + +import sys +import allmydata.Crypto.PublicKey.DSA + +key = allmydata.Crypto.PublicKey.DSA.construct(( + # y + 0x43E9162E224CBD1B66D7C27EB7E795392310B5E7AC6E0B1F60021F5E03F90E851CB7F76603FAE73907154371AE04EDBF0D9D557DF03488F34C18324B8DFEF5D2L, + # g + 0x4D6DB63479E55D0BE31CF1BEA58AB9365FC5EA267FFCD8424B56390E6EE7DD9BF788F696EED8475516353E61F37B8441137FA4F8DC82A9F84FA52BCD37517C32L, + # p + 0x8000011124427A59DC0AF8AC982B490C75B1B3E94042F50F500E0636391C6FCC8C13E628528B4B75E158618A34592D5A68CA684371F9678BBA54DD40C0020F25L, + # q + 0x9B128544B02353FF961E1774D2FA94E52E078F5DL, + # x + 0x991386B7B92C221E42B1386D61255F5C58FD79A7L, +)) + +if __name__ == '__main__': + # Running this script directly will generate a new key and print it out + from allmydata.Crypto.PublicKey import DSA + from allmydata.Crypto.Util.randpool import KeyboardRandomPool + + pool = KeyboardRandomPool(numbytes = 64) + pool.randomize() + + if len(sys.argv) == 2: + keylen = int(sys.argv[1]) + elif len(sys.argv) == 1: + keylen = 512 + else: + print >>sys.stderr, 'Usage: '+sys.argv[0]+' [keylen]' + sys.exit(1) + key = DSA.generate(keylen, pool.get_bytes, sys.stdout.write) + print "key = allmydata.Crypto.PublicKey.DSA.construct((" + for field in key.keydata: + print " #", field + print " " + hex(getattr(key, field)) + "," + print '))' + + + diff --git a/src/Crypto/Doc/pycrypt.tex b/src/Crypto/Doc/pycrypt.tex new file mode 100644 index 00000000..d9c9bf62 --- /dev/null +++ b/src/Crypto/Doc/pycrypt.tex @@ -0,0 +1,1188 @@ +\documentclass{howto} + +\title{Python Cryptography Toolkit} + +\release{2.0.1} + +\author{A.M. Kuchling} +\authoraddress{\url{www.amk.ca}} + +\begin{document} +\maketitle + +\begin{abstract} +\noindent +The Python Cryptography Toolkit describes a package containing various +cryptographic modules for the Python programming language. This +documentation assumes you have some basic knowledge about the Python +language, but not necessarily about cryptography. + +\end{abstract} + +\tableofcontents + + +%====================================================================== +\section{Introduction} + +\subsection{Design Goals} +The Python cryptography toolkit is intended to provide a reliable and +stable base for writing Python programs that require cryptographic +functions. + +A central goal of the author's has been to provide a simple, +consistent interface for similar classes of algorithms. For example, +all block cipher objects have the same methods and return values, and +support the same feedback modes. Hash functions have a different +interface, but it too is consistent over all the hash functions +available. Some of these interfaces have been codified as Python +Enhancement Proposal documents, as \pep{247}, ``API for Cryptographic +Hash Functions'', and \pep{272}, ``API for Block Encryption +Algorithms''. + +This is intended to make it easy to replace old algorithms with newer, +more secure ones. If you're given a bit of portably-written Python +code that uses the DES encryption algorithm, you should be able to use +AES instead by simply changing \code{from Crypto.Cipher import DES} to +\code{from Crypto.Cipher import AES}, and changing all references to +\code{DES.new()} to \code{AES.new()}. It's also fairly simple to +write your own modules that mimic this interface, thus letting you use +combinations or permutations of algorithms. + +Some modules are implemented in C for performance; others are written +in Python for ease of modification. Generally, low-level functions +like ciphers and hash functions are written in C, while less +speed-critical functions have been written in Python. This division +may change in future releases. When speeds are quoted in this +document, they were measured on a 500 MHz Pentium II running Linux. +The exact speeds will obviously vary with different machines, +different compilers, and the phase of the moon, but they provide a +crude basis for comparison. Currently the cryptographic +implementations are acceptably fast, but not spectacularly good. I +welcome any suggestions or patches for faster code. + +I have placed the code under no restrictions; you can redistribute the +code freely or commercially, in its original form or with any +modifications you make, subject to whatever local laws may apply in your +jurisdiction. Note that you still have to come to some agreement with +the holders of any patented algorithms you're using. If you're +intensively using these modules, please tell me about it; there's little +incentive for me to work on this package if I don't know of anyone using +it. + +I also make no guarantees as to the usefulness, correctness, or legality +of these modules, nor does their inclusion constitute an endorsement of +their effectiveness. Many cryptographic algorithms are patented; +inclusion in this package does not necessarily mean you are allowed to +incorporate them in a product and sell it. Some of these algorithms may +have been cryptanalyzed, and may no longer be secure. While I will +include commentary on the relative security of the algorithms in the +sections entitled "Security Notes", there may be more recent analyses +I'm not aware of. (Or maybe I'm just clueless.) If you're implementing +an important system, don't just grab things out of a toolbox and put +them together; do some research first. On the other hand, if you're +just interested in keeping your co-workers or your relatives out of your +files, any of the components here could be used. + +This document is very much a work in progress. If you have any +questions, comments, complaints, or suggestions, please send them to me. + +\subsection{Acknowledgements} +Much of the code that actually implements the various cryptographic +algorithms was not written by me. I'd like to thank all the people who +implemented them, and released their work under terms which allowed me +to use their code. These individuals are credited in the relevant +chapters of this documentation. Bruce Schneier's book \emph{Applied +Cryptography} was also very useful in writing this toolkit; I highly +recommend it if you're interested in learning more about cryptography. + +Good luck with your cryptography hacking! + +A.M.K. + +\email{comments@amk.ca} + +Washington DC, USA + +June 2005 + + +%====================================================================== +\section{Crypto.Hash: Hash Functions} + +Hash functions take arbitrary strings as input, and produce an output +of fixed size that is dependent on the input; it should never be +possible to derive the input data given only the hash function's +output. One simple hash function consists of simply adding together +all the bytes of the input, and taking the result modulo 256. For a +hash function to be cryptographically secure, it must be very +difficult to find two messages with the same hash value, or to find a +message with a given hash value. The simple additive hash function +fails this criterion miserably and the hash functions described below +meet this criterion (as far as we know). Examples of +cryptographically secure hash functions include MD2, MD5, and SHA1. + +Hash functions can be used simply as a checksum, or, in association with a +public-key algorithm, can be used to implement digital signatures. + +The hashing algorithms currently implemented are: + +\begin{tableii}{c|l}{}{Hash function}{Digest length} +\lineii{MD2}{128 bits} +\lineii{MD4}{128 bits} +\lineii{MD5}{128 bits} +\lineii{RIPEMD}{160 bits} +\lineii{SHA1}{160 bits} +\lineii{SHA256}{256 bits} +\end{tableii} + +All hashing modules share the same interface. After importing a given +hashing module, call the \function{new()} function to create a new +hashing object. You can now feed arbitrary strings into the object +with the \method{update()} method, and can ask for the hash value at +any time by calling the \method{digest()} or \method{hexdigest()} +methods. The \function{new()} function can also be passed an optional +string parameter that will be immediately hashed into the object's +state. + +Hash function modules define one variable: + +\begin{datadesc}{digest_size} +An integer value; the size of the digest +produced by the hashing objects. You could also obtain this value by +creating a sample object, and taking the length of the digest string +it returns, but using \member{digest_size} is faster. +\end{datadesc} + +The methods for hashing objects are always the following: + +\begin{methoddesc}{copy}{} +Return a separate copy of this hashing object. An \code{update} to +this copy won't affect the original object. +\end{methoddesc} + +\begin{methoddesc}{digest}{} +Return the hash value of this hashing object, as a string containing +8-bit data. The object is not altered in any way by this function; +you can continue updating the object after calling this function. +\end{methoddesc} + +\begin{methoddesc}{hexdigest}{} +Return the hash value of this hashing object, as a string containing +the digest data as hexadecimal digits. The resulting string will be +twice as long as that returned by \method{digest()}. The object is not +altered in any way by this function; you can continue updating the +object after calling this function. +\end{methoddesc} + +\begin{methoddesc}{update}{arg} +Update this hashing object with the string \var{arg}. +\end{methoddesc} + +Here's an example, using the MD5 algorithm: + +\begin{verbatim} +>>> from Crypto.Hash import MD5 +>>> m = MD5.new() +>>> m.update('abc') +>>> m.digest() +'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr' +>>> m.hexdigest() +'900150983cd24fb0d6963f7d28e17f72' +\end{verbatim} + + +\subsection{Security Notes} + +Hashing algorithms are broken by developing an algorithm to compute a +string that produces a given hash value, or to find two messages that +produce the same hash value. Consider an example where Alice and Bob +are using digital signatures to sign a contract. Alice computes the +hash value of the text of the contract and signs the hash value with +her private key. Bob could then compute a different contract that has +the same hash value, and it would appear that Alice signed that bogus +contract; she'd have no way to prove otherwise. Finding such a +message by brute force takes \code{pow(2, b-1)} operations, where the +hash function produces \emph{b}-bit hashes. + +If Bob can only find two messages with the same hash value but can't +choose the resulting hash value, he can look for two messages with +different meanings, such as "I will mow Bob's lawn for $10" and "I owe +Bob $1,000,000", and ask Alice to sign the first, innocuous contract. +This attack is easier for Bob, since finding two such messages by brute +force will take \code{pow(2, b/2)} operations on average. However, +Alice can protect herself by changing the protocol; she can simply +append a random string to the contract before hashing and signing it; +the random string can then be kept with the signature. + +None of the algorithms implemented here have been completely broken. +There are no attacks on MD2, but it's rather slow at 1250 K/sec. MD4 +is faster at 44,500 K/sec but there have been some partial attacks on +it. MD4 makes three iterations of a basic mixing operation; two of +the three rounds have been cryptanalyzed, but the attack can't be +extended to the full algorithm. MD5 is a strengthened version of MD4 +with four rounds; an attack against one round has been found XXX +update this. MD5 is still believed secure at the moment, but people +are gravitating toward using SHA1 in new software because there are no +known attacks against SHA1. The MD5 implementation is moderately +well-optimized and thus faster on x86 processors, running at 35,500 +K/sec. MD5 may even be faster than MD4, depending on the processor +and compiler you use. + +All the MD\var{n} algorithms produce 128-bit hashes; SHA1 produces a +larger 160-bit hash, and there are no known attacks against it. The +first version of SHA had a weakness which was later corrected; the +code used here implements the second, corrected, version. It operates +at 21,000 K/sec. SHA256 is about as half as fast as SHA1. RIPEMD has +a 160-bit output, the same output size as SHA1, and operates at 17,600 +K/sec. + +\subsection{Credits} +The MD2 and MD4 implementations were written by A.M. Kuchling, and the +MD5 code was implemented by Colin Plumb. The SHA1 code was originally +written by Peter Gutmann. The RIPEMD code was written by Antoon +Bosselaers, and adapted for the toolkit by Hirendra Hindocha. The +SHA256 code was written by Tom St.~Denis and is part of the +LibTomCrypt library (\url{http://www.libtomcrypt.org/}); it was +adapted for the toolkit by Jeethu Rao and Taylor Boon. + + +%====================================================================== +\section{Crypto.Cipher: Encryption Algorithms} + +Encryption algorithms transform their input data, or \dfn{plaintext}, +in some way that is dependent on a variable \dfn{key}, producing +\dfn{ciphertext}. This transformation can easily be reversed, if (and, +hopefully, only if) one knows the key. The key can be varied by the +user or application and chosen from some very large space of possible +keys. + +For a secure encryption algorithm, it should be very difficult to +determine the original plaintext without knowing the key; usually, no +clever attacks on the algorithm are known, so the only way of breaking +the algorithm is to try all possible keys. Since the number of possible +keys is usually of the order of 2 to the power of 56 or 128, this is not +a serious threat, although 2 to the power of 56 is now considered +insecure in the face of custom-built parallel computers and distributed +key guessing efforts. + +\dfn{Block ciphers} take multibyte inputs of a fixed size +(frequently 8 or 16 bytes long) and encrypt them. Block ciphers can +be operated in various modes. The simplest is Electronic Code Book +(or ECB) mode. In this mode, each block of plaintext is simply +encrypted to produce the ciphertext. This mode can be dangerous, +because many files will contain patterns greater than the block size; +for example, the comments in a C program may contain long strings of +asterisks intended to form a box. All these identical blocks will +encrypt to identical ciphertext; an adversary may be able to use this +structure to obtain some information about the text. + +To eliminate this weakness, there are various feedback modes in which +the plaintext is combined with the previous ciphertext before +encrypting; this eliminates any repetitive structure in the +ciphertext. + +One mode is Cipher Block Chaining (CBC mode); another is Cipher +FeedBack (CFB mode). CBC mode still encrypts in blocks, and thus is +only slightly slower than ECB mode. CFB mode encrypts on a +byte-by-byte basis, and is much slower than either of the other two +modes. The chaining feedback modes require an initialization value to +start off the encryption; this is a string of the same length as the +ciphering algorithm's block size, and is passed to the \code{new()} +function. There is also a special PGP mode, which is an oddball +variant of CFB used by the PGP program. While you can use it in +non-PGP programs, it's quite non-standard. + +The currently available block ciphers are listed in the following table, +and are in the \code{Crypto.Cipher} package: + +\begin{tableii}{c|l}{}{Cipher}{Key Size/Block Size} +\lineii{AES}{16, 24, or 32 bytes/16 bytes} +\lineii{ARC2}{Variable/8 bytes} +\lineii{Blowfish}{Variable/8 bytes} +\lineii{CAST}{Variable/8 bytes} +\lineii{DES}{8 bytes/8 bytes} +\lineii{DES3 (Triple DES)}{16 bytes/8 bytes} +\lineii{IDEA}{16 bytes/8 bytes} +\lineii{RC5}{Variable/8 bytes} +\end{tableii} + +In a strict formal sense, \dfn{stream ciphers} encrypt data bit-by-bit; +practically, stream ciphers work on a character-by-character basis. +Stream ciphers use exactly the +same interface as block ciphers, with a block length that will always +be 1; this is how block and stream ciphers can be distinguished. +The only feedback mode available for stream ciphers is ECB mode. + +The currently available stream ciphers are listed in the following table: + +\begin{tableii}{c|l}{}{Cipher}{Key Size} +\lineii{Cipher}{Key Size} + \lineii{ARC4}{Variable} + \lineii{XOR}{Variable} +\end{tableii} + +ARC4 is short for `Alleged RC4'. In September of 1994, someone posted +C code to both the Cypherpunks mailing list and to the Usenet +newsgroup \code{sci.crypt}, claiming that it implemented the RC4 +algorithm. This claim turned out to be correct. Note that there's a +damaging class of weak RC4 keys; this module won't warn you about such keys. +% XXX other analyses of RC4? + +A similar anonymous posting was made for Alleged RC2 in January, 1996. + +An example usage of the DES module: +\begin{verbatim} +>>> from Crypto.Cipher import DES +>>> obj=DES.new('abcdefgh', DES.MODE_ECB) +>>> plain="Guido van Rossum is a space alien." +>>> len(plain) +34 +>>> obj.encrypt(plain) +Traceback (innermost last): + File "", line 1, in ? +ValueError: Strings for DES must be a multiple of 8 in length +>>> ciph=obj.encrypt(plain+'XXXXXX') +>>> ciph +'\021,\343Nq\214DY\337T\342pA\372\255\311s\210\363,\300j\330\250\312\347\342I\3215w\03561\303dgb/\006' +>>> obj.decrypt(ciph) +'Guido van Rossum is a space alien.XXXXXX' +\end{verbatim} + +All cipher algorithms share a common interface. After importing a +given module, there is exactly one function and two variables +available. + +\begin{funcdesc}{new}{key, mode\optional{, IV}} +Returns a ciphering object, using \var{key} and feedback mode +\var{mode}. If \var{mode} is \constant{MODE_CBC} or \constant{MODE_CFB}, \var{IV} must be provided, +and must be a string of the same length as the block size. Some +algorithms support additional keyword arguments to this function; see +the "Algorithm-specific Notes for Encryption Algorithms" section below for the details. +\end{funcdesc} + +\begin{datadesc}{block_size} +An integer value; the size of the blocks encrypted by this module. +Strings passed to the \code{encrypt} and \code{decrypt} functions +must be a multiple of this length. For stream ciphers, +\code{block_size} will be 1. +\end{datadesc} + +\begin{datadesc}{key_size} +An integer value; the size of the keys required by this module. If +\code{key_size} is zero, then the algorithm accepts arbitrary-length +keys. You cannot pass a key of length 0 (that is, the null string +\code{''} as such a variable-length key. +\end{datadesc} + +All cipher objects have at least three attributes: + +\begin{memberdesc}{block_size} +An integer value equal to the size of the blocks encrypted by this object. +Identical to the module variable of the same name. +\end{memberdesc} + +\begin{memberdesc}{IV} +Contains the initial value which will be used to start a cipher +feedback mode. After encrypting or decrypting a string, this value +will reflect the modified feedback text; it will always be one block +in length. It is read-only, and cannot be assigned a new value. +\end{memberdesc} + +\begin{memberdesc}{key_size} +An integer value equal to the size of the keys used by this object. If +\code{key_size} is zero, then the algorithm accepts arbitrary-length +keys. For algorithms that support variable length keys, this will be 0. +Identical to the module variable of the same name. +\end{memberdesc} + +All ciphering objects have the following methods: + +\begin{methoddesc}{decrypt}{string} +Decrypts \var{string}, using the key-dependent data in the object, and +with the appropriate feedback mode. The string's length must be an exact +multiple of the algorithm's block size. Returns a string containing +the plaintext. +\end{methoddesc} + +\begin{methoddesc}{encrypt}{string} +Encrypts a non-null \var{string}, using the key-dependent data in the +object, and with the appropriate feedback mode. The string's length +must be an exact multiple of the algorithm's block size; for stream +ciphers, the string can be of any length. Returns a string containing +the ciphertext. +\end{methoddesc} + + +\subsection{Algorithm-specific Notes for Encryption Algorithms} + +RC5 has a bunch of parameters; see Ronald Rivest's paper at +\url{http://theory.lcs.mit.edu/~rivest/rc5rev.ps} for the +implementation details. The keyword parameters are: + +\begin{itemize} +\item \code{version}: +The version +of the RC5 algorithm to use; currently the only legal value is +\code{0x10} for RC5 1.0. +\item \code{wordsize}: +The word size to use; +16 or 32 are the only legal values. (A larger word size is better, so +usually 32 will be used. 16-bit RC5 is probably only of academic +interest.) +\item \code{rounds}: +The number of rounds to apply, the larger the more secure: this +can be any value from 0 to 255, so you will have to choose a value +balanced between speed and security. +\end{itemize} + + +\subsection{Security Notes} +Encryption algorithms can be broken in several ways. If you have some +ciphertext and know (or can guess) the corresponding plaintext, you can +simply try every possible key in a \dfn{known-plaintext} attack. Or, it +might be possible to encrypt text of your choice using an unknown key; +for example, you might mail someone a message intending it to be +encrypted and forwarded to someone else. This is a +\dfn{chosen-plaintext} attack, which is particularly effective if it's +possible to choose plaintexts that reveal something about the key when +encrypted. + +DES (5100 K/sec) has a 56-bit key; this is starting to become too small +for safety. It has been estimated that it would only cost \$1,000,000 to +build a custom DES-cracking machine that could find a key in 3 hours. A +chosen-ciphertext attack using the technique of \dfn{linear +cryptanalysis} can break DES in \code{pow(2, 43)} steps. However, +unless you're encrypting data that you want to be safe from major +governments, DES will be fine. DES3 (1830 K/sec) uses three DES +encryptions for greater security and a 112-bit or 168-bit key, but is +correspondingly slower. + +There are no publicly known attacks against IDEA (3050 K/sec), and +it's been around long enough to have been examined. There are no +known attacks against ARC2 (2160 K/sec), ARC4 (8830 K/sec), Blowfish +(9250 K/sec), CAST (2960 K/sec), or RC5 (2060 K/sec), but they're all +relatively new algorithms and there hasn't been time for much analysis +to be performed; use them for serious applications only after careful +research. + +AES, the Advanced Encryption Standard, was chosen by the US National +Institute of Standards and Technology from among 6 competitors, and is +probably your best choice. It runs at 7060 K/sec, so it's among the +faster algorithms around. + + +\subsection{Credits} +The code for Blowfish was written by Bryan Olson, partially based on a +previous implementation by Bruce Schneier, who also invented the +algorithm; the Blowfish algorithm has been placed in the public domain +and can be used freely. (See \url{http://www.counterpane.com} for more +information about Blowfish.) The CAST implementation was written by +Wim Lewis. The DES implementation was written by Eric Young, and the +IDEA implementation by Colin Plumb. The RC5 implementation +was written by A.M. Kuchling. + +The Alleged RC4 code was posted to the \code{sci.crypt} newsgroup by an +unknown party, and re-implemented by A.M. Kuchling. + + +%====================================================================== +\section{Crypto.Protocol: Various Protocols} + +\subsection{Crypto.Protocol.AllOrNothing} + +This module implements all-or-nothing package transformations. +An all-or-nothing package transformation is one in which some text is +transformed into message blocks, such that all blocks must be obtained before +the reverse transformation can be applied. Thus, if any blocks are corrupted +or lost, the original message cannot be reproduced. + +An all-or-nothing package transformation is not encryption, although a block +cipher algorithm is used. The encryption key is randomly generated and is +extractable from the message blocks. + +\begin{classdesc}{AllOrNothing}{ciphermodule, mode=None, IV=None} +Class implementing the All-or-Nothing package transform. + +\var{ciphermodule} is a module implementing the cipher algorithm to +use. Optional arguments \var{mode} and \var{IV} are passed directly +through to the \var{ciphermodule}.\code{new()} method; they are the +feedback mode and initialization vector to use. All three arguments +must be the same for the object used to create the digest, and to +undigest'ify the message blocks. + +The module passed as \var{ciphermodule} must provide the \pep{272} +interface. An encryption key is randomly generated automatically when +needed. +\end{classdesc} + +The methods of the \class{AllOrNothing} class are: + +\begin{methoddesc}{digest}{text} +Perform the All-or-Nothing package transform on the +string \var{text}. Output is a list of message blocks describing the +transformed text, where each block is a string of bit length equal +to the cipher module's block_size. +\end{methoddesc} + +\begin{methoddesc}{undigest}{mblocks} +Perform the reverse package transformation on a list of message +blocks. Note that the cipher module used for both transformations +must be the same. \var{mblocks} is a list of strings of bit length +equal to \var{ciphermodule}'s block_size. The output is a string object. +\end{methoddesc} + + +\subsection{Crypto.Protocol.Chaffing} + +Winnowing and chaffing is a technique for enhancing privacy without requiring +strong encryption. In short, the technique takes a set of authenticated +message blocks (the wheat) and adds a number of chaff blocks which have +randomly chosen data and MAC fields. This means that to an adversary, the +chaff blocks look as valid as the wheat blocks, and so the authentication +would have to be performed on every block. By tailoring the number of chaff +blocks added to the message, the sender can make breaking the message +computationally infeasible. There are many other interesting properties of +the winnow/chaff technique. + +For example, say Alice is sending a message to Bob. She packetizes the +message and performs an all-or-nothing transformation on the packets. Then +she authenticates each packet with a message authentication code (MAC). The +MAC is a hash of the data packet, and there is a secret key which she must +share with Bob (key distribution is an exercise left to the reader). She then +adds a serial number to each packet, and sends the packets to Bob. + +Bob receives the packets, and using the shared secret authentication key, +authenticates the MACs for each packet. Those packets that have bad MACs are +simply discarded. The remainder are sorted by serial number, and passed +through the reverse all-or-nothing transform. The transform means that an +eavesdropper (say Eve) must acquire all the packets before any of the data can +be read. If even one packet is missing, the data is useless. + +There's one twist: by adding chaff packets, Alice and Bob can make Eve's job +much harder, since Eve now has to break the shared secret key, or try every +combination of wheat and chaff packet to read any of the message. The cool +thing is that Bob doesn't need to add any additional code; the chaff packets +are already filtered out because their MACs don't match (in all likelihood -- +since the data and MACs for the chaff packets are randomly chosen it is +possible, but very unlikely that a chaff MAC will match the chaff data). And +Alice need not even be the party adding the chaff! She could be completely +unaware that a third party, say Charles, is adding chaff packets to her +messages as they are transmitted. + +\begin{classdesc}{Chaff}{factor=1.0, blocksper=1} +Class implementing the chaff adding algorithm. +\var{factor} is the number of message blocks + to add chaff to, expressed as a percentage between 0.0 and 1.0; the default value is 1.0. +\var{blocksper} is the number of chaff blocks to include for each block + being chaffed, and defaults to 1. The default settings +add one chaff block to every + message block. By changing the defaults, you can adjust how + computationally difficult it could be for an adversary to + brute-force crack the message. The difficulty is expressed as: + +\begin{verbatim} +pow(blocksper, int(factor * number-of-blocks)) +\end{verbatim} + +For ease of implementation, when \var{factor} < 1.0, only the first +\code{int(\var{factor}*number-of-blocks)} message blocks are chaffed. +\end{classdesc} + +\class{Chaff} instances have the following methods: + +\begin{methoddesc}{chaff}{blocks} +Add chaff to message blocks. \var{blocks} is a list of 3-tuples of the +form (\var{serial-number}, \var{data}, \var{MAC}). + +Chaff is created by choosing a random number of the same +byte-length as \var{data}, and another random number of the same +byte-length as \var{MAC}. The message block's serial number is placed +on the chaff block and all the packet's chaff blocks are randomly +interspersed with the single wheat block. This method then +returns a list of 3-tuples of the same form. Chaffed blocks will +contain multiple instances of 3-tuples with the same serial +number, but the only way to figure out which blocks are wheat and +which are chaff is to perform the MAC hash and compare values. +\end{methoddesc} + + +%====================================================================== +\section{Crypto.PublicKey: Public-Key Algorithms} +So far, the encryption algorithms described have all been \dfn{private +key} ciphers. The same key is used for both encryption and decryption +so all correspondents must know it. This poses a problem: you may +want encryption to communicate sensitive data over an insecure +channel, but how can you tell your correspondent what the key is? You +can't just e-mail it to her because the channel is insecure. One +solution is to arrange the key via some other way: over the phone or +by meeting in person. + +Another solution is to use \dfn{public-key} cryptography. In a public +key system, there are two different keys: one for encryption and one for +decryption. The encryption key can be made public by listing it in a +directory or mailing it to your correspondent, while you keep the +decryption key secret. Your correspondent then sends you data encrypted +with your public key, and you use the private key to decrypt it. While +the two keys are related, it's very difficult to derive the private key +given only the public key; however, deriving the private key is always +possible given enough time and computing power. This makes it very +important to pick keys of the right size: large enough to be secure, but +small enough to be applied fairly quickly. + +Many public-key algorithms can also be used to sign messages; simply +run the message to be signed through a decryption with your private +key key. Anyone receiving the message can encrypt it with your +publicly available key and read the message. Some algorithms do only +one thing, others can both encrypt and authenticate. + +The currently available public-key algorithms are listed in the +following table: + +\begin{tableii}{c|l}{}{Algorithm}{Capabilities} +\lineii{RSA}{Encryption, authentication/signatures} +\lineii{ElGamal}{Encryption, authentication/signatures} +\lineii{DSA}{Authentication/signatures} +\lineii{qNEW}{Authentication/signatures} +\end{tableii} + +Many of these algorithms are patented. Before using any of them in a +commercial product, consult a patent attorney; you may have to arrange +a license with the patent holder. + +An example of using the RSA module to sign a message: +\begin{verbatim} +>>> from Crypto.Hash import MD5 +>>> from Crypto.PublicKey import RSA +>>> RSAkey = RSA.generate(384, randfunc) # This will take a while... +>>> hash = MD5.new(plaintext).digest() +>>> signature = RSAkey.sign(hash, "") +>>> signature # Print what an RSA sig looks like--you don't really care. +('\021\317\313\336\264\315' ...,) +>>> RSAkey.verify(hash, signature) # This sig will check out +1 +>>> RSAkey.verify(hash[:-1], signature)# This sig will fail +0 +\end{verbatim} + +Public-key modules make the following functions available: + +\begin{funcdesc}{construct}{tuple} +Constructs a key object from a tuple of data. This is +algorithm-specific; look at the source code for the details. (To be +documented later.) +\end{funcdesc} + +\begin{funcdesc}{generate}{size, randfunc, progress_func=\code{None}} +Generate a fresh public/private key pair. \var{size} is a +algorithm-dependent size parameter, usually measured in bits; the +larger it is, the more difficult it will be to break the key. Safe +key sizes vary from algorithm to algorithm; you'll have to research +the question and decide on a suitable key size for your application. +An N-bit keys can encrypt messages up to N-1 bits long. + +\var{randfunc} is a random number generation function; it should +accept a single integer \var{N} and return a string of random data +\var{N} bytes long. You should always use a cryptographically secure +random number generator, such as the one defined in the +\module{Crypto.Util.randpool} module; \emph{don't} just use the +current time and the \module{random} module. + +\var{progress_func} is an optional function that will be called with a short +string containing the key parameter currently being generated; it's +useful for interactive applications where a user is waiting for a key +to be generated. +\end{funcdesc} + +If you want to interface with some other program, you will have to know +the details of the algorithm being used; this isn't a big loss. If you +don't care about working with non-Python software, simply use the +\module{pickle} module when you need to write a key or a signature to a +file. It's portable across all the architectures that Python supports, +and it's simple to use. + +Public-key objects always support the following methods. Some of them +may raise exceptions if their functionality is not supported by the +algorithm. + +\begin{methoddesc}{can_blind}{} +Returns true if the algorithm is capable of blinding data; +returns false otherwise. +\end{methoddesc} + +\begin{methoddesc}{can_encrypt}{} +Returns true if the algorithm is capable of encrypting and decrypting +data; returns false otherwise. To test if a given key object can encrypt +data, use \code{key.can_encrypt() and key.has_private()}. +\end{methoddesc} + +\begin{methoddesc}{can_sign}{} +Returns true if the algorithm is capable of signing data; returns false +otherwise. To test if a given key object can sign data, use +\code{key.can_sign() and key.has_private()}. +\end{methoddesc} + +\begin{methoddesc}{decrypt}{tuple} +Decrypts \var{tuple} with the private key, returning another string. +This requires the private key to be present, and will raise an exception +if it isn't present. It will also raise an exception if \var{string} is +too long. +\end{methoddesc} + +\begin{methoddesc}{encrypt}{string, K} +Encrypts \var{string} with the private key, returning a tuple of +strings; the length of the tuple varies from algorithm to algorithm. +\var{K} should be a string of random data that is as long as +possible. Encryption does not require the private key to be present +inside the key object. It will raise an exception if \var{string} is +too long. For ElGamal objects, the value of \var{K} expressed as a +big-endian integer must be relatively prime to \code{self.p-1}; an +exception is raised if it is not. +\end{methoddesc} + +\begin{methoddesc}{has_private}{} +Returns true if the key object contains the private key data, which +will allow decrypting data and generating signatures. +Otherwise this returns false. +\end{methoddesc} + +\begin{methoddesc}{publickey}{} +Returns a new public key object that doesn't contain the private key +data. +\end{methoddesc} + +\begin{methoddesc}{sign}{string, K} +Sign \var{string}, returning a signature, which is just a tuple; in +theory the signature may be made up of any Python objects at all; in +practice they'll be either strings or numbers. \var{K} should be a +string of random data that is as long as possible. Different algorithms +will return tuples of different sizes. \code{sign()} raises an +exception if \var{string} is too long. For ElGamal objects, the value +of \var{K} expressed as a big-endian integer must be relatively prime to +\code{self.p-1}; an exception is raised if it is not. +\end{methoddesc} + +\begin{methoddesc}{size}{} +Returns the maximum size of a string that can be encrypted or signed, +measured in bits. String data is treated in big-endian format; the most +significant byte comes first. (This seems to be a \emph{de facto} standard +for cryptographical software.) If the size is not a multiple of 8, then +some of the high order bits of the first byte must be zero. Usually +it's simplest to just divide the size by 8 and round down. +\end{methoddesc} + +\begin{methoddesc}{verify}{string, signature} +Returns true if the signature is valid, and false otherwise. +\var{string} is not processed in any way; \code{verify} does +not run a hash function over the data, but you can easily do that yourself. +\end{methoddesc} + +\subsection{The ElGamal and DSA algorithms} +For RSA, the \var{K} parameters are unused; if you like, you can just +pass empty strings. The ElGamal and DSA algorithms require a real +\var{K} value for technical reasons; see Schneier's book for a detailed +explanation of the respective algorithms. This presents a possible +hazard that can +inadvertently reveal the private key. Without going into the +mathematical details, the danger is as follows. \var{K} is never derived +or needed by others; theoretically, it can be thrown away once the +encryption or signing operation is performed. However, revealing +\var{K} for a given message would enable others to derive the secret key +data; worse, reusing the same value of \var{K} for two different +messages would also enable someone to derive the secret key data. An +adversary could intercept and store every message, and then try deriving +the secret key from each pair of messages. + +This places implementors on the horns of a dilemma. On the one hand, +you want to store the \var{K} values to avoid reusing one; on the other +hand, storing them means they could fall into the hands of an adversary. +One can randomly generate \var{K} values of a suitable length such as +128 or 144 bits, and then trust that the random number generator +probably won't produce a duplicate anytime soon. This is an +implementation decision that depends on the desired level of security +and the expected usage lifetime of a private key. I can't choose and +enforce one policy for this, so I've added the \var{K} parameter to the +\method{encrypt} and \method{sign} methods. You must choose \var{K} by +generating a string of random data; for ElGamal, when interpreted as a +big-endian number (with the most significant byte being the first byte +of the string), \var{K} must be relatively prime to \code{self.p-1}; any +size will do, but brute force searches would probably start with small +primes, so it's probably good to choose fairly large numbers. It might be +simplest to generate a prime number of a suitable length using the +\module{Crypto.Util.number} module. + + +\subsection{Security Notes for Public-key Algorithms} +Any of these algorithms can be trivially broken; for example, RSA can be +broken by factoring the modulus \emph{n} into its two prime factors. +This is easily done by the following code: + +\begin{verbatim} +for i in range(2, n): + if (n%i)==0: + print i, 'is a factor' + break +\end{verbatim} + +However, \emph{n} is usually a few hundred bits long, so this simple +program wouldn't find a solution before the universe comes to an end. +Smarter algorithms can factor numbers more quickly, but it's still +possible to choose keys so large that they can't be broken in a +reasonable amount of time. For ElGamal and DSA, discrete logarithms are +used instead of factoring, but the principle is the same. + +Safe key sizes depend on the current state of number theory and +computer technology. At the moment, one can roughly define three +levels of security: low-security commercial, high-security commercial, +and military-grade. For RSA, these three levels correspond roughly to +768, 1024, and 2048-bit keys. + + +%====================================================================== +\section{Crypto.Util: Odds and Ends} +This chapter contains all the modules that don't fit into any of the +other chapters. + +\subsection{Crypto.Util.number} + +This module contains various number-theoretic functions. + +\begin{funcdesc}{GCD}{x,y} +Return the greatest common divisor of \var{x} and \var{y}. +\end{funcdesc} + +\begin{funcdesc}{getPrime}{N, randfunc} +Return an \var{N}-bit random prime number, using random data obtained +from the function \var{randfunc}. \var{randfunc} must take a single +integer argument, and return a string of random data of the +corresponding length; the \method{get_bytes()} method of a +\class{RandomPool} object will serve the purpose nicely, as will the +\method{read()} method of an opened file such as \file{/dev/random}. +\end{funcdesc} + +\begin{funcdesc}{getRandomNumber}{N, randfunc} +Return an \var{N}-bit random number, using random data obtained from the +function \var{randfunc}. As usual, \var{randfunc} must take a single +integer argument and return a string of random data of the +corresponding length. +\end{funcdesc} + +\begin{funcdesc}{inverse}{u, v} +Return the inverse of \var{u} modulo \var{v}. +\end{funcdesc} + +\begin{funcdesc}{isPrime}{N} +Returns true if the number \var{N} is prime, as determined by a +Rabin-Miller test. +\end{funcdesc} + + +\subsection{Crypto.Util.randpool} + +For cryptographic purposes, ordinary random number generators are +frequently insufficient, because if some of their output is known, it +is frequently possible to derive the generator's future (or past) +output. Given the generator's state at some point in time, someone +could try to derive any keys generated using it. The solution is to +use strong encryption or hashing algorithms to generate successive +data; this makes breaking the generator as difficult as breaking the +algorithms used. + +Understanding the concept of \dfn{entropy} is important for using the +random number generator properly. In the sense we'll be using it, +entropy measures the amount of randomness; the usual unit is in bits. +So, a single random bit has an entropy of 1 bit; a random byte has an +entropy of 8 bits. Now consider a one-byte field in a database containing a +person's sex, represented as a single character \samp{M} or \samp{F}. +What's the entropy of this field? Since there are only two possible +values, it's not 8 bits, but one; if you were trying to guess the value, +you wouldn't have to bother trying \samp{Q} or \samp{@}. + +Now imagine running that single byte field through a hash function that +produces 128 bits of output. Is the entropy of the resulting hash value +128 bits? No, it's still just 1 bit. The entropy is a measure of how many +possible states of the data exist. For English +text, the entropy of a five-character string is not 40 bits; it's +somewhat less, because not all combinations would be seen. \samp{Guido} +is a possible string, as is \samp{In th}; \samp{zJwvb} is not. + +The relevance to random number generation? We want enough bits of +entropy to avoid making an attack on our generator possible. An +example: One computer system had a mechanism which generated nonsense +passwords for its users. This is a good idea, since it would prevent +people from choosing their own name or some other easily guessed string. +Unfortunately, the random number generator used only had 65536 states, +which meant only 65536 different passwords would ever be generated, and +it was easy to compute all the possible passwords and try them. The +entropy of the random passwords was far too low. By the same token, if +you generate an RSA key with only 32 bits of entropy available, there +are only about 4.2 billion keys you could have generated, and an +adversary could compute them all to find your private key. See \rfc{1750}, +"Randomness Recommendations for Security", for an interesting discussion +of the issues related to random number generation. + +The \module{randpool} module implements a strong random number generator +in the \class{RandomPool} class. The internal state consists of a string +of random data, which is returned as callers request it. The class +keeps track of the number of bits of entropy left, and provides a function to +add new random data; this data can be obtained in various ways, such as +by using the variance in a user's keystroke timings. + +\begin{classdesc}{RandomPool}{\optional{numbytes, cipher, hash} } +An object of the \code{RandomPool} class can be created without +parameters if desired. \var{numbytes} sets the number of bytes of +random data in the pool, and defaults to 160 (1280 bits). \var{hash} +can be a string containing the module name of the hash function to use +in stirring the random data, or a module object supporting the hashing +interface. The default action is to use SHA. + +The \var{cipher} argument is vestigial; it was removed from version +1.1 so RandomPool would work even in the limited exportable subset of +the code. I recommend passing \var{hash} using a keyword argument so +that someday I can safely delete the \var{cipher} argument + +\end{classdesc} + +\class{RandomPool} objects define the following variables and methods: + +\begin{methoddesc}{add_event}{time\optional{, string}} +Adds an event to the random pool. \var{time} should be set to the +current system time, measured at the highest resolution available. +\var{string} can be a string of data that will be XORed into the pool, +and can be used to increase the entropy of the pool. For example, if +you're encrypting a document, you might use the hash value of the +document; an adversary presumably won't have the plaintext of the +document, and thus won't be able to use this information to break the +generator. +\end{methoddesc} + +The return value is the value of \member{self.entropy} after the data has +been added. The function works in the following manner: the time +between successive calls to the \method{add_event()} method is determined, +and the entropy of the data is guessed; the larger the time between +calls, the better. The system time is then read and added to the pool, +along with the \var{string} parameter, if present. The hope is that the +low-order bits of the time are effectively random. In an application, +it is recommended that \method{add_event()} be called as frequently as +possible, with whatever random data can be found. + +\begin{memberdesc}{bits} +A constant integer value containing the number of bits of data in +the pool, equal to the \member{bytes} attribute multiplied by 8. +\end{memberdesc} + +\begin{memberdesc}{bytes} +A constant integer value containing the number of bytes of data in +the pool. +\end{memberdesc} + +\begin{memberdesc}{entropy} +An integer value containing the number of bits of entropy currently in +the pool. The value is incremented by the \method{add_event()} method, +and decreased by the \method{get_bytes()} method. +\end{memberdesc} + +\begin{methoddesc}{get_bytes}{num} +Returns a string containing \var{num} bytes of random data, and +decrements the amount of entropy available. It is not an error to +reduce the entropy to zero, or to call this function when the entropy +is zero. This simply means that, in theory, enough random information has been +extracted to derive the state of the generator. It is the caller's +responsibility to monitor the amount of entropy remaining and decide +whether it is sufficent for secure operation. +\end{methoddesc} + +\begin{methoddesc}{stir}{} +Scrambles the random pool using the previously chosen encryption and +hash function. An adversary may attempt to learn or alter the state +of the pool in order to affect its future output; this function +destroys the existing state of the pool in a non-reversible way. It +is recommended that \method{stir()} be called before and after using +the \class{RandomPool} object. Even better, several calls to +\method{stir()} can be interleaved with calls to \method{add_event()}. +\end{methoddesc} + +The \class{PersistentRandomPool} class is a subclass of \class{RandomPool} +that adds the capability to save and load the pool from a disk file. + +\begin{classdesc}{PersistentRandomPool}{filename, \optional{numbytes, cipher, hash}} +The path given in \var{filename} will be automatically opened, and an +existing random pool read; if no such file exists, the pool will be +initialized as usual. If omitted, the filename defaults to the empty +string, which will prevent it from being saved to a file. These +arguments are identical to those for the \class{RandomPool} +constructor. +\end{classdesc} + +\begin{methoddesc}{save}{} +Opens the file named by the \member{filename} attribute, and saves the +random data into the file using the \module{pickle} module. +\end{methoddesc} + +The \class{KeyboardRandomPool} class is a subclass of +\class{PersistentRandomPool} that provides a method to obtain random +data from the keyboard: + +\begin{methoddesc}{randomize}{} +(Unix systems only) Obtain random data from the keyboard. This works +by prompting the +user to hit keys at random, and then using the keystroke timings (and +also the actual keys pressed) to add entropy to the pool. This works +similarly to PGP's random pool mechanism. +\end{methoddesc} + + +\subsection{Crypto.Util.RFC1751} +The keys for private-key algorithms should be arbitrary binary data. +Many systems err by asking the user to enter a password, and then +using the password as the key. This limits the space of possible +keys, as each key byte is constrained within the range of possible +ASCII characters, 32-127, instead of the whole 0-255 range possible +with ASCII. Unfortunately, it's difficult for humans to remember 16 +or 32 hex digits. + +One solution is to request a lengthy passphrase from the user, and +then run it through a hash function such as SHA or MD5. Another +solution is discussed in RFC 1751, "A Convention for Human-Readable +128-bit Keys", by Daniel L. McDonald. Binary keys are transformed +into a list of short English words that should be easier to remember. +For example, the hex key EB33F77EE73D4053 is transformed to "TIDE ITCH +SLOW REIN RULE MOT". + +\begin{funcdesc}{key_to_english}{key} +Accepts a string of arbitrary data \var{key}, and returns a string +containing uppercase English words separated by spaces. \var{key}'s +length must be a multiple of 8. +\end{funcdesc} + +\begin{funcdesc}{english_to_key}{string} +Accepts \var{string} containing English words, and returns a string of +binary data representing the key. Words must be separated by +whitespace, and can be any mixture of uppercase and lowercase +characters. 6 words are required for 8 bytes of key data, so +the number of words in \var{string} must be a multiple of 6. +\end{funcdesc} + + +%====================================================================== +\section{Extending the Toolkit} + +Preserving the a common interface for cryptographic routines is a good +idea. This chapter explains how to write new modules for the Toolkit. + +The basic process is as follows: +\begin{enumerate} + +\item Add a new \file{.c} file containing an implementation of the new +algorithm. +This file must define 3 or 4 standard functions, +a few constants, and a C \code{struct} encapsulating the state variables required by the algorithm. + +\item Add the new algorithm to \file{setup.py}. + +\item Send a copy of the code to me, if you like; code for new +algorithms will be gratefully accepted. +\end{enumerate} + + +\subsection{Adding Hash Algorithms} + +The required constant definitions are as follows: + +\begin{verbatim} +#define MODULE_NAME MD2 /* Name of algorithm */ +#define DIGEST_SIZE 16 /* Size of resulting digest in bytes */ +\end{verbatim} + +The C structure must be named \ctype{hash_state}: + +\begin{verbatim} +typedef struct { + ... whatever state variables you need ... +} hash_state; +\end{verbatim} + +There are four functions that need to be written: to initialize the +algorithm's state, to hash a string into the algorithm's state, to get +a digest from the current state, and to copy a state. + +\begin{itemize} + \item \code{void hash_init(hash_state *self);} + \item \code{void hash_update(hash_state *self, unsigned char *buffer, int length);} + \item \code{PyObject *hash_digest(hash_state *self);} + \item \code{void hash_copy(hash_state *source, hash_state *dest);} +\end{itemize} + +Put \code{\#include "hash_template.c"} at the end of the file to +include the actual implementation of the module. + + +\subsection{Adding Block Encryption Algorithms} + +The required constant definitions are as follows: + +\begin{verbatim} +#define MODULE_NAME AES /* Name of algorithm */ +#define BLOCK_SIZE 16 /* Size of encryption block */ +#define KEY_SIZE 0 /* Size of key in bytes (0 if not fixed size) */ +\end{verbatim} + +The C structure must be named \ctype{block_state}: + +\begin{verbatim} +typedef struct { + ... whatever state variables you need ... +} block_state; +\end{verbatim} + +There are three functions that need to be written: to initialize the +algorithm's state, and to encrypt and decrypt a single block. + +\begin{itemize} + \item \code{void block_init(block_state *self, unsigned char *key, + int keylen);} + \item \code{void block_encrypt(block_state *self, unsigned char *in, + unsigned char *out);} + \item \code{void block_decrypt(block_state *self, unsigned char *in, + unsigned char *out);} +\end{itemize} + +Put \code{\#include "block_template.c"} at the end of the file to +include the actual implementation of the module. + + +\subsection{Adding Stream Encryption Algorithms} + +The required constant definitions are as follows: + +\begin{verbatim} +#define MODULE_NAME ARC4 /* Name of algorithm */ +#define BLOCK_SIZE 1 /* Will always be 1 for a stream cipher */ +#define KEY_SIZE 0 /* Size of key in bytes (0 if not fixed size) */ +\end{verbatim} + +The C structure must be named \ctype{stream_state}: + +\begin{verbatim} +typedef struct { + ... whatever state variables you need ... +} stream_state; +\end{verbatim} + +There are three functions that need to be written: to initialize the +algorithm's state, and to encrypt and decrypt a single block. + +\begin{itemize} + \item \code{void stream_init(stream_state *self, unsigned char *key, + int keylen);} + \item \code{void stream_encrypt(stream_state *self, unsigned char *block, + int length);} + \item \code{void stream_decrypt(stream_state *self, unsigned char *block, + int length);} +\end{itemize} + +Put \code{\#include "stream_template.c"} at the end of the file to +include the actual implementation of the module. + + +\end{document} diff --git a/src/Crypto/Hash/HMAC.py b/src/Crypto/Hash/HMAC.py new file mode 100644 index 00000000..eeb57823 --- /dev/null +++ b/src/Crypto/Hash/HMAC.py @@ -0,0 +1,108 @@ +"""HMAC (Keyed-Hashing for Message Authentication) Python module. + +Implements the HMAC algorithm as described by RFC 2104. + +This is just a copy of the Python 2.2 HMAC module, modified to work when +used on versions of Python before 2.2. +""" + +__revision__ = "$Id: HMAC.py,v 1.5 2002/07/25 17:19:02 z3p Exp $" + +import string + +def _strxor(s1, s2): + """Utility method. XOR the two strings s1 and s2 (must have same length). + """ + return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), s1, s2)) + +# The size of the digests returned by HMAC depends on the underlying +# hashing module used. +digest_size = None + +class HMAC: + """RFC2104 HMAC class. + + This supports the API for Cryptographic Hash Functions (PEP 247). + """ + + def __init__(self, key, msg = None, digestmod = None): + """Create a new HMAC object. + + key: key for the keyed hash object. + msg: Initial input for the hash, if provided. + digestmod: A module supporting PEP 247. Defaults to the md5 module. + """ + if digestmod == None: + import md5 + digestmod = md5 + + self.digestmod = digestmod + self.outer = digestmod.new() + self.inner = digestmod.new() + try: + self.digest_size = digestmod.digest_size + except AttributeError: + self.digest_size = len(self.outer.digest()) + + blocksize = 64 + ipad = "\x36" * blocksize + opad = "\x5C" * blocksize + + if len(key) > blocksize: + key = digestmod.new(key).digest() + + key = key + chr(0) * (blocksize - len(key)) + self.outer.update(_strxor(key, opad)) + self.inner.update(_strxor(key, ipad)) + if (msg): + self.update(msg) + +## def clear(self): +## raise NotImplementedError, "clear() method not available in HMAC." + + def update(self, msg): + """Update this hashing object with the string msg. + """ + self.inner.update(msg) + + def copy(self): + """Return a separate copy of this hashing object. + + An update to this copy won't affect the original object. + """ + other = HMAC("") + other.digestmod = self.digestmod + other.inner = self.inner.copy() + other.outer = self.outer.copy() + return other + + def digest(self): + """Return the hash value of this hashing object. + + This returns a string containing 8-bit data. The object is + not altered in any way by this function; you can continue + updating the object after calling this function. + """ + h = self.outer.copy() + h.update(self.inner.digest()) + return h.digest() + + def hexdigest(self): + """Like digest(), but returns a string of hexadecimal digits instead. + """ + return "".join([string.zfill(hex(ord(x))[2:], 2) + for x in tuple(self.digest())]) + +def new(key, msg = None, digestmod = None): + """Create a new hashing object and return it. + + key: The starting key for the hash. + msg: if available, will immediately be hashed into the object's starting + state. + + You can now feed arbitrary strings into the object using its update() + method, and can ask for the hash value at any time by calling its digest() + method. + """ + return HMAC(key, msg, digestmod) + diff --git a/src/Crypto/Hash/MD5.py b/src/Crypto/Hash/MD5.py new file mode 100644 index 00000000..b0eba394 --- /dev/null +++ b/src/Crypto/Hash/MD5.py @@ -0,0 +1,13 @@ + +# Just use the MD5 module from the Python standard library + +__revision__ = "$Id: MD5.py,v 1.4 2002/07/11 14:31:19 akuchling Exp $" + +from md5 import * + +import md5 +if hasattr(md5, 'digestsize'): + digest_size = digestsize + del digestsize +del md5 + diff --git a/src/Crypto/Hash/SHA.py b/src/Crypto/Hash/SHA.py new file mode 100644 index 00000000..ea3c6a34 --- /dev/null +++ b/src/Crypto/Hash/SHA.py @@ -0,0 +1,11 @@ + +# Just use the SHA module from the Python standard library + +__revision__ = "$Id: SHA.py,v 1.4 2002/07/11 14:31:19 akuchling Exp $" + +from sha import * +import sha +if hasattr(sha, 'digestsize'): + digest_size = digestsize + del digestsize +del sha diff --git a/src/Crypto/Hash/__init__.py b/src/Crypto/Hash/__init__.py new file mode 100644 index 00000000..30cbe1b6 --- /dev/null +++ b/src/Crypto/Hash/__init__.py @@ -0,0 +1,24 @@ +"""Hashing algorithms + +Hash functions take arbitrary strings as input, and produce an output +of fixed size that is dependent on the input; it should never be +possible to derive the input data given only the hash function's +output. Hash functions can be used simply as a checksum, or, in +association with a public-key algorithm, can be used to implement +digital signatures. + +The hashing modules here all support the interface described in PEP +247, "API for Cryptographic Hash Functions". + +Submodules: +Crypto.Hash.HMAC RFC 2104: Keyed-Hashing for Message Authentication +Crypto.Hash.MD2 +Crypto.Hash.MD4 +Crypto.Hash.MD5 +Crypto.Hash.RIPEMD +Crypto.Hash.SHA +""" + +__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'SHA', 'SHA256'] +__revision__ = "$Id: __init__.py,v 1.6 2003/12/19 14:24:25 akuchling Exp $" + diff --git a/src/Crypto/LICENSE b/src/Crypto/LICENSE new file mode 100644 index 00000000..ad3ae419 --- /dev/null +++ b/src/Crypto/LICENSE @@ -0,0 +1,15 @@ +=================================================================== +Distribute and use freely; there are no restrictions on further +dissemination and usage except those imposed by the laws of your +country of residence. This software is provided "as is" without +warranty of fitness for use or suitability for any purpose, express +or implied. Use at your own risk or not at all. +=================================================================== + +Incorporating the code into commercial products is permitted; you do +not have to make source available or contribute your changes back +(though that would be nice). + +--amk (www.amk.ca) + + diff --git a/src/Crypto/MANIFEST b/src/Crypto/MANIFEST new file mode 100644 index 00000000..d19134e2 --- /dev/null +++ b/src/Crypto/MANIFEST @@ -0,0 +1,63 @@ +ACKS +ChangeLog +Cipher/__init__.py +Doc/pycrypt.tex +Hash/HMAC.py +Hash/MD5.py +Hash/SHA.py +Hash/__init__.py +LICENSE +MANIFEST +Protocol/AllOrNothing.py +Protocol/Chaffing.py +Protocol/__init__.py +PublicKey/DSA.py +PublicKey/ElGamal.py +PublicKey/RSA.py +PublicKey/__init__.py +PublicKey/pubkey.py +PublicKey/qNEW.py +PublicKey/test/rsa_speed.py +README +TODO +Util/RFC1751.py +Util/__init__.py +Util/number.py +Util/randpool.py +Util/test.py +Util/test/prime_speed.py +__init__.py +setup.py +src/AES.c +src/ARC2.c +src/ARC4.c +src/Blowfish.c +src/CAST.c +src/DES.c +src/DES3.c +src/IDEA.c +src/MD2.c +src/MD4.c +src/RC5.c +src/RIPEMD.c +src/SHA256.c +src/XOR.c +src/block_template.c +src/cast5.c +src/hash_template.c +src/stream_template.c +src/winrand.c +src/_dsa.c +src/_fastmath.c +src/_rsa.c +test.py +test/template +test/test_allornothing.py +test/test_chaffing.py +test/test_hashes.py +test/test_hmac.py +test/test_number.py +test/test_publickey.py +test/test_randpool.py +test/test_rfc1751.py +test/testdata.py diff --git a/src/Crypto/PKG-INFO b/src/Crypto/PKG-INFO new file mode 100644 index 00000000..764da08a --- /dev/null +++ b/src/Crypto/PKG-INFO @@ -0,0 +1,18 @@ +Metadata-Version: 1.0 +Name: pycrypto +Version: 2.0.1 +Summary: Cryptographic modules for Python. +Home-page: http://www.amk.ca/python/code/crypto +Author: A.M. Kuchling +Author-email: amk@amk.ca +License: UNKNOWN +Download-URL: http://www.amk.ca/files/python/crypto/pycrypto-2.0.1.tar.gz +Description: UNKNOWN +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: License :: Public Domain +Classifier: Intended Audience :: Developers +Classifier: Operating System :: Unix +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Topic :: Security :: Cryptography diff --git a/src/Crypto/Protocol/AllOrNothing.py b/src/Crypto/Protocol/AllOrNothing.py new file mode 100644 index 00000000..5fc600d9 --- /dev/null +++ b/src/Crypto/Protocol/AllOrNothing.py @@ -0,0 +1,295 @@ +"""This file implements all-or-nothing package transformations. + +An all-or-nothing package transformation is one in which some text is +transformed into message blocks, such that all blocks must be obtained before +the reverse transformation can be applied. Thus, if any blocks are corrupted +or lost, the original message cannot be reproduced. + +An all-or-nothing package transformation is not encryption, although a block +cipher algorithm is used. The encryption key is randomly generated and is +extractable from the message blocks. + +This class implements the All-Or-Nothing package transformation algorithm +described in: + +Ronald L. Rivest. "All-Or-Nothing Encryption and The Package Transform" +http://theory.lcs.mit.edu/~rivest/fusion.pdf + +""" + +__revision__ = "$Id: AllOrNothing.py,v 1.8 2003/02/28 15:23:20 akuchling Exp $" + +import operator +import string +from allmydata.Crypto.Util.number import bytes_to_long, long_to_bytes + + + +class AllOrNothing: + """Class implementing the All-or-Nothing package transform. + + Methods for subclassing: + + _inventkey(key_size): + Returns a randomly generated key. Subclasses can use this to + implement better random key generating algorithms. The default + algorithm is probably not very cryptographically secure. + + """ + + def __init__(self, ciphermodule, mode=None, IV=None): + """AllOrNothing(ciphermodule, mode=None, IV=None) + + ciphermodule is a module implementing the cipher algorithm to + use. It must provide the PEP272 interface. + + Note that the encryption key is randomly generated + automatically when needed. Optional arguments mode and IV are + passed directly through to the ciphermodule.new() method; they + are the feedback mode and initialization vector to use. All + three arguments must be the same for the object used to create + the digest, and to undigest'ify the message blocks. + """ + + self.__ciphermodule = ciphermodule + self.__mode = mode + self.__IV = IV + self.__key_size = ciphermodule.key_size + if self.__key_size == 0: + self.__key_size = 16 + + __K0digit = chr(0x69) + + def digest(self, text): + """digest(text:string) : [string] + + Perform the All-or-Nothing package transform on the given + string. Output is a list of message blocks describing the + transformed text, where each block is a string of bit length equal + to the ciphermodule's block_size. + """ + + # generate a random session key and K0, the key used to encrypt the + # hash blocks. Rivest calls this a fixed, publically-known encryption + # key, but says nothing about the security implications of this key or + # how to choose it. + key = self._inventkey(self.__key_size) + K0 = self.__K0digit * self.__key_size + + # we need two cipher objects here, one that is used to encrypt the + # message blocks and one that is used to encrypt the hashes. The + # former uses the randomly generated key, while the latter uses the + # well-known key. + mcipher = self.__newcipher(key) + hcipher = self.__newcipher(K0) + + # Pad the text so that its length is a multiple of the cipher's + # block_size. Pad with trailing spaces, which will be eliminated in + # the undigest() step. + block_size = self.__ciphermodule.block_size + padbytes = block_size - (len(text) % block_size) + text = text + ' ' * padbytes + + # Run through the algorithm: + # s: number of message blocks (size of text / block_size) + # input sequence: m1, m2, ... ms + # random key K' (`key' in the code) + # Compute output sequence: m'1, m'2, ... m's' for s' = s + 1 + # Let m'i = mi ^ E(K', i) for i = 1, 2, 3, ..., s + # Let m's' = K' ^ h1 ^ h2 ^ ... hs + # where hi = E(K0, m'i ^ i) for i = 1, 2, ... s + # + # The one complication I add is that the last message block is hard + # coded to the number of padbytes added, so that these can be stripped + # during the undigest() step + s = len(text) / block_size + blocks = [] + hashes = [] + for i in range(1, s+1): + start = (i-1) * block_size + end = start + block_size + mi = text[start:end] + assert len(mi) == block_size + cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) + mticki = bytes_to_long(mi) ^ bytes_to_long(cipherblock) + blocks.append(mticki) + # calculate the hash block for this block + hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size)) + hashes.append(bytes_to_long(hi)) + + # Add the padbytes length as a message block + i = i + 1 + cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) + mticki = padbytes ^ bytes_to_long(cipherblock) + blocks.append(mticki) + + # calculate this block's hash + hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size)) + hashes.append(bytes_to_long(hi)) + + # Now calculate the last message block of the sequence 1..s'. This + # will contain the random session key XOR'd with all the hash blocks, + # so that for undigest(), once all the hash blocks are calculated, the + # session key can be trivially extracted. Calculating all the hash + # blocks requires that all the message blocks be received, thus the + # All-or-Nothing algorithm succeeds. + mtick_stick = bytes_to_long(key) ^ reduce(operator.xor, hashes) + blocks.append(mtick_stick) + + # we convert the blocks to strings since in Python, byte sequences are + # always represented as strings. This is more consistent with the + # model that encryption and hash algorithms always operate on strings. + return map(long_to_bytes, blocks) + + + def undigest(self, blocks): + """undigest(blocks : [string]) : string + + Perform the reverse package transformation on a list of message + blocks. Note that the ciphermodule used for both transformations + must be the same. blocks is a list of strings of bit length + equal to the ciphermodule's block_size. + """ + + # better have at least 2 blocks, for the padbytes package and the hash + # block accumulator + if len(blocks) < 2: + raise ValueError, "List must be at least length 2." + + # blocks is a list of strings. We need to deal with them as long + # integers + blocks = map(bytes_to_long, blocks) + + # Calculate the well-known key, to which the hash blocks are + # encrypted, and create the hash cipher. + K0 = self.__K0digit * self.__key_size + hcipher = self.__newcipher(K0) + + # Since we have all the blocks (or this method would have been called + # prematurely), we can calcualte all the hash blocks. + hashes = [] + for i in range(1, len(blocks)): + mticki = blocks[i-1] ^ i + hi = hcipher.encrypt(long_to_bytes(mticki)) + hashes.append(bytes_to_long(hi)) + + # now we can calculate K' (key). remember the last block contains + # m's' which we don't include here + key = blocks[-1] ^ reduce(operator.xor, hashes) + + # and now we can create the cipher object + mcipher = self.__newcipher(long_to_bytes(key)) + block_size = self.__ciphermodule.block_size + + # And we can now decode the original message blocks + parts = [] + for i in range(1, len(blocks)): + cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) + mi = blocks[i-1] ^ bytes_to_long(cipherblock) + parts.append(mi) + + # The last message block contains the number of pad bytes appended to + # the original text string, such that its length was an even multiple + # of the cipher's block_size. This number should be small enough that + # the conversion from long integer to integer should never overflow + padbytes = int(parts[-1]) + text = string.join(map(long_to_bytes, parts[:-1]), '') + return text[:-padbytes] + + def _inventkey(self, key_size): + # TBD: Not a very secure algorithm. Eventually, I'd like to use JHy's + # kernelrand module + import time + from allmydata.Crypto.Util import randpool + # TBD: key_size * 2 to work around possible bug in RandomPool? + pool = randpool.RandomPool(key_size * 2) + while key_size > pool.entropy: + pool.add_event() + + # we now have enough entropy in the pool to get a key_size'd key + return pool.get_bytes(key_size) + + def __newcipher(self, key): + if self.__mode is None and self.__IV is None: + return self.__ciphermodule.new(key) + elif self.__IV is None: + return self.__ciphermodule.new(key, self.__mode) + else: + return self.__ciphermodule.new(key, self.__mode, self.__IV) + + + +if __name__ == '__main__': + import sys + import getopt + import base64 + + usagemsg = '''\ +Test module usage: %(program)s [-c cipher] [-l] [-h] + +Where: + --cipher module + -c module + Cipher module to use. Default: %(ciphermodule)s + + --aslong + -l + Print the encoded message blocks as long integers instead of base64 + encoded strings + + --help + -h + Print this help message +''' + + ciphermodule = 'AES' + aslong = 0 + + def usage(code, msg=None): + if msg: + print msg + print usagemsg % {'program': sys.argv[0], + 'ciphermodule': ciphermodule} + sys.exit(code) + + try: + opts, args = getopt.getopt(sys.argv[1:], + 'c:l', ['cipher=', 'aslong']) + except getopt.error, msg: + usage(1, msg) + + if args: + usage(1, 'Too many arguments') + + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-c', '--cipher'): + ciphermodule = arg + elif opt in ('-l', '--aslong'): + aslong = 1 + + # ugly hack to force __import__ to give us the end-path module + module = __import__('allmydata.Crypto.Cipher.'+ciphermodule, None, None, ['new']) + + a = AllOrNothing(module) + print 'Original text:\n==========' + print __doc__ + print '==========' + msgblocks = a.digest(__doc__) + print 'message blocks:' + for i, blk in map(None, range(len(msgblocks)), msgblocks): + # base64 adds a trailing newline + print ' %3d' % i, + if aslong: + print bytes_to_long(blk) + else: + print base64.encodestring(blk)[:-1] + # + # get a new undigest-only object so there's no leakage + b = AllOrNothing(module) + text = b.undigest(msgblocks) + if text == __doc__: + print 'They match!' + else: + print 'They differ!' diff --git a/src/Crypto/Protocol/Chaffing.py b/src/Crypto/Protocol/Chaffing.py new file mode 100644 index 00000000..36215f55 --- /dev/null +++ b/src/Crypto/Protocol/Chaffing.py @@ -0,0 +1,229 @@ +"""This file implements the chaffing algorithm. + +Winnowing and chaffing is a technique for enhancing privacy without requiring +strong encryption. In short, the technique takes a set of authenticated +message blocks (the wheat) and adds a number of chaff blocks which have +randomly chosen data and MAC fields. This means that to an adversary, the +chaff blocks look as valid as the wheat blocks, and so the authentication +would have to be performed on every block. By tailoring the number of chaff +blocks added to the message, the sender can make breaking the message +computationally infeasible. There are many other interesting properties of +the winnow/chaff technique. + +For example, say Alice is sending a message to Bob. She packetizes the +message and performs an all-or-nothing transformation on the packets. Then +she authenticates each packet with a message authentication code (MAC). The +MAC is a hash of the data packet, and there is a secret key which she must +share with Bob (key distribution is an exercise left to the reader). She then +adds a serial number to each packet, and sends the packets to Bob. + +Bob receives the packets, and using the shared secret authentication key, +authenticates the MACs for each packet. Those packets that have bad MACs are +simply discarded. The remainder are sorted by serial number, and passed +through the reverse all-or-nothing transform. The transform means that an +eavesdropper (say Eve) must acquire all the packets before any of the data can +be read. If even one packet is missing, the data is useless. + +There's one twist: by adding chaff packets, Alice and Bob can make Eve's job +much harder, since Eve now has to break the shared secret key, or try every +combination of wheat and chaff packet to read any of the message. The cool +thing is that Bob doesn't need to add any additional code; the chaff packets +are already filtered out because their MACs don't match (in all likelihood -- +since the data and MACs for the chaff packets are randomly chosen it is +possible, but very unlikely that a chaff MAC will match the chaff data). And +Alice need not even be the party adding the chaff! She could be completely +unaware that a third party, say Charles, is adding chaff packets to her +messages as they are transmitted. + +For more information on winnowing and chaffing see this paper: + +Ronald L. Rivest, "Chaffing and Winnowing: Confidentiality without Encryption" +http://theory.lcs.mit.edu/~rivest/chaffing.txt + +""" + +__revision__ = "$Id: Chaffing.py,v 1.7 2003/02/28 15:23:21 akuchling Exp $" + +from allmydata.Crypto.Util.number import bytes_to_long + +class Chaff: + """Class implementing the chaff adding algorithm. + + Methods for subclasses: + + _randnum(size): + Returns a randomly generated number with a byte-length equal + to size. Subclasses can use this to implement better random + data and MAC generating algorithms. The default algorithm is + probably not very cryptographically secure. It is most + important that the chaff data does not contain any patterns + that can be used to discern it from wheat data without running + the MAC. + + """ + + def __init__(self, factor=1.0, blocksper=1): + """Chaff(factor:float, blocksper:int) + + factor is the number of message blocks to add chaff to, + expressed as a percentage between 0.0 and 1.0. blocksper is + the number of chaff blocks to include for each block being + chaffed. Thus the defaults add one chaff block to every + message block. By changing the defaults, you can adjust how + computationally difficult it could be for an adversary to + brute-force crack the message. The difficulty is expressed + as: + + pow(blocksper, int(factor * number-of-blocks)) + + For ease of implementation, when factor < 1.0, only the first + int(factor*number-of-blocks) message blocks are chaffed. + """ + + if not (0.0<=factor<=1.0): + raise ValueError, "'factor' must be between 0.0 and 1.0" + if blocksper < 0: + raise ValueError, "'blocksper' must be zero or more" + + self.__factor = factor + self.__blocksper = blocksper + + + def chaff(self, blocks): + """chaff( [(serial-number:int, data:string, MAC:string)] ) + : [(int, string, string)] + + Add chaff to message blocks. blocks is a list of 3-tuples of the + form (serial-number, data, MAC). + + Chaff is created by choosing a random number of the same + byte-length as data, and another random number of the same + byte-length as MAC. The message block's serial number is + placed on the chaff block and all the packet's chaff blocks + are randomly interspersed with the single wheat block. This + method then returns a list of 3-tuples of the same form. + Chaffed blocks will contain multiple instances of 3-tuples + with the same serial number, but the only way to figure out + which blocks are wheat and which are chaff is to perform the + MAC hash and compare values. + """ + + chaffedblocks = [] + + # count is the number of blocks to add chaff to. blocksper is the + # number of chaff blocks to add per message block that is being + # chaffed. + count = len(blocks) * self.__factor + blocksper = range(self.__blocksper) + for i, wheat in map(None, range(len(blocks)), blocks): + # it shouldn't matter which of the n blocks we add chaff to, so for + # ease of implementation, we'll just add them to the first count + # blocks + if i < count: + serial, data, mac = wheat + datasize = len(data) + macsize = len(mac) + addwheat = 1 + # add chaff to this block + for j in blocksper: + import sys + chaffdata = self._randnum(datasize) + chaffmac = self._randnum(macsize) + chaff = (serial, chaffdata, chaffmac) + # mix up the order, if the 5th bit is on then put the + # wheat on the list + if addwheat and bytes_to_long(self._randnum(16)) & 0x40: + chaffedblocks.append(wheat) + addwheat = 0 + chaffedblocks.append(chaff) + if addwheat: + chaffedblocks.append(wheat) + else: + # just add the wheat + chaffedblocks.append(wheat) + return chaffedblocks + + def _randnum(self, size): + # TBD: Not a very secure algorithm. + # TBD: size * 2 to work around possible bug in RandomPool + from allmydata.Crypto.Util import randpool + import time + pool = randpool.RandomPool(size * 2) + while size > pool.entropy: + pass + + # we now have enough entropy in the pool to get size bytes of random + # data... well, probably + return pool.get_bytes(size) + + + +if __name__ == '__main__': + text = """\ +We hold these truths to be self-evident, that all men are created equal, that +they are endowed by their Creator with certain unalienable Rights, that among +these are Life, Liberty, and the pursuit of Happiness. That to secure these +rights, Governments are instituted among Men, deriving their just powers from +the consent of the governed. That whenever any Form of Government becomes +destructive of these ends, it is the Right of the People to alter or to +abolish it, and to institute new Government, laying its foundation on such +principles and organizing its powers in such form, as to them shall seem most +likely to effect their Safety and Happiness. +""" + print 'Original text:\n==========' + print text + print '==========' + + # first transform the text into packets + blocks = [] ; size = 40 + for i in range(0, len(text), size): + blocks.append( text[i:i+size] ) + + # now get MACs for all the text blocks. The key is obvious... + print 'Calculating MACs...' + from allmydata.Crypto.Hash import HMAC, SHA + key = 'Jefferson' + macs = [HMAC.new(key, block, digestmod=SHA).digest() + for block in blocks] + + assert len(blocks) == len(macs) + + # put these into a form acceptable as input to the chaffing procedure + source = [] + m = map(None, range(len(blocks)), blocks, macs) + print m + for i, data, mac in m: + source.append((i, data, mac)) + + # now chaff these + print 'Adding chaff...' + c = Chaff(factor=0.5, blocksper=2) + chaffed = c.chaff(source) + + from base64 import encodestring + + # print the chaffed message blocks. meanwhile, separate the wheat from + # the chaff + + wheat = [] + print 'chaffed message blocks:' + for i, data, mac in chaffed: + # do the authentication + h = HMAC.new(key, data, digestmod=SHA) + pmac = h.digest() + if pmac == mac: + tag = '-->' + wheat.append(data) + else: + tag = ' ' + # base64 adds a trailing newline + print tag, '%3d' % i, \ + repr(data), encodestring(mac)[:-1] + + # now decode the message packets and check it against the original text + print 'Undigesting wheat...' + newtext = "".join(wheat) + if newtext == text: + print 'They match!' + else: + print 'They differ!' diff --git a/src/Crypto/Protocol/__init__.py b/src/Crypto/Protocol/__init__.py new file mode 100644 index 00000000..a6d68bcf --- /dev/null +++ b/src/Crypto/Protocol/__init__.py @@ -0,0 +1,17 @@ + +"""Cryptographic protocols + +Implements various cryptographic protocols. (Don't expect to find +network protocols here.) + +Crypto.Protocol.AllOrNothing Transforms a message into a set of message + blocks, such that the blocks can be + recombined to get the message back. + +Crypto.Protocol.Chaffing Takes a set of authenticated message blocks + (the wheat) and adds a number of + randomly generated blocks (the chaff). +""" + +__all__ = ['AllOrNothing', 'Chaffing'] +__revision__ = "$Id: __init__.py,v 1.4 2003/02/28 15:23:21 akuchling Exp $" diff --git a/src/Crypto/PublicKey/DSA.py b/src/Crypto/PublicKey/DSA.py new file mode 100644 index 00000000..685842ea --- /dev/null +++ b/src/Crypto/PublicKey/DSA.py @@ -0,0 +1,238 @@ + +# +# DSA.py : Digital Signature Algorithm +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: DSA.py,v 1.16 2004/05/06 12:52:54 akuchling Exp $" + +from allmydata.Crypto.PublicKey.pubkey import * +from allmydata.Crypto.Util import number +from allmydata.Crypto.Util.number import bytes_to_long, long_to_bytes +from allmydata.Crypto.Hash import SHA + +try: + from allmydata.Crypto.PublicKey import _fastmath +except ImportError: + _fastmath = None + +class error (Exception): + pass + +def generateQ(randfunc): + S=randfunc(20) + hash1=SHA.new(S).digest() + hash2=SHA.new(long_to_bytes(bytes_to_long(S)+1)).digest() + q = bignum(0) + for i in range(0,20): + c=ord(hash1[i])^ord(hash2[i]) + if i==0: + c=c | 128 + if i==19: + c= c | 1 + q=q*256+c + while (not isPrime(q)): + q=q+2 + if pow(2,159L) < q < pow(2,160L): + return S, q + raise error, 'Bad q value generated' + +def generate(bits, randfunc, progress_func=None): + """generate(bits:int, randfunc:callable, progress_func:callable) + + Generate a DSA key of length 'bits', using 'randfunc' to get + random data and 'progress_func', if present, to display + the progress of the key generation. + """ + + if bits<160: + raise error, 'Key length <160 bits' + obj=DSAobj() + # Generate string S and prime q + if progress_func: + progress_func('p,q\n') + while (1): + S, obj.q = generateQ(randfunc) + n=(bits-1)/160 + C, N, V = 0, 2, {} + b=(obj.q >> 5) & 15 + powb=pow(bignum(2), b) + powL1=pow(bignum(2), bits-1) + while C<4096: + for k in range(0, n+1): + V[k]=bytes_to_long(SHA.new(S+str(N)+str(k)).digest()) + W=V[n] % powb + for k in range(n-1, -1, -1): + W=(W<<160L)+V[k] + X=W+powL1 + p=X-(X%(2*obj.q)-1) + if powL1<=p and isPrime(p): + break + C, N = C+1, N+n+1 + if C<4096: + break + if progress_func: + progress_func('4096 multiples failed\n') + + obj.p = p + power=(p-1)/obj.q + if progress_func: + progress_func('h,g\n') + while (1): + h=bytes_to_long(randfunc(bits)) % (p-1) + g=pow(h, power, p) + if 11: + break + obj.g=g + if progress_func: + progress_func('x,y\n') + while (1): + x=bytes_to_long(randfunc(20)) + if 0 < x < obj.q: + break + obj.x, obj.y = x, pow(g, x, p) + return obj + +def construct(tuple): + """construct(tuple:(long,long,long,long)|(long,long,long,long,long)):DSAobj + Construct a DSA object from a 4- or 5-tuple of numbers. + """ + obj=DSAobj() + if len(tuple) not in [4,5]: + raise error, 'argument for construct() wrong length' + for i in range(len(tuple)): + field = obj.keydata[i] + setattr(obj, field, tuple[i]) + return obj + +class DSAobj(pubkey): + keydata=['y', 'g', 'p', 'q', 'x'] + + def _encrypt(self, s, Kstr): + raise error, 'DSA algorithm cannot encrypt data' + + def _decrypt(self, s): + raise error, 'DSA algorithm cannot decrypt data' + + def _sign(self, M, K): + if (K<2 or self.q<=K): + raise error, 'K is not between 2 and q' + r=pow(self.g, K, self.p) % self.q + s=(inverse(K, self.q)*(M+self.x*r)) % self.q + return (r,s) + + def _verify(self, M, sig): + r, s = sig + if r<=0 or r>=self.q or s<=0 or s>=self.q: + return 0 + w=inverse(s, self.q) + u1, u2 = (M*w) % self.q, (r*w) % self.q + v1 = pow(self.g, u1, self.p) + v2 = pow(self.y, u2, self.p) + v = ((v1*v2) % self.p) + v = v % self.q + if v==r: + return 1 + return 0 + + def size(self): + "Return the maximum number of bits that can be handled by this key." + return number.size(self.p) - 1 + + def has_private(self): + """Return a Boolean denoting whether the object contains + private components.""" + if hasattr(self, 'x'): + return 1 + else: + return 0 + + def can_sign(self): + """Return a Boolean value recording whether this algorithm can generate signatures.""" + return 1 + + def can_encrypt(self): + """Return a Boolean value recording whether this algorithm can encrypt data.""" + return 0 + + def publickey(self): + """Return a new key object containing only the public information.""" + return construct((self.y, self.g, self.p, self.q)) + +object=DSAobj + +generate_py = generate +construct_py = construct + +class DSAobj_c(pubkey): + keydata = ['y', 'g', 'p', 'q', 'x'] + + def __init__(self, key): + self.key = key + + def __getattr__(self, attr): + if attr in self.keydata: + return getattr(self.key, attr) + else: + if self.__dict__.has_key(attr): + self.__dict__[attr] + else: + raise AttributeError, '%s instance has no attribute %s' % (self.__class__, attr) + + def __getstate__(self): + d = {} + for k in self.keydata: + if hasattr(self.key, k): + d[k]=getattr(self.key, k) + return d + + def __setstate__(self, state): + y,g,p,q = state['y'], state['g'], state['p'], state['q'] + if not state.has_key('x'): + self.key = _fastmath.dsa_construct(y,g,p,q) + else: + x = state['x'] + self.key = _fastmath.dsa_construct(y,g,p,q,x) + + def _sign(self, M, K): + return self.key._sign(M, K) + + def _verify(self, M, (r, s)): + return self.key._verify(M, r, s) + + def size(self): + return self.key.size() + + def has_private(self): + return self.key.has_private() + + def publickey(self): + return construct_c((self.key.y, self.key.g, self.key.p, self.key.q)) + + def can_sign(self): + return 1 + + def can_encrypt(self): + return 0 + +def generate_c(bits, randfunc, progress_func=None): + obj = generate_py(bits, randfunc, progress_func) + y,g,p,q,x = obj.y, obj.g, obj.p, obj.q, obj.x + return construct_c((y,g,p,q,x)) + +def construct_c(tuple): + key = apply(_fastmath.dsa_construct, tuple) + return DSAobj_c(key) + +if _fastmath: + #print "using C version of DSA" + generate = generate_c + construct = construct_c + error = _fastmath.error diff --git a/src/Crypto/PublicKey/ElGamal.py b/src/Crypto/PublicKey/ElGamal.py new file mode 100644 index 00000000..c919744b --- /dev/null +++ b/src/Crypto/PublicKey/ElGamal.py @@ -0,0 +1,132 @@ +# +# ElGamal.py : ElGamal encryption/decryption and signatures +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: ElGamal.py,v 1.9 2003/04/04 19:44:26 akuchling Exp $" + +from allmydata.Crypto.PublicKey.pubkey import * +from allmydata.Crypto.Util import number + +class error (Exception): + pass + +# Generate an ElGamal key with N bits +def generate(bits, randfunc, progress_func=None): + """generate(bits:int, randfunc:callable, progress_func:callable) + + Generate an ElGamal key of length 'bits', using 'randfunc' to get + random data and 'progress_func', if present, to display + the progress of the key generation. + """ + obj=ElGamalobj() + # Generate prime p + if progress_func: + progress_func('p\n') + obj.p=bignum(getPrime(bits, randfunc)) + # Generate random number g + if progress_func: + progress_func('g\n') + size=bits-1-(ord(randfunc(1)) & 63) # g will be from 1--64 bits smaller than p + if size<1: + size=bits-1 + while (1): + obj.g=bignum(getPrime(size, randfunc)) + if obj.g < obj.p: + break + size=(size+1) % bits + if size==0: + size=4 + # Generate random number x + if progress_func: + progress_func('x\n') + while (1): + size=bits-1-ord(randfunc(1)) # x will be from 1 to 256 bits smaller than p + if size>2: + break + while (1): + obj.x=bignum(getPrime(size, randfunc)) + if obj.x < obj.p: + break + size = (size+1) % bits + if size==0: + size=4 + if progress_func: + progress_func('y\n') + obj.y = pow(obj.g, obj.x, obj.p) + return obj + +def construct(tuple): + """construct(tuple:(long,long,long,long)|(long,long,long,long,long))) + : ElGamalobj + Construct an ElGamal key from a 3- or 4-tuple of numbers. + """ + + obj=ElGamalobj() + if len(tuple) not in [3,4]: + raise error, 'argument for construct() wrong length' + for i in range(len(tuple)): + field = obj.keydata[i] + setattr(obj, field, tuple[i]) + return obj + +class ElGamalobj(pubkey): + keydata=['p', 'g', 'y', 'x'] + + def _encrypt(self, M, K): + a=pow(self.g, K, self.p) + b=( M*pow(self.y, K, self.p) ) % self.p + return ( a,b ) + + def _decrypt(self, M): + if (not hasattr(self, 'x')): + raise error, 'Private key not available in this object' + ax=pow(M[0], self.x, self.p) + plaintext=(M[1] * inverse(ax, self.p ) ) % self.p + return plaintext + + def _sign(self, M, K): + if (not hasattr(self, 'x')): + raise error, 'Private key not available in this object' + p1=self.p-1 + if (GCD(K, p1)!=1): + raise error, 'Bad K value: GCD(K,p-1)!=1' + a=pow(self.g, K, self.p) + t=(M-self.x*a) % p1 + while t<0: t=t+p1 + b=(t*inverse(K, p1)) % p1 + return (a, b) + + def _verify(self, M, sig): + v1=pow(self.y, sig[0], self.p) + v1=(v1*pow(sig[0], sig[1], self.p)) % self.p + v2=pow(self.g, M, self.p) + if v1==v2: + return 1 + return 0 + + def size(self): + "Return the maximum number of bits that can be handled by this key." + return number.size(self.p) - 1 + + def has_private(self): + """Return a Boolean denoting whether the object contains + private components.""" + if hasattr(self, 'x'): + return 1 + else: + return 0 + + def publickey(self): + """Return a new key object containing only the public information.""" + return construct((self.p, self.g, self.y)) + + +object=ElGamalobj diff --git a/src/Crypto/PublicKey/RSA.py b/src/Crypto/PublicKey/RSA.py new file mode 100644 index 00000000..e43242f6 --- /dev/null +++ b/src/Crypto/PublicKey/RSA.py @@ -0,0 +1,256 @@ +# +# RSA.py : RSA encryption/decryption +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: RSA.py,v 1.20 2004/05/06 12:52:54 akuchling Exp $" + +from allmydata.Crypto.PublicKey import pubkey +from allmydata.Crypto.Util import number + +try: + from allmydata.Crypto.PublicKey import _fastmath +except ImportError: + _fastmath = None + +class error (Exception): + pass + +def generate(bits, randfunc, progress_func=None): + """generate(bits:int, randfunc:callable, progress_func:callable) + + Generate an RSA key of length 'bits', using 'randfunc' to get + random data and 'progress_func', if present, to display + the progress of the key generation. + """ + obj=RSAobj() + + # Generate the prime factors of n + if progress_func: + progress_func('p,q\n') + p = q = 1L + while number.size(p*q) < bits: + p = pubkey.getPrime(bits/2, randfunc) + q = pubkey.getPrime(bits/2, randfunc) + + # p shall be smaller than q (for calc of u) + if p > q: + (p, q)=(q, p) + obj.p = p + obj.q = q + + if progress_func: + progress_func('u\n') + obj.u = pubkey.inverse(obj.p, obj.q) + obj.n = obj.p*obj.q + + obj.e = 65537L + if progress_func: + progress_func('d\n') + obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1)) + + assert bits <= 1+obj.size(), "Generated key is too small" + + return obj + +def construct(tuple): + """construct(tuple:(long,) : RSAobj + Construct an RSA object from a 2-, 3-, 5-, or 6-tuple of numbers. + """ + + obj=RSAobj() + if len(tuple) not in [2,3,5,6]: + raise error, 'argument for construct() wrong length' + for i in range(len(tuple)): + field = obj.keydata[i] + setattr(obj, field, tuple[i]) + if len(tuple) >= 5: + # Ensure p is smaller than q + if obj.p>obj.q: + (obj.p, obj.q)=(obj.q, obj.p) + + if len(tuple) == 5: + # u not supplied, so we're going to have to compute it. + obj.u=pubkey.inverse(obj.p, obj.q) + + return obj + +class RSAobj(pubkey.pubkey): + keydata = ['n', 'e', 'd', 'p', 'q', 'u'] + def _encrypt(self, plaintext, K=''): + if self.n<=plaintext: + raise error, 'Plaintext too large' + return (pow(plaintext, self.e, self.n),) + + def _decrypt(self, ciphertext): + if (not hasattr(self, 'd')): + raise error, 'Private key not available in this object' + if self.n<=ciphertext[0]: + raise error, 'Ciphertext too large' + return pow(ciphertext[0], self.d, self.n) + + def _sign(self, M, K=''): + return (self._decrypt((M,)),) + + def _verify(self, M, sig): + m2=self._encrypt(sig[0]) + if m2[0]==M: + return 1 + else: return 0 + + def _blind(self, M, B): + tmp = pow(B, self.e, self.n) + return (M * tmp) % self.n + + def _unblind(self, M, B): + tmp = pubkey.inverse(B, self.n) + return (M * tmp) % self.n + + def can_blind (self): + """can_blind() : bool + Return a Boolean value recording whether this algorithm can + blind data. (This does not imply that this + particular key object has the private information required to + to blind a message.) + """ + return 1 + + def size(self): + """size() : int + Return the maximum number of bits that can be handled by this key. + """ + return number.size(self.n) - 1 + + def has_private(self): + """has_private() : bool + Return a Boolean denoting whether the object contains + private components. + """ + if hasattr(self, 'd'): + return 1 + else: return 0 + + def publickey(self): + """publickey(): RSAobj + Return a new key object containing only the public key information. + """ + return construct((self.n, self.e)) + +class RSAobj_c(pubkey.pubkey): + keydata = ['n', 'e', 'd', 'p', 'q', 'u'] + + def __init__(self, key): + self.key = key + + def __getattr__(self, attr): + if attr in self.keydata: + return getattr(self.key, attr) + else: + if self.__dict__.has_key(attr): + self.__dict__[attr] + else: + raise AttributeError, '%s instance has no attribute %s' % (self.__class__, attr) + + def __getstate__(self): + d = {} + for k in self.keydata: + if hasattr(self.key, k): + d[k]=getattr(self.key, k) + return d + + def __setstate__(self, state): + n,e = state['n'], state['e'] + if not state.has_key('d'): + self.key = _fastmath.rsa_construct(n,e) + else: + d = state['d'] + if not state.has_key('q'): + self.key = _fastmath.rsa_construct(n,e,d) + else: + p, q, u = state['p'], state['q'], state['u'] + self.key = _fastmath.rsa_construct(n,e,d,p,q,u) + + def _encrypt(self, plain, K): + return (self.key._encrypt(plain),) + + def _decrypt(self, cipher): + return self.key._decrypt(cipher[0]) + + def _sign(self, M, K): + return (self.key._sign(M),) + + def _verify(self, M, sig): + return self.key._verify(M, sig[0]) + + def _blind(self, M, B): + return self.key._blind(M, B) + + def _unblind(self, M, B): + return self.key._unblind(M, B) + + def can_blind (self): + return 1 + + def size(self): + return self.key.size() + + def has_private(self): + return self.key.has_private() + + def publickey(self): + return construct_c((self.key.n, self.key.e)) + +def generate_c(bits, randfunc, progress_func = None): + # Generate the prime factors of n + if progress_func: + progress_func('p,q\n') + + p = q = 1L + while number.size(p*q) < bits: + p = pubkey.getPrime(bits/2, randfunc) + q = pubkey.getPrime(bits/2, randfunc) + + # p shall be smaller than q (for calc of u) + if p > q: + (p, q)=(q, p) + if progress_func: + progress_func('u\n') + u=pubkey.inverse(p, q) + n=p*q + + e = 65537L + if progress_func: + progress_func('d\n') + d=pubkey.inverse(e, (p-1)*(q-1)) + key = _fastmath.rsa_construct(n,e,d,p,q,u) + obj = RSAobj_c(key) + +## print p +## print q +## print number.size(p), number.size(q), number.size(q*p), +## print obj.size(), bits + assert bits <= 1+obj.size(), "Generated key is too small" + return obj + + +def construct_c(tuple): + key = apply(_fastmath.rsa_construct, tuple) + return RSAobj_c(key) + +object = RSAobj + +generate_py = generate +construct_py = construct + +if _fastmath: + #print "using C version of RSA" + generate = generate_c + construct = construct_c + error = _fastmath.error diff --git a/src/Crypto/PublicKey/__init__.py b/src/Crypto/PublicKey/__init__.py new file mode 100644 index 00000000..ad1c80ca --- /dev/null +++ b/src/Crypto/PublicKey/__init__.py @@ -0,0 +1,17 @@ +"""Public-key encryption and signature algorithms. + +Public-key encryption uses two different keys, one for encryption and +one for decryption. The encryption key can be made public, and the +decryption key is kept private. Many public-key algorithms can also +be used to sign messages, and some can *only* be used for signatures. + +Crypto.PublicKey.DSA Digital Signature Algorithm. (Signature only) +Crypto.PublicKey.ElGamal (Signing and encryption) +Crypto.PublicKey.RSA (Signing, encryption, and blinding) +Crypto.PublicKey.qNEW (Signature only) + +""" + +__all__ = ['RSA', 'DSA', 'ElGamal', 'qNEW'] +__revision__ = "$Id: __init__.py,v 1.4 2003/04/03 20:27:13 akuchling Exp $" + diff --git a/src/Crypto/PublicKey/pubkey.py b/src/Crypto/PublicKey/pubkey.py new file mode 100644 index 00000000..5597fb7a --- /dev/null +++ b/src/Crypto/PublicKey/pubkey.py @@ -0,0 +1,172 @@ +# +# pubkey.py : Internal functions for public key operations +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: pubkey.py,v 1.11 2003/04/03 20:36:14 akuchling Exp $" + +import types, warnings +from allmydata.Crypto.Util.number import * + +# Basic public key class +class pubkey: + def __init__(self): + pass + + def __getstate__(self): + """To keep key objects platform-independent, the key data is + converted to standard Python long integers before being + written out. It will then be reconverted as necessary on + restoration.""" + d=self.__dict__ + for key in self.keydata: + if d.has_key(key): d[key]=long(d[key]) + return d + + def __setstate__(self, d): + """On unpickling a key object, the key data is converted to the big +number representation being used, whether that is Python long +integers, MPZ objects, or whatever.""" + for key in self.keydata: + if d.has_key(key): self.__dict__[key]=bignum(d[key]) + + def encrypt(self, plaintext, K): + """encrypt(plaintext:string|long, K:string|long) : tuple + Encrypt the string or integer plaintext. K is a random + parameter required by some algorithms. + """ + wasString=0 + if isinstance(plaintext, types.StringType): + plaintext=bytes_to_long(plaintext) ; wasString=1 + if isinstance(K, types.StringType): + K=bytes_to_long(K) + ciphertext=self._encrypt(plaintext, K) + if wasString: return tuple(map(long_to_bytes, ciphertext)) + else: return ciphertext + + def decrypt(self, ciphertext): + """decrypt(ciphertext:tuple|string|long): string + Decrypt 'ciphertext' using this key. + """ + wasString=0 + if not isinstance(ciphertext, types.TupleType): + ciphertext=(ciphertext,) + if isinstance(ciphertext[0], types.StringType): + ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1 + plaintext=self._decrypt(ciphertext) + if wasString: return long_to_bytes(plaintext) + else: return plaintext + + def sign(self, M, K): + """sign(M : string|long, K:string|long) : tuple + Return a tuple containing the signature for the message M. + K is a random parameter required by some algorithms. + """ + if (not self.has_private()): + raise error, 'Private key not available in this object' + if isinstance(M, types.StringType): M=bytes_to_long(M) + if isinstance(K, types.StringType): K=bytes_to_long(K) + return self._sign(M, K) + + def verify (self, M, signature): + """verify(M:string|long, signature:tuple) : bool + Verify that the signature is valid for the message M; + returns true if the signature checks out. + """ + if isinstance(M, types.StringType): M=bytes_to_long(M) + return self._verify(M, signature) + + # alias to compensate for the old validate() name + def validate (self, M, signature): + warnings.warn("validate() method name is obsolete; use verify()", + DeprecationWarning) + + def blind(self, M, B): + """blind(M : string|long, B : string|long) : string|long + Blind message M using blinding factor B. + """ + wasString=0 + if isinstance(M, types.StringType): + M=bytes_to_long(M) ; wasString=1 + if isinstance(B, types.StringType): B=bytes_to_long(B) + blindedmessage=self._blind(M, B) + if wasString: return long_to_bytes(blindedmessage) + else: return blindedmessage + + def unblind(self, M, B): + """unblind(M : string|long, B : string|long) : string|long + Unblind message M using blinding factor B. + """ + wasString=0 + if isinstance(M, types.StringType): + M=bytes_to_long(M) ; wasString=1 + if isinstance(B, types.StringType): B=bytes_to_long(B) + unblindedmessage=self._unblind(M, B) + if wasString: return long_to_bytes(unblindedmessage) + else: return unblindedmessage + + + # The following methods will usually be left alone, except for + # signature-only algorithms. They both return Boolean values + # recording whether this key's algorithm can sign and encrypt. + def can_sign (self): + """can_sign() : bool + Return a Boolean value recording whether this algorithm can + generate signatures. (This does not imply that this + particular key object has the private information required to + to generate a signature.) + """ + return 1 + + def can_encrypt (self): + """can_encrypt() : bool + Return a Boolean value recording whether this algorithm can + encrypt data. (This does not imply that this + particular key object has the private information required to + to decrypt a message.) + """ + return 1 + + def can_blind (self): + """can_blind() : bool + Return a Boolean value recording whether this algorithm can + blind data. (This does not imply that this + particular key object has the private information required to + to blind a message.) + """ + return 0 + + # The following methods will certainly be overridden by + # subclasses. + + def size (self): + """size() : int + Return the maximum number of bits that can be handled by this key. + """ + return 0 + + def has_private (self): + """has_private() : bool + Return a Boolean denoting whether the object contains + private components. + """ + return 0 + + def publickey (self): + """publickey(): object + Return a new key object containing only the public information. + """ + return self + + def __eq__ (self, other): + """__eq__(other): 0, 1 + Compare us to other for equality. + """ + return self.__getstate__() == other.__getstate__() diff --git a/src/Crypto/PublicKey/qNEW.py b/src/Crypto/PublicKey/qNEW.py new file mode 100644 index 00000000..d8e98f18 --- /dev/null +++ b/src/Crypto/PublicKey/qNEW.py @@ -0,0 +1,170 @@ +# +# qNEW.py : The q-NEW signature algorithm. +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: qNEW.py,v 1.8 2003/04/04 15:13:35 akuchling Exp $" + +from allmydata.Crypto.PublicKey import pubkey +from allmydata.Crypto.Util.number import * +from allmydata.Crypto.Hash import SHA + +class error (Exception): + pass + +HASHBITS = 160 # Size of SHA digests + +def generate(bits, randfunc, progress_func=None): + """generate(bits:int, randfunc:callable, progress_func:callable) + + Generate a qNEW key of length 'bits', using 'randfunc' to get + random data and 'progress_func', if present, to display + the progress of the key generation. + """ + obj=qNEWobj() + + # Generate prime numbers p and q. q is a 160-bit prime + # number. p is another prime number (the modulus) whose bit + # size is chosen by the caller, and is generated so that p-1 + # is a multiple of q. + # + # Note that only a single seed is used to + # generate p and q; if someone generates a key for you, you can + # use the seed to duplicate the key generation. This can + # protect you from someone generating values of p,q that have + # some special form that's easy to break. + if progress_func: + progress_func('p,q\n') + while (1): + obj.q = getPrime(160, randfunc) + # assert pow(2, 159L)1. g is kept; h can be discarded. + if progress_func: + progress_func('h,g\n') + while (1): + h=bytes_to_long(randfunc(bits)) % (p-1) + g=pow(h, power, p) + if 11: + break + obj.g=g + + # x is the private key information, and is + # just a random number between 0 and q. + # y=g**x mod p, and is part of the public information. + if progress_func: + progress_func('x,y\n') + while (1): + x=bytes_to_long(randfunc(20)) + if 0 < x < obj.q: + break + obj.x, obj.y=x, pow(g, x, p) + + return obj + +# Construct a qNEW object +def construct(tuple): + """construct(tuple:(long,long,long,long)|(long,long,long,long,long) + Construct a qNEW object from a 4- or 5-tuple of numbers. + """ + obj=qNEWobj() + if len(tuple) not in [4,5]: + raise error, 'argument for construct() wrong length' + for i in range(len(tuple)): + field = obj.keydata[i] + setattr(obj, field, tuple[i]) + return obj + +class qNEWobj(pubkey.pubkey): + keydata=['p', 'q', 'g', 'y', 'x'] + + def _sign(self, M, K=''): + if (self.q<=K): + raise error, 'K is greater than q' + if M<0: + raise error, 'Illegal value of M (<0)' + if M>=pow(2,161L): + raise error, 'Illegal value of M (too large)' + r=pow(self.g, K, self.p) % self.q + s=(K- (r*M*self.x % self.q)) % self.q + return (r,s) + def _verify(self, M, sig): + r, s = sig + if r<=0 or r>=self.q or s<=0 or s>=self.q: + return 0 + if M<0: + raise error, 'Illegal value of M (<0)' + if M<=0 or M>=pow(2,161L): + return 0 + v1 = pow(self.g, s, self.p) + v2 = pow(self.y, M*r, self.p) + v = ((v1*v2) % self.p) + v = v % self.q + if v==r: + return 1 + return 0 + + def size(self): + "Return the maximum number of bits that can be handled by this key." + return 160 + + def has_private(self): + """Return a Boolean denoting whether the object contains + private components.""" + return hasattr(self, 'x') + + def can_sign(self): + """Return a Boolean value recording whether this algorithm can generate signatures.""" + return 1 + + def can_encrypt(self): + """Return a Boolean value recording whether this algorithm can encrypt data.""" + return 0 + + def publickey(self): + """Return a new key object containing only the public information.""" + return construct((self.p, self.q, self.g, self.y)) + +object = qNEWobj + diff --git a/src/Crypto/PublicKey/test/rsa_speed.py b/src/Crypto/PublicKey/test/rsa_speed.py new file mode 100644 index 00000000..00a13e82 --- /dev/null +++ b/src/Crypto/PublicKey/test/rsa_speed.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Script to time fast and slow RSA operations +# Contributed by Joris Bontje. + +import time, pprint +from allmydata.Crypto.PublicKey import * +from allmydata.Crypto.Util.randpool import RandomPool +from allmydata.Crypto.Util import number + +pool = RandomPool() +pool.stir() + +KEYSIZE=2048 +COUNT=5 +fasttime=0 +slowtime=0 +for x in range(COUNT): + begintime=time.time() + rsa=RSA.generate(KEYSIZE, pool.get_bytes) + endtime=time.time() + print "Server: Generating %d bit RSA key: %f s" % (KEYSIZE, endtime-begintime) + rsa_slow=RSA.construct((rsa.n,rsa.e,rsa.d)) + + code=number.getRandomNumber(256, pool.get_bytes) + begintime=time.time() + signature=rsa.sign(code,None)[0] + endtime=time.time() + fast=(endtime-begintime) + fasttime=fasttime+fast + print "Fast signing took %f s" % fast + + begintime=time.time() + signature_slow=rsa_slow.sign(code,None)[0] + endtime=time.time() + slow=(endtime-begintime) + slowtime=slowtime+slow + print "Slow signing took %f s" % slow + + if rsa.verify(code,(signature,)) and signature==signature_slow: + print "Signature okay" + else: + print "Signature WRONG" + + print "faster: %f" % (slow/fast) + +print "Based on %d signatures with %d bits keys the optimized\n RSA decryption/signing algorithm is %f times faster" % (COUNT, KEYSIZE, (slowtime/fasttime)) + diff --git a/src/Crypto/README b/src/Crypto/README new file mode 100644 index 00000000..c0a134f7 --- /dev/null +++ b/src/Crypto/README @@ -0,0 +1,76 @@ +Python Cryptography Toolkit (pycrypto) +====================================== + +This is a collection of both secure hash functions (such as MD5 and SHA), +and various encryption algorithms (AES, DES, IDEA, RSA, ElGamal, etc.). The +package is structured to make adding new modules easy. I consider this +section to be essentially complete, and the software interface will almost +certainly not change in an incompatible way in the future; all that remains +to be done is to fix any bugs that show up. If you encounter a bug, please +report it in the SourceForge bug tracker at + https://sourceforge.net/tracker/?group_id=20937&atid=120937 + +An example usage of the MD5 module is: +>>> from Crypto.Hash import MD5 +>>> hash=MD5.new() +>>> hash.update('message') +>>> hash.digest() +'x\xe71\x02}\x8f\xd5\x0e\xd6B4\x0b|\x9ac\xb3' + +An example usage of an encryption algorithm (AES, in this case) is: + +>>> from Crypto.Cipher import AES +>>> obj=AES.new('This is a key456', AES.MODE_ECB) +>>> message="The answer is no" +>>> ciphertext=obj.encrypt(message) +>>> ciphertext +'o\x1aq_{P+\xd0\x07\xce\x89\xd1=M\x989' +>>> obj2 = AES.new('This is a key456', AES.MODE_ECB) +>>> obj2.decrypt(ciphertext) +'The answer is no' + +One possible application of the modules is writing secure +administration tools. Another application is in writing daemons and +servers. Clients and servers can encrypt the data being exchanged and +mutually authenticate themselves; daemons can encrypt private data for +added security. Python also provides a pleasant framework for +prototyping and experimentation with cryptographic algorithms; thanks +to its arbitrary-length integers, public key algorithms are easily +implemented. + +Development of the toolkit can be discussed on the pct mailing list; +archives and instructions for subscribing at at +. + + +Installation +============ + +The toolkit is written and tested using Python 2.2, though it should +also work with Python 2.1. Python 1.5.2 is not supported, and the +setup.py script will abort if you run it with 1.5.2. + +The modules are packaged using the Distutils, so you can simply run +"python setup.py build" to build the package, and "python setup.py +install" to install it. + +If the setup.py script crashes with a DistutilsPlatformError +complaining that the file /usr/lib/python2.2/config/Makefile doesn't +exist, this means that the files needed for compiling new Python +modules aren't installed on your system. Red Hat users often run into +this because they don't have the python2-devel RPM installed. The fix +is to simply install the requisite RPM. + +To verify that everything is in order, run "python test.py". It will test +all the cryptographic modules, skipping ones that aren't available. If the +test script reports an error on your machine, please report the bug using +the bug tracker (URL given above). If possible, track down the bug and +include a patch that fixes it. + +To install the package under the site-packages directory of +your Python installation, run "python setup.py install". + +If you have any comments, corrections, or improvements for this package, +please send it to the 'pct' mailing list. Good luck! + +--amk (www.amk.ca) diff --git a/src/Crypto/TODO b/src/Crypto/TODO new file mode 100644 index 00000000..a79ad719 --- /dev/null +++ b/src/Crypto/TODO @@ -0,0 +1,31 @@ + +* Add more tests for random pool code? + +* Manual and Web page: point to SF project for bug reports + +* Update documentation (mention dodgy status of PublicKey code) + +* Clean up markup in pycrypt.tex + +* Reformat all the code to MEMS Exchange style + +* Document the functions and macros for adding a new algorithm + Hash functions: + hash_init(), hash_copy(), DIGEST_SIZE, hash_update(), hash_digest() + Block functions: + ... + +* Provide drop-in support for extensions/drivers like +amkCrypto/mxCrypto. There should be some way to register these +drivers in your package, e.g. by defining a certain subdirectory +to be a place where pycrypto looks for these drivers at startup +time. + +* Add a secure PRNG (Yarrow, maybe?) + +* A secret sharing module should be added to Util or Protocols. + +Documentation: + Document chaff/winnow better + Add docstrings everywhere. + diff --git a/src/Crypto/Util/RFC1751.py b/src/Crypto/Util/RFC1751.py new file mode 100644 index 00000000..0a479524 --- /dev/null +++ b/src/Crypto/Util/RFC1751.py @@ -0,0 +1,342 @@ +#!/usr/local/bin/python +# rfc1751.py : Converts between 128-bit strings and a human-readable +# sequence of words, as defined in RFC1751: "A Convention for +# Human-Readable 128-bit Keys", by Daniel L. McDonald. + +__revision__ = "$Id: RFC1751.py,v 1.6 2003/04/04 15:15:10 akuchling Exp $" + + +import string, binascii + +binary={0:'0000', 1:'0001', 2:'0010', 3:'0011', 4:'0100', 5:'0101', + 6:'0110', 7:'0111', 8:'1000', 9:'1001', 10:'1010', 11:'1011', + 12:'1100', 13:'1101', 14:'1110', 15:'1111'} + +def _key2bin(s): + "Convert a key into a string of binary digits" + kl=map(lambda x: ord(x), s) + kl=map(lambda x: binary[x/16]+binary[x&15], kl) + return ''.join(kl) + +def _extract(key, start, length): + """Extract a bitstring from a string of binary digits, and return its + numeric value.""" + k=key[start:start+length] + return reduce(lambda x,y: x*2+ord(y)-48, k, 0) + +def key_to_english (key): + """key_to_english(key:string) : string + Transform an arbitrary key into a string containing English words. + The key length must be a multiple of 8. + """ + english='' + for index in range(0, len(key), 8): # Loop over 8-byte subkeys + subkey=key[index:index+8] + # Compute the parity of the key + skbin=_key2bin(subkey) ; p=0 + for i in range(0, 64, 2): p=p+_extract(skbin, i, 2) + # Append parity bits to the subkey + skbin=_key2bin(subkey+chr((p<<6) & 255)) + for i in range(0, 64, 11): + english=english+wordlist[_extract(skbin, i, 11)]+' ' + + return english[:-1] # Remove the trailing space + +def english_to_key (str): + """english_to_key(string):string + Transform a string into a corresponding key. + The string must contain words separated by whitespace; the number + of words must be a multiple of 6. + """ + + L=string.split(string.upper(str)) ; key='' + for index in range(0, len(L), 6): + sublist=L[index:index+6] ; char=9*[0] ; bits=0 + for i in sublist: + index = wordlist.index(i) + shift = (8-(bits+11)%8) %8 + y = index << shift + cl, cc, cr = (y>>16), (y>>8)&0xff, y & 0xff + if (shift>5): + char[bits/8] = char[bits/8] | cl + char[bits/8+1] = char[bits/8+1] | cc + char[bits/8+2] = char[bits/8+2] | cr + elif shift>-3: + char[bits/8] = char[bits/8] | cc + char[bits/8+1] = char[bits/8+1] | cr + else: char[bits/8] = char[bits/8] | cr + bits=bits+11 + subkey=reduce(lambda x,y:x+chr(y), char, '') + + # Check the parity of the resulting key + skbin=_key2bin(subkey) + p=0 + for i in range(0, 64, 2): p=p+_extract(skbin, i, 2) + if (p&3) != _extract(skbin, 64, 2): + raise ValueError, "Parity error in resulting key" + key=key+subkey[0:8] + return key + +wordlist=[ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", + "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", + "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", + "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", + "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", + "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", + "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", + "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", + "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", + "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", + "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", + "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", + "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", + "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", + "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", + "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW", + "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", + "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", + "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", + "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", + "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", + "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", + "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE", + "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", + "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", + "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", + "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", + "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", + "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", + "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", + "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", + "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", + "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", + "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", + "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", + "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", + "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", + "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", + "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", + "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", + "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", + "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", + "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", + "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", + "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", + "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", + "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", + "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", + "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", + "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", + "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", + "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", + "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", + "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", + "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", + "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", + "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", + "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", + "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", + "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", + "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", + "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", + "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW", + "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA", + "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM", + "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", + "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", + "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", + "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", + "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", + "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", + "BEAU", "BECK", "BEEF", "BEEN", "BEER", + "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", + "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", + "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", + "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", + "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", + "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", + "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", + "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", + "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", + "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", + "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", + "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", + "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", + "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL", + "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", + "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", + "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", + "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", + "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", + "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", + "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", + "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST", + "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", + "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", + "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", + "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN", + "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", + "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", + "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", + "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", + "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", + "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", + "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", + "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", + "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", + "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", + "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", + "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", + "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", + "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", + "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", + "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST", + "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", + "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", + "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", + "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", + "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", + "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", + "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", + "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", + "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", + "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH", + "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", + "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", + "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", + "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", + "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", + "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", + "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", + "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", + "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", + "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK", + "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", + "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", + "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", + "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", + "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", + "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", + "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", + "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", + "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", + "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", + "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", + "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", + "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", + "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", + "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", + "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", + "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", + "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", + "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", + "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", + "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", + "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", + "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", + "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", + "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", + "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST", + "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", + "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", + "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", + "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", + "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", + "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", + "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", + "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", + "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", + "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK", + "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", + "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", + "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", + "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", + "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", + "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", + "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", + "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", + "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", + "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", + "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", + "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", + "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", + "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", + "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", + "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", + "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", + "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", + "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", + "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", + "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", + "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", + "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA", + "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", + "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD", + "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", + "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", + "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", + "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", + "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", + "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", + "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", + "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", + "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS", + "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", + "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", + "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", + "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", + "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", + "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", + "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", + "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", + "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", + "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", + "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", + "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", + "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", + "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", + "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", + "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", + "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN", + "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", + "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY", + "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", + "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", + "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", + "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", + "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", + "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", + "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", + "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", + "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", + "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", + "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", + "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", + "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", + "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", + "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", + "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE", + "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", + "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", + "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", + "YELL", "YOGA", "YOKE" ] + +if __name__=='__main__': + data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), + ('CCAC2AED591056BE4F90FD441C534766', + 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), + ('EFF81F9BFBC65350920CDD7416DE8009', + 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') + ] + + for key, words in data: + print 'Trying key', key + key=binascii.a2b_hex(key) + w2=key_to_english(key) + if w2!=words: + print 'key_to_english fails on key', repr(key), ', producing', str(w2) + k2=english_to_key(words) + if k2!=key: + print 'english_to_key fails on key', repr(key), ', producing', repr(k2) + + diff --git a/src/Crypto/Util/__init__.py b/src/Crypto/Util/__init__.py new file mode 100644 index 00000000..0d147681 --- /dev/null +++ b/src/Crypto/Util/__init__.py @@ -0,0 +1,16 @@ +"""Miscellaneous modules + +Contains useful modules that don't belong into any of the +other Crypto.* subpackages. + +Crypto.Util.number Number-theoretic functions (primality testing, etc.) +Crypto.Util.randpool Random number generation +Crypto.Util.RFC1751 Converts between 128-bit keys and human-readable + strings of words. + +""" + +__all__ = ['randpool', 'RFC1751', 'number'] + +__revision__ = "$Id: __init__.py,v 1.4 2003/02/28 15:26:00 akuchling Exp $" + diff --git a/src/Crypto/Util/bench.py b/src/Crypto/Util/bench.py new file mode 100644 index 00000000..a1682939 --- /dev/null +++ b/src/Crypto/Util/bench.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +from pyutil.assertutil import _assert, precondition, postcondition +from pyutil.randutil import insecurerandstr +from pyutil import benchutil + +from allmydata.Crypto.Cipher import AES + +MODE_CTR = AES.MODE_CTR # MODE_CTR is same value for all ciphers in pycrypto 2.0.1 + +class CipherRunner: + def __init__(self, ciph, mode): + if not ciph.key_size: ciph.key_size = 16 + self.ciph = ciph + self.mode = mode + self.counterstart = None + self.key = None + self.text = None + self.obj = None + self.obj2 = None + + def init(self, n): + precondition(self.ciph.key_size, self.ciph.key_size) + self.key = insecurerandstr(self.ciph.key_size) + if self.mode == MODE_CTR: + self.counterstart = insecurerandstr(self.ciph.block_size) + _assert(self.key, self.key) + self.text = insecurerandstr(n) + if self.mode == MODE_CTR: + self.obj = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) + else: + self.obj = self.ciph.new(self.key, self.mode) + if self.mode == MODE_CTR: + self.obj2 = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) + else: + self.obj2 = self.ciph.new(self.key, self.mode) + + def construct_then_encrypt(self, n): + assert len(self.text) == n + if self.mode == MODE_CTR: + self.obj = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) + else: + self.obj = self.ciph.new(self.key, self.mode) + return self.obj.encrypt(self.text) + + def encrypt(self, n): + assert len(self.text) == n + return self.obj.encrypt(self.text) + + def decrypt(self, n): + assert len(self.text) == n + return self.obj.decrypt(self.text) + + def encrypt_then_decrypt_then_compare(self, n): + assert len(self.text) == n + ciphertext = self.obj.encrypt(self.text) + decrypted = self.obj2.decrypt(ciphertext) + if decrypted != self.text: + raise "FAILURE! decrypted does match original plaintext, self.text[:64]: %r, decrypted[:64]: %r" % (self.text[:64], decrypted[:64],) + + def construct_then_encrypt_then_decrypt_then_compare(self, n): + assert len(self.text) == n + if self.mode == MODE_CTR: + self.obj = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) + else: + self.obj = self.ciph.new(self.key, self.mode) + if self.mode == MODE_CTR: + self.obj2 = self.ciph.new(self.key, self.mode, counterstart=self.counterstart) + else: + self.obj2 = self.ciph.new(self.key, self.mode) + ciphertext = self.obj.encrypt(self.text) + decrypted = self.obj2.decrypt(ciphertext) + if decrypted != self.text: + raise "FAILURE! decrypted does match original plaintext, self.text[:64]: %r, decrypted[:64]: %r" % (self.text[:64], decrypted[:64],) + +from allmydata.Crypto.Cipher import * +def bench_aes_ctr(): + c = CipherRunner(AES, AES.MODE_CTR) + + for m in (c.construct_then_encrypt, c.encrypt, c.decrypt, c.encrypt_then_decrypt_then_compare, c.construct_then_encrypt_then_decrypt_then_compare,): + print m.__name__ + for BSIZE in (2**4, 2**8, 2**10, 2**14, 2**16,): + benchutil.rep_bench(m, BSIZE, initfunc=c.init, MAXREPS=2**14, MAXTIME=10.0) + diff --git a/src/Crypto/Util/number.py b/src/Crypto/Util/number.py new file mode 100644 index 00000000..7a5de7de --- /dev/null +++ b/src/Crypto/Util/number.py @@ -0,0 +1,201 @@ +# +# number.py : Number-theoretic functions +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: number.py,v 1.13 2003/04/04 18:21:07 akuchling Exp $" + +bignum = long +try: + from allmydata.Crypto.PublicKey import _fastmath +except ImportError: + _fastmath = None + +# Commented out and replaced with faster versions below +## def long2str(n): +## s='' +## while n>0: +## s=chr(n & 255)+s +## n=n>>8 +## return s + +## import types +## def str2long(s): +## if type(s)!=types.StringType: return s # Integers will be left alone +## return reduce(lambda x,y : x*256+ord(y), s, 0L) + +def size (N): + """size(N:long) : int + Returns the size of the number N in bits. + """ + bits, power = 0,1L + while N >= power: + bits += 1 + power = power << 1 + return bits + +def getRandomNumber(N, randfunc): + """getRandomNumber(N:int, randfunc:callable):long + Return an N-bit random number.""" + + S = randfunc(N/8) + odd_bits = N % 8 + if odd_bits != 0: + char = ord(randfunc(1)) >> (8-odd_bits) + S = chr(char) + S + value = bytes_to_long(S) + value |= 2L ** (N-1) # Ensure high bit is set + assert size(value) >= N + return value + +def GCD(x,y): + """GCD(x:long, y:long): long + Return the GCD of x and y. + """ + x = abs(x) ; y = abs(y) + while x > 0: + x, y = y % x, x + return y + +def inverse(u, v): + """inverse(u:long, u:long):long + Return the inverse of u mod v. + """ + u3, v3 = long(u), long(v) + u1, v1 = 1L, 0L + while v3 > 0: + q=u3 / v3 + u1, v1 = v1, u1 - v1*q + u3, v3 = v3, u3 - v3*q + while u1<0: + u1 = u1 + v + return u1 + +# Given a number of bits to generate and a random generation function, +# find a prime number of the appropriate size. + +def getPrime(N, randfunc): + """getPrime(N:int, randfunc:callable):long + Return a random N-bit prime number. + """ + + number=getRandomNumber(N, randfunc) | 1 + while (not isPrime(number)): + number=number+2 + return number + +def isPrime(N): + """isPrime(N:long):bool + Return true if N is prime. + """ + if N == 1: + return 0 + if N in sieve: + return 1 + for i in sieve: + if (N % i)==0: + return 0 + + # Use the accelerator if available + if _fastmath is not None: + return _fastmath.isPrime(N) + + # Compute the highest bit that's set in N + N1 = N - 1L + n = 1L + while (n> 1L + + # Rabin-Miller test + for c in sieve[:7]: + a=long(c) ; d=1L ; t=n + while (t): # Iterate over the bits in N1 + x=(d*d) % N + if x==1L and d!=1L and d!=N1: + return 0 # Square root of 1 found + if N1 & t: + d=(x*a) % N + else: + d=x + t = t >> 1L + if d!=1L: + return 0 + return 1 + +# Small primes used for checking primality; these are all the primes +# less than 256. This should be enough to eliminate most of the odd +# numbers before needing to do a Rabin-Miller test at all. + +sieve=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, + 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, + 197, 199, 211, 223, 227, 229, 233, 239, 241, 251] + +# Improved conversion functions contributed by Barry Warsaw, after +# careful benchmarking + +import struct + +def long_to_bytes(n, blocksize=0): + """long_to_bytes(n:long, blocksize:int) : string + Convert a long integer to a byte string. + + If optional blocksize is given and greater than zero, pad the front of the + byte string with binary zeros so that the length is a multiple of + blocksize. + """ + # after much testing, this algorithm was deemed to be the fastest + s = '' + n = long(n) + pack = struct.pack + while n > 0: + s = pack('>I', n & 0xffffffffL) + s + n = n >> 32 + # strip off leading zeros + for i in range(len(s)): + if s[i] != '\000': + break + else: + # only happens when n == 0 + s = '\000' + i = 0 + s = s[i:] + # add back some pad bytes. this could be done more efficiently w.r.t. the + # de-padding being done above, but sigh... + if blocksize > 0 and len(s) % blocksize: + s = (blocksize - len(s) % blocksize) * '\000' + s + return s + +def bytes_to_long(s): + """bytes_to_long(string) : long + Convert a byte string to a long integer. + + This is (essentially) the inverse of long_to_bytes(). + """ + acc = 0L + unpack = struct.unpack + length = len(s) + if length % 4: + extra = (4 - length % 4) + s = '\000' * extra + s + length = length + extra + for i in range(0, length, 4): + acc = (acc << 32) + unpack('>I', s[i:i+4])[0] + return acc + +# For backwards compatibility... +import warnings +def long2str(n, blocksize=0): + warnings.warn("long2str() has been replaced by long_to_bytes()") + return long_to_bytes(n, blocksize) +def str2long(s): + warnings.warn("str2long() has been replaced by bytes_to_long()") + return bytes_to_long(s) diff --git a/src/Crypto/Util/randpool.py b/src/Crypto/Util/randpool.py new file mode 100644 index 00000000..fb15ed69 --- /dev/null +++ b/src/Crypto/Util/randpool.py @@ -0,0 +1,421 @@ +# +# randpool.py : Cryptographically strong random number generation +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: randpool.py,v 1.14 2004/05/06 12:56:54 akuchling Exp $" + +import time, array, types, warnings, os.path +from allmydata.Crypto.Util.number import long_to_bytes +try: + import allmydata.Crypto.Util.winrandom as winrandom +except: + winrandom = None + +STIRNUM = 3 + +class RandomPool: + """randpool.py : Cryptographically strong random number generation. + + The implementation here is similar to the one in PGP. To be + cryptographically strong, it must be difficult to determine the RNG's + output, whether in the future or the past. This is done by using + a cryptographic hash function to "stir" the random data. + + Entropy is gathered in the same fashion as PGP; the highest-resolution + clock around is read and the data is added to the random number pool. + A conservative estimate of the entropy is then kept. + + If a cryptographically secure random source is available (/dev/urandom + on many Unixes, Windows CryptGenRandom on most Windows), then use + it. + + Instance Attributes: + bits : int + Maximum size of pool in bits + bytes : int + Maximum size of pool in bytes + entropy : int + Number of bits of entropy in this pool. + + Methods: + add_event([s]) : add some entropy to the pool + get_bytes(int) : get N bytes of random data + randomize([N]) : get N bytes of randomness from external source + """ + + + def __init__(self, numbytes = 160, cipher=None, hash=None): + if hash is None: + from allmydata.Crypto.Hash import SHA as hash + + # The cipher argument is vestigial; it was removed from + # version 1.1 so RandomPool would work even in the limited + # exportable subset of the code + if cipher is not None: + warnings.warn("'cipher' parameter is no longer used") + + if isinstance(hash, types.StringType): + # ugly hack to force __import__ to give us the end-path module + hash = __import__('allmydata.Crypto.Hash.'+hash, + None, None, ['new']) + warnings.warn("'hash' parameter should now be a hashing module") + + self.bytes = numbytes + self.bits = self.bytes*8 + self.entropy = 0 + self._hash = hash + + # Construct an array to hold the random pool, + # initializing it to 0. + self._randpool = array.array('B', [0]*self.bytes) + + self._event1 = self._event2 = 0 + self._addPos = 0 + self._getPos = hash.digest_size + self._lastcounter=time.time() + self.__counter = 0 + + self._measureTickSize() # Estimate timer resolution + self._randomize() + + def _updateEntropyEstimate(self, nbits): + self.entropy += nbits + if self.entropy < 0: + self.entropy = 0 + elif self.entropy > self.bits: + self.entropy = self.bits + + def _randomize(self, N = 0, devname = '/dev/urandom'): + """_randomize(N, DEVNAME:device-filepath) + collects N bits of randomness from some entropy source (e.g., + /dev/urandom on Unixes that have it, Windows CryptoAPI + CryptGenRandom, etc) + DEVNAME is optional, defaults to /dev/urandom. You can change it + to /dev/random if you want to block till you get enough + entropy. + """ + data = '' + if N <= 0: + nbytes = int((self.bits - self.entropy)/8+0.5) + else: + nbytes = int(N/8+0.5) + if winrandom: + # Windows CryptGenRandom provides random data. + data = winrandom.new().get_bytes(nbytes) + elif os.path.exists(devname): + # Many OSes support a /dev/urandom device + try: + f=open(devname) + data=f.read(nbytes) + f.close() + except IOError, (num, msg): + if num!=2: raise IOError, (num, msg) + # If the file wasn't found, ignore the error + if data: + self._addBytes(data) + # Entropy estimate: The number of bits of + # data obtained from the random source. + self._updateEntropyEstimate(8*len(data)) + self.stir_n() # Wash the random pool + + def randomize(self, N=0): + """randomize(N:int) + use the class entropy source to get some entropy data. + This is overridden by KeyboardRandomize(). + """ + return self._randomize(N) + + def stir_n(self, N = STIRNUM): + """stir_n(N) + stirs the random pool N times + """ + for i in xrange(N): + self.stir() + + def stir (self, s = ''): + """stir(s:string) + Mix up the randomness pool. This will call add_event() twice, + but out of paranoia the entropy attribute will not be + increased. The optional 's' parameter is a string that will + be hashed with the randomness pool. + """ + + entropy=self.entropy # Save inital entropy value + self.add_event() + + # Loop over the randomness pool: hash its contents + # along with a counter, and add the resulting digest + # back into the pool. + for i in range(self.bytes / self._hash.digest_size): + h = self._hash.new(self._randpool) + h.update(str(self.__counter) + str(i) + str(self._addPos) + s) + self._addBytes( h.digest() ) + self.__counter = (self.__counter + 1) & 0xFFFFffffL + + self._addPos, self._getPos = 0, self._hash.digest_size + self.add_event() + + # Restore the old value of the entropy. + self.entropy=entropy + + + def get_bytes (self, N): + """get_bytes(N:int) : string + Return N bytes of random data. + """ + + s='' + i, pool = self._getPos, self._randpool + h=self._hash.new() + dsize = self._hash.digest_size + num = N + while num > 0: + h.update( self._randpool[i:i+dsize] ) + s = s + h.digest() + num = num - dsize + i = (i + dsize) % self.bytes + if i>1, bits+1 + if bits>8: bits=8 + + self._event1, self._event2 = event, self._event1 + + self._updateEntropyEstimate(bits) + return bits + + # Private functions + def _noise(self): + # Adds a bit of noise to the random pool, by adding in the + # current time and CPU usage of this process. + # The difference from the previous call to _noise() is taken + # in an effort to estimate the entropy. + t=time.time() + delta = (t - self._lastcounter)/self._ticksize*1e6 + self._lastcounter = t + self._addBytes(long_to_bytes(long(1000*time.time()))) + self._addBytes(long_to_bytes(long(1000*time.clock()))) + self._addBytes(long_to_bytes(long(1000*time.time()))) + self._addBytes(long_to_bytes(long(delta))) + + # Reduce delta to a maximum of 8 bits so we don't add too much + # entropy as a result of this call. + delta=delta % 0xff + return int(delta) + + + def _measureTickSize(self): + # _measureTickSize() tries to estimate a rough average of the + # resolution of time that you can see from Python. It does + # this by measuring the time 100 times, computing the delay + # between measurements, and taking the median of the resulting + # list. (We also hash all the times and add them to the pool) + interval = [None] * 100 + h = self._hash.new(`(id(self),id(interval))`) + + # Compute 100 differences + t=time.time() + h.update(`t`) + i = 0 + j = 0 + while i < 100: + t2=time.time() + h.update(`(i,j,t2)`) + j += 1 + delta=int((t2-t)*1e6) + if delta: + interval[i] = delta + i += 1 + t=t2 + + # Take the median of the array of intervals + interval.sort() + self._ticksize=interval[len(interval)/2] + h.update(`(interval,self._ticksize)`) + # mix in the measurement times and wash the random pool + self.stir(h.digest()) + + def _addBytes(self, s): + "XOR the contents of the string S into the random pool" + i, pool = self._addPos, self._randpool + for j in range(0, len(s)): + pool[i]=pool[i] ^ ord(s[j]) + i=(i+1) % self.bytes + self._addPos = i + + # Deprecated method names: remove in PCT 2.1 or later. + def getBytes(self, N): + warnings.warn("getBytes() method replaced by get_bytes()", + DeprecationWarning) + return self.get_bytes(N) + + def addEvent (self, event, s=""): + warnings.warn("addEvent() method replaced by add_event()", + DeprecationWarning) + return self.add_event(s + str(event)) + +class PersistentRandomPool (RandomPool): + def __init__ (self, filename=None, *args, **kwargs): + RandomPool.__init__(self, *args, **kwargs) + self.filename = filename + if filename: + try: + # the time taken to open and read the file might have + # a little disk variability, modulo disk/kernel caching... + f=open(filename, 'rb') + self.add_event() + data = f.read() + self.add_event() + # mix in the data from the file and wash the random pool + self.stir(data) + f.close() + except IOError: + # Oh, well; the file doesn't exist or is unreadable, so + # we'll just ignore it. + pass + + def save(self): + if self.filename == "": + raise ValueError, "No filename set for this object" + # wash the random pool before save, provides some forward secrecy for + # old values of the pool. + self.stir_n() + f=open(self.filename, 'wb') + self.add_event() + f.write(self._randpool.tostring()) + f.close() + self.add_event() + # wash the pool again, provide some protection for future values + self.stir() + +# non-echoing Windows keyboard entry +_kb = 0 +if not _kb: + try: + import msvcrt + class KeyboardEntry: + def getch(self): + c = msvcrt.getch() + if c in ('\000', '\xe0'): + # function key + c += msvcrt.getch() + return c + def close(self, delay = 0): + if delay: + time.sleep(delay) + while msvcrt.kbhit(): + msvcrt.getch() + _kb = 1 + except: + pass + +# non-echoing Posix keyboard entry +if not _kb: + try: + import termios + class KeyboardEntry: + def __init__(self, fd = 0): + self._fd = fd + self._old = termios.tcgetattr(fd) + new = termios.tcgetattr(fd) + new[3]=new[3] & ~termios.ICANON & ~termios.ECHO + termios.tcsetattr(fd, termios.TCSANOW, new) + def getch(self): + termios.tcflush(0, termios.TCIFLUSH) # XXX Leave this in? + return os.read(self._fd, 1) + def close(self, delay = 0): + if delay: + time.sleep(delay) + termios.tcflush(self._fd, termios.TCIFLUSH) + termios.tcsetattr(self._fd, termios.TCSAFLUSH, self._old) + _kb = 1 + except: + pass + +class KeyboardRandomPool (PersistentRandomPool): + def __init__(self, *args, **kwargs): + PersistentRandomPool.__init__(self, *args, **kwargs) + + def randomize(self, N = 0): + "Adds N bits of entropy to random pool. If N is 0, fill up pool." + import os, string, time + if N <= 0: + bits = self.bits - self.entropy + else: + bits = N*8 + if bits == 0: + return + print bits,'bits of entropy are now required. Please type on the keyboard' + print 'until enough randomness has been accumulated.' + kb = KeyboardEntry() + s='' # We'll save the characters typed and add them to the pool. + hash = self._hash + e = 0 + try: + while e < bits: + temp=str(bits-e).rjust(6) + os.write(1, temp) + s=s+kb.getch() + e += self.add_event(s) + os.write(1, 6*chr(8)) + self.add_event(s+hash.new(s).digest() ) + finally: + kb.close() + print '\n\007 Enough. Please wait a moment.\n' + self.stir_n() # wash the random pool. + kb.close(4) + +if __name__ == '__main__': + pool = RandomPool() + print 'random pool entropy', pool.entropy, 'bits' + pool.add_event('something') + print `pool.get_bytes(100)` + import tempfile, os + fname = tempfile.mktemp() + pool = KeyboardRandomPool(filename=fname) + print 'keyboard random pool entropy', pool.entropy, 'bits' + pool.randomize() + print 'keyboard random pool entropy', pool.entropy, 'bits' + pool.randomize(128) + pool.save() + saved = open(fname, 'rb').read() + print 'saved', `saved` + print 'pool ', `pool._randpool.tostring()` + newpool = PersistentRandomPool(fname) + print 'persistent random pool entropy', pool.entropy, 'bits' + os.remove(fname) diff --git a/src/Crypto/Util/test.py b/src/Crypto/Util/test.py new file mode 100644 index 00000000..b4a3c143 --- /dev/null +++ b/src/Crypto/Util/test.py @@ -0,0 +1,495 @@ +# +# test.py : Functions used for testing the modules +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +__revision__ = "$Id: test.py,v 1.16 2004/08/13 22:24:18 akuchling Exp $" + +import binascii +import random +import string +import testdata + +from allmydata.Crypto.Cipher import * +from allmydata.Crypto.Util.number import long_to_bytes + +def die(string): + import sys + print '***ERROR: ', string +# sys.exit(0) # Will default to continuing onward... + +def print_timing (size, delta, verbose): + if verbose: + if delta == 0: + print 'Unable to measure time -- elapsed time too small' + else: + print '%.2f K/sec' % (size/delta) + +def exerciseBlockCipher(cipher, verbose): + import string, time + try: + ciph = eval(cipher) + except NameError: + print cipher, 'module not available' + return None + print cipher+ ':' + str='1' # Build 128K of test data + for i in xrange(0, 17): + str=str+str + if ciph.key_size==0: ciph.key_size=16 + password = 'password12345678Extra text for password'[0:ciph.key_size] + IV = 'Test IV Test IV Test IV Test'[0:ciph.block_size] + + if verbose: print ' ECB mode:', + obj=ciph.new(password, ciph.MODE_ECB) + if obj.block_size != ciph.block_size: + die("Module and cipher object block_size don't match") + + text='1234567812345678'[0:ciph.block_size] + c=obj.encrypt(text) + if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"') + text='KuchlingKuchling'[0:ciph.block_size] + c=obj.encrypt(text) + if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"') + text='NotTodayNotEver!'[0:ciph.block_size] + c=obj.encrypt(text) + if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"') + + start=time.time() + s=obj.encrypt(str) + s2=obj.decrypt(s) + end=time.time() + if (str!=s2): + die('Error in resulting plaintext from ECB mode') + print_timing(256, end-start, verbose) + del obj + + if verbose: print ' CFB mode:', + obj1=ciph.new(password, ciph.MODE_CFB, IV) + obj2=ciph.new(password, ciph.MODE_CFB, IV) + start=time.time() + ciphertext=obj1.encrypt(str[0:65536]) + plaintext=obj2.decrypt(ciphertext) + end=time.time() + if (plaintext!=str[0:65536]): + die('Error in resulting plaintext from CFB mode') + print_timing(64, end-start, verbose) + del obj1, obj2 + + if verbose: print ' CBC mode:', + obj1=ciph.new(password, ciph.MODE_CBC, IV) + obj2=ciph.new(password, ciph.MODE_CBC, IV) + start=time.time() + ciphertext=obj1.encrypt(str) + plaintext=obj2.decrypt(ciphertext) + end=time.time() + if (plaintext!=str): + die('Error in resulting plaintext from CBC mode') + print_timing(256, end-start, verbose) + del obj1, obj2 + + if verbose: print ' PGP mode:', + obj1=ciph.new(password, ciph.MODE_PGP, IV) + obj2=ciph.new(password, ciph.MODE_PGP, IV) + start=time.time() + ciphertext=obj1.encrypt(str) + plaintext=obj2.decrypt(ciphertext) + end=time.time() + if (plaintext!=str): + die('Error in resulting plaintext from PGP mode') + print_timing(256, end-start, verbose) + del obj1, obj2 + + if verbose: print ' OFB mode:', + obj1=ciph.new(password, ciph.MODE_OFB, IV) + obj2=ciph.new(password, ciph.MODE_OFB, IV) + start=time.time() + ciphertext=obj1.encrypt(str) + plaintext=obj2.decrypt(ciphertext) + end=time.time() + if (plaintext!=str): + die('Error in resulting plaintext from OFB mode') + print_timing(256, end-start, verbose) + del obj1, obj2 + + startctr = random.randrange(0, 2**(ciph.block_size * 8)) + + if verbose: print ' CTR mode:', + obj1=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) + obj2=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) + start=time.time() + ciphertext=obj1.encrypt(str) + plaintext=obj2.decrypt(ciphertext) + end=time.time() + if (plaintext!=str): + die('Error in resulting plaintext from CTR mode') + print_timing(256, end-start, verbose) + del obj1, obj2 + + if verbose: print ' CTR mode, variable length:', + strv = str[:-1] + obj1=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) + obj2=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) + start=time.time() + ciphertext=obj1.encrypt(strv) + plaintext=obj2.decrypt(ciphertext) + end=time.time() + if (plaintext!=strv): + die('Error in resulting plaintext from CTR mode, variable length') + print_timing(256, end-start, verbose) + del obj1, obj2 + + if verbose: print ' CTR mode, variable length, restart:', + strv = str[:-1] + obj1=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) + obj2=ciph.new(password, ciph.MODE_CTR, counterstart=long_to_bytes(startctr, ciph.block_size)) + start=time.time() + tempstrv = strv + ciphertexta = [] + while tempstrv: + chunksiz = random.randrange(1, len(tempstrv)+1) + ciphertexta.append(obj1.encrypt(tempstrv[:chunksiz])) + tempstrv = tempstrv[chunksiz:] + ciphertext = ''.join(ciphertexta) + plaintext=obj2.decrypt(ciphertext) + end=time.time() + if (len(plaintext)!=len(strv)): + die('Error in resulting plaintext from CTR mode, variable length, restart, lenofplaintext: %s, lenofstrv: %r' % (len(plaintext), len(strv),)) + + if (plaintext!=strv): + die('Error in resulting plaintext from CTR mode, variable length, restart, plaintext: %r, strv: %r' % (plaintext, strv,)) + print_timing(256, end-start, verbose) + del obj1, obj2 + + # Test the IV handling + if verbose: print ' Testing IV handling' + obj1=ciph.new(password, ciph.MODE_CBC, IV) + plaintext='Test'*(ciph.block_size/4)*3 + ciphertext1=obj1.encrypt(plaintext) + obj1.IV=IV + ciphertext2=obj1.encrypt(plaintext) + if ciphertext1!=ciphertext2: + die('Error in setting IV') + + # Test keyword arguments + obj1=ciph.new(key=password) + obj1=ciph.new(password, mode=ciph.MODE_CBC) + obj1=ciph.new(mode=ciph.MODE_CBC, key=password) + obj1=ciph.new(IV=IV, mode=ciph.MODE_CBC, key=password) + + return ciph + +def exerciseStreamCipher(cipher, verbose): + import string, time + try: + ciph = eval(cipher) + except (NameError): + print cipher, 'module not available' + return None + print cipher + ':', + str='1' # Build 128K of test data + for i in xrange(0, 17): + str=str+str + key_size = ciph.key_size or 16 + password = 'password12345678Extra text for password'[0:key_size] + + obj1=ciph.new(password) + obj2=ciph.new(password) + if obj1.block_size != ciph.block_size: + die("Module and cipher object block_size don't match") + if obj1.key_size != ciph.key_size: + die("Module and cipher object key_size don't match") + + text='1234567812345678Python' + c=obj1.encrypt(text) + if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"') + text='B1FF I2 A R3A11Y |<00L D00D!!!!!' + c=obj1.encrypt(text) + if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"') + c=obj1.encrypt(text) + if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"') + + start=time.time() + s=obj1.encrypt(str) + str=obj2.decrypt(s) + end=time.time() + print_timing(256, end-start, verbose) + del obj1, obj2 + + return ciph + +def TestStreamModules(args=['arc4', 'XOR'], verbose=1): + import sys, string + args=map(string.lower, args) + + if 'arc4' in args: + # Test ARC4 stream cipher + arc4=exerciseStreamCipher('ARC4', verbose) + if (arc4!=None): + for entry in testdata.arc4: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=arc4.new(key) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('ARC4 failed on entry '+`entry`) + + if 'xor' in args: + # Test XOR stream cipher + XOR=exerciseStreamCipher('XOR', verbose) + if (XOR!=None): + for entry in testdata.xor: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=XOR.new(key) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('XOR failed on entry '+`entry`) + + +def TestBlockModules(args=['aes', 'arc2', 'des', 'blowfish', 'cast', 'des3'], + verbose=1): + import string + args=map(string.lower, args) + if 'aes' in args: + ciph=exerciseBlockCipher('AES', verbose) # AES + if (ciph!=None): + if verbose: print ' Verifying against test suite...' + for entry in testdata.aes: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=ciph.new(key, ciph.MODE_ECB) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('AES failed on entry '+`entry`) + for i in ciphertext: + if verbose: print hex(ord(i)), + if verbose: print + + for entry in testdata.aes_modes: + mode, key, plain, cipher, kw = entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + try: + obj=ciph.new(key, mode, **kw) + obj2=ciph.new(key, mode, **kw) + except: + print 'AES contruction got exception on entry '+`entry` + raise + try: + ciphertext=obj.encrypt(plain) + except: + print 'AES encrypt got exception on entry '+`entry` + raise + if (ciphertext!=cipher): + die('AES encrypt failed on entry '+`entry`) + for i in ciphertext: + if verbose: print hex(ord(i)), + if verbose: print + + plain2=obj2.decrypt(ciphertext) + if plain2!=plain: + die('AES decrypt failed on entry '+`entry`) + for i in plain2: + if verbose: print hex(ord(i)), + if verbose: print + + + if 'arc2' in args: + ciph=exerciseBlockCipher('ARC2', verbose) # Alleged RC2 + if (ciph!=None): + if verbose: print ' Verifying against test suite...' + for entry in testdata.arc2: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=ciph.new(key, ciph.MODE_ECB) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('ARC2 failed on entry '+`entry`) + for i in ciphertext: + if verbose: print hex(ord(i)), + print + + if 'blowfish' in args: + ciph=exerciseBlockCipher('Blowfish',verbose)# Bruce Schneier's Blowfish cipher + if (ciph!=None): + if verbose: print ' Verifying against test suite...' + for entry in testdata.blowfish: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=ciph.new(key, ciph.MODE_ECB) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('Blowfish failed on entry '+`entry`) + for i in ciphertext: + if verbose: print hex(ord(i)), + if verbose: print + + if 'cast' in args: + ciph=exerciseBlockCipher('CAST', verbose) # CAST-128 + if (ciph!=None): + if verbose: print ' Verifying against test suite...' + for entry in testdata.cast: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=ciph.new(key, ciph.MODE_ECB) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('CAST failed on entry '+`entry`) + for i in ciphertext: + if verbose: print hex(ord(i)), + if verbose: print + + if 0: + # The full-maintenance test; it requires 4 million encryptions, + # and correspondingly is quite time-consuming. I've disabled + # it; it's faster to compile block/cast.c with -DTEST and run + # the resulting program. + a = b = '\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45\x67\x89\x34\x56\x78\x9A' + + for i in range(0, 1000000): + obj = cast.new(b, cast.MODE_ECB) + a = obj.encrypt(a[:8]) + obj.encrypt(a[-8:]) + obj = cast.new(a, cast.MODE_ECB) + b = obj.encrypt(b[:8]) + obj.encrypt(b[-8:]) + + if a!="\xEE\xA9\xD0\xA2\x49\xFD\x3B\xA6\xB3\x43\x6F\xB8\x9D\x6D\xCA\x92": + if verbose: print 'CAST test failed: value of "a" doesn\'t match' + if b!="\xB2\xC9\x5E\xB0\x0C\x31\xAD\x71\x80\xAC\x05\xB8\xE8\x3D\x69\x6E": + if verbose: print 'CAST test failed: value of "b" doesn\'t match' + + if 'des' in args: + # Test/benchmark DES block cipher + des=exerciseBlockCipher('DES', verbose) + if (des!=None): + # Various tests taken from the DES library packaged with Kerberos V4 + obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_ECB) + s=obj.encrypt('Now is t') + if (s!=binascii.a2b_hex('3fa40e8a984d4815')): + die('DES fails test 1') + obj=des.new(binascii.a2b_hex('08192a3b4c5d6e7f'), des.MODE_ECB) + s=obj.encrypt('\000\000\000\000\000\000\000\000') + if (s!=binascii.a2b_hex('25ddac3e96176467')): + die('DES fails test 2') + obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC, + binascii.a2b_hex('1234567890abcdef')) + s=obj.encrypt("Now is the time for all ") + if (s!=binascii.a2b_hex('e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6')): + die('DES fails test 3') + obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC, + binascii.a2b_hex('fedcba9876543210')) + s=obj.encrypt("7654321 Now is the time for \000\000\000\000") + if (s!=binascii.a2b_hex("ccd173ffab2039f4acd8aefddfd8a1eb468e91157888ba681d269397f7fe62b4")): + die('DES fails test 4') + del obj,s + + # R. Rivest's test: see http://theory.lcs.mit.edu/~rivest/destest.txt + x=binascii.a2b_hex('9474B8E8C73BCA7D') + for i in range(0, 16): + obj=des.new(x, des.MODE_ECB) + if (i & 1): x=obj.decrypt(x) + else: x=obj.encrypt(x) + if x!=binascii.a2b_hex('1B1A2DDB4C642438'): + die("DES fails Rivest's test") + + if verbose: print ' Verifying against test suite...' + for entry in testdata.des: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=des.new(key, des.MODE_ECB) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('DES failed on entry '+`entry`) + for entry in testdata.des_cbc: + key, iv, plain, cipher=entry + key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher) + obj1=des.new(key, des.MODE_CBC, iv) + obj2=des.new(key, des.MODE_CBC, iv) + ciphertext=obj1.encrypt(plain) + if (ciphertext!=cipher): + die('DES CBC mode failed on entry '+`entry`) + + if 'des3' in args: + ciph=exerciseBlockCipher('DES3', verbose) # Triple DES + if (ciph!=None): + if verbose: print ' Verifying against test suite...' + for entry in testdata.des3: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=ciph.new(key, ciph.MODE_ECB) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('DES3 failed on entry '+`entry`) + for i in ciphertext: + if verbose: print hex(ord(i)), + if verbose: print + for entry in testdata.des3_cbc: + key, iv, plain, cipher=entry + key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher) + obj1=ciph.new(key, ciph.MODE_CBC, iv) + obj2=ciph.new(key, ciph.MODE_CBC, iv) + ciphertext=obj1.encrypt(plain) + if (ciphertext!=cipher): + die('DES3 CBC mode failed on entry '+`entry`) + + if 'idea' in args: + ciph=exerciseBlockCipher('IDEA', verbose) # IDEA block cipher + if (ciph!=None): + if verbose: print ' Verifying against test suite...' + for entry in testdata.idea: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=ciph.new(key, ciph.MODE_ECB) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('IDEA failed on entry '+`entry`) + + if 'rc5' in args: + # Ronald Rivest's RC5 algorithm + ciph=exerciseBlockCipher('RC5', verbose) + if (ciph!=None): + if verbose: print ' Verifying against test suite...' + for entry in testdata.rc5: + key,plain,cipher=entry + key=binascii.a2b_hex(key) + plain=binascii.a2b_hex(plain) + cipher=binascii.a2b_hex(cipher) + obj=ciph.new(key[4:], ciph.MODE_ECB, + version =ord(key[0]), + word_size=ord(key[1]), + rounds =ord(key[2]) ) + ciphertext=obj.encrypt(plain) + if (ciphertext!=cipher): + die('RC5 failed on entry '+`entry`) + for i in ciphertext: + if verbose: print hex(ord(i)), + if verbose: print + + + diff --git a/src/Crypto/Util/test/prime_speed.py b/src/Crypto/Util/test/prime_speed.py new file mode 100644 index 00000000..672bd970 --- /dev/null +++ b/src/Crypto/Util/test/prime_speed.py @@ -0,0 +1,24 @@ + +import time +from allmydata.Crypto.Util import number + +# Test of prime-generation speed + +# This randfunc is deterministic, so we should always find the same primes. +chars = ''.join(map(chr, range(255, 0, -1))) +def randfunc (N): + s = '' + while len(s) Mon, 5 Jun 2006 16:45:58 -0700 + +python-crypto (2.0.1+dfsg1-1) unstable; urgency=low + + * Acknowlegde NMUs (closes: #318055, #318012). + * Packaged new upstream version (closes: #325517). + - 2.0.1 includes fix for AMD64, presumingly also closes: #297516. + + -- Andreas Rottmann Tue, 4 Oct 2005 00:10:40 +0200 + +python-crypto (2.0+dp1-2.3) unstable; urgency=low + + * NMU. + * Add python2.4-crypto package, drop python2.1 and python2.2 packages + (closes: #313349). + + -- Matthias Klose Mon, 29 Aug 2005 07:18:38 +0000 + +python-crypto (2.0+dp1-2.2) unstable; urgency=low + + * NMU to fix build failures on some architectures + * Remove -O3 gcc option on m68k architecture to fix FTBFS due to an + internal compiler error + * Standards version 3.6.2 (no changes required) + * Relax the versioned build dependency of libgmp3-dev to 4.1.4-8 + instead of -9. Some architectures only have -8 at this point + which is sufficient. + + -- Bastian Kleineidam Fri, 12 Aug 2005 11:04:21 +0200 + +python-crypto (2.0+dp1-2.1) unstable; urgency=low + + * NMU to make package installable again + * Added missing build dependency on (versioned) libgmp3-dev, otherwise + the _fastmath module won't be compiled. + * Recompile against libgmp3c2 (Closes: #318055) + + -- Bastian Kleineidam Tue, 9 Aug 2005 10:54:41 +0200 + +python-crypto (2.0+dp1-2) unstable; urgency=medium + + * Added missing build-dependency on tetex-bin and tetex-extra (closes: + #288602). + + -- Andreas Rottmann Tue, 4 Jan 2005 17:47:27 +0100 + +python-crypto (2.0+dp1-1) unstable; urgency=medium + + * Again remove problematic code from orig tarball, which the NMU did + miss (not to mention that the orig tarball from the NMU wasn't + pristine and contained .pyc files). Urgency medium, so sarge won't end + up with problematic code. + * Include the manual in binary packages (closes: #273622). + * Switch to CDBS. + * Lowercase description synopsis, as suggested by lintian/developer's + reference. + * Advertice the newly-included (since 2.0) SHA256 module in the + description. + + -- Andreas Rottmann Sat, 1 Jan 2005 14:47:12 +0100 + +python-crypto (2.0-1) unstable; urgency=medium + + * NMU. + * New upstream version. + + -- Matthias Klose Tue, 17 Aug 2004 23:44:24 +0200 + +python-crypto (1.9a6+dp2-1) unstable; urgency=low + + * Transitioned to Python 2.3. + * Removed accidential junk form .orig.tar.gz. + + -- Andreas Rottmann Sat, 9 Aug 2003 12:41:23 +0200 + +python-crypto (1.9a6+dp1-2) unstable; urgency=low + + * Fixed Section (python instead of interpreters). + + -- Andreas Rottmann Sun, 20 Jul 2003 15:21:37 +0200 + +python-crypto (1.9a6+dp1-1) unstable; urgency=low + + * New upstream release. + * Bump Standards-Version to 3.6.0 (no changes). + + -- Andreas Rottmann Sun, 13 Jul 2003 18:26:54 +0200 + +python-crypto (1.9a4+dp1-4) unstable; urgency=low + + * Use dh_python. + + Build-depend on debhelper >= 4.1.29. + + Build-depend on python. + * Bump Standards-Version to 3.5.8. + + -- Andreas Rottmann Thu, 20 Feb 2003 14:55:12 +0100 + +python-crypto (1.9a4+dp1-3) unstable; urgency=low + + * Cipher/__init__.py: Remove 'RC5' and 'IDEA' from __all__. + + -- Andreas Rottmann Fri, 14 Feb 2003 01:10:26 +0100 + +python-crypto (1.9a4+dp1-2) unstable; urgency=low + + * debian/control: Added python2.x dependencies to binary packages. + * debian/control: Fixed 'Cryptpgraphic' typo (closes: #162884). + + -- Andreas Rottmann Thu, 7 Nov 2002 22:05:27 +0100 + +python-crypto (1.9a4+dp1-1) unstable; urgency=low + + * Removed problematic algorithms from source code. + + Added README.Debian with details. + + Updated package descriptions. + * Include docs in all pythonX.Y-crypto packages. + + -- Andreas Rottmann Wed, 11 Sep 2002 13:15:45 +0200 + +python-crypto (1.9a4-1) unstable; urgency=low + + * Initial Release (closes: #159717) + + -- Andreas Rottmann Thu, 5 Sep 2002 14:53:33 +0200 + diff --git a/src/Crypto/debian/compat b/src/Crypto/debian/compat new file mode 100644 index 00000000..b8626c4c --- /dev/null +++ b/src/Crypto/debian/compat @@ -0,0 +1 @@ +4 diff --git a/src/Crypto/debian/control b/src/Crypto/debian/control new file mode 100644 index 00000000..1e6f4e1a --- /dev/null +++ b/src/Crypto/debian/control @@ -0,0 +1,60 @@ +Source: python-amdcrypto +Section: python +Priority: optional +Maintainer: Andreas Rottmann +Build-Depends: cdbs, debhelper (>= 4.2), python, python2.3-dev, python2.4-dev, ed, tetex-bin, tetex-extra, libgmp3-dev (>= 4.1.4-10) +Standards-Version: 3.6.2 + +Package: python-amdcrypto +Architecture: any +Depends: ${python:Depends} +Conflicts: python-crypto +Provides: python-crypto +Description: cryptographic algorithms and protocols for Python + A collection of cryptographic algorithms and protocols, implemented + for use from Python. Among the contents of the package: + . + * Hash functions: MD2, MD4. + * Block encryption algorithms: AES, ARC2, Blowfish, CAST, DES, Triple-DES. + * Stream encryption algorithms: ARC4, simple XOR. + * Public-key algorithms: RSA, DSA, ElGamal, qNEW. + * Protocols: All-or-nothing transforms, chaffing/winnowing. + * Miscellaneous: RFC1751 module for converting 128-key keys + into a set of English words, primality testing. + . + This is an empty dummy package that always depends on a package built + for Debian's default Python version. + +Package: python2.3-amdcrypto +Architecture: any +Depends: ${shlibs:Depends}, python2.3 +Conflicts: python2.3-crypto +Provides: python2.3-crypto +Description: cryptographic algorithms and protocols for Python + A collection of cryptographic algorithms and protocols, implemented + for use from Python. Among the contents of the package: + . + * Hash functions: MD2, MD4, SHA256. + * Block encryption algorithms: AES, ARC2, Blowfish, CAST, DES, Triple-DES. + * Stream encryption algorithms: ARC4, simple XOR. + * Public-key algorithms: RSA, DSA, ElGamal, qNEW. + * Protocols: All-or-nothing transforms, chaffing/winnowing. + * Miscellaneous: RFC1751 module for converting 128-key keys + into a set of English words, primality testing. + +Package: python2.4-amdcrypto +Architecture: any +Depends: ${shlibs:Depends}, python2.4 +Conflicts: python2.4-crypto +Provides: python2.4-crypto +Description: cryptographic algorithms and protocols for Python + A collection of cryptographic algorithms and protocols, implemented + for use from Python. Among the contents of the package: + . + * Hash functions: MD2, MD4. + * Block encryption algorithms: AES, ARC2, Blowfish, CAST, DES, Triple-DES. + * Stream encryption algorithms: ARC4, simple XOR. + * Public-key algorithms: RSA, DSA, ElGamal, qNEW. + * Protocols: All-or-nothing transforms, chaffing/winnowing. + * Miscellaneous: RFC1751 module for converting 128-key keys + into a set of English words, primality testing. diff --git a/src/Crypto/debian/copyright b/src/Crypto/debian/copyright new file mode 100644 index 00000000..7f39a182 --- /dev/null +++ b/src/Crypto/debian/copyright @@ -0,0 +1,20 @@ +This package was debianized by Andreas Rottmann on +Thu, 5 Sep 2002 14:53:33 +0200. + +It was downloaded from http://www.amk.ca/python/code/crypto.html + +Upstream Author: A.M. Kuchling + +Copyright: + +=================================================================== +Distribute and use freely; there are no restrictions on further +dissemination and usage except those imposed by the laws of your +country of residence. This software is provided "as is" without +warranty of fitness for use or suitability for any purpose, express +or implied. Use at your own risk or not at all. +=================================================================== + +Incorporating the code into commercial products is permitted; you do +not have to make source available or contribute your changes back +(though that would be nice). diff --git a/src/Crypto/debian/dirs b/src/Crypto/debian/dirs new file mode 100644 index 00000000..ca882bbb --- /dev/null +++ b/src/Crypto/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/src/Crypto/debian/pathmangle.sh b/src/Crypto/debian/pathmangle.sh new file mode 100644 index 00000000..32bf8ced --- /dev/null +++ b/src/Crypto/debian/pathmangle.sh @@ -0,0 +1,17 @@ +#! /bin/sh +# +# This script is used to mangle things like /usr/local/bin/python into +# something more in line with Debian's Python policy. + +set -e + +CMD=$1 +DIR=$2 + +grep -E -l -r '/usr/local(/bin)?/python' "$DIR" | + while read f; do + printf ",s:/usr/local\\\\(/bin\\\\)\\\\?/python:$CMD:g\nw\n" | ed -s "$f" + if [ "$(head -c2 $f)" = "#!" ]; then + chmod 755 "$f" + fi + done diff --git a/src/Crypto/debian/python2.3-amdcrypto.docs b/src/Crypto/debian/python2.3-amdcrypto.docs new file mode 100644 index 00000000..9b472891 --- /dev/null +++ b/src/Crypto/debian/python2.3-amdcrypto.docs @@ -0,0 +1,4 @@ +README +TODO +debian/README.Debian +Doc/pycrypt.ps diff --git a/src/Crypto/debian/python2.4-amdcrypto.docs b/src/Crypto/debian/python2.4-amdcrypto.docs new file mode 100644 index 00000000..9b472891 --- /dev/null +++ b/src/Crypto/debian/python2.4-amdcrypto.docs @@ -0,0 +1,4 @@ +README +TODO +debian/README.Debian +Doc/pycrypt.ps diff --git a/src/Crypto/debian/rules b/src/Crypto/debian/rules new file mode 100644 index 00000000..6520a8ff --- /dev/null +++ b/src/Crypto/debian/rules @@ -0,0 +1,17 @@ +#!/usr/bin/make -f + +include /usr/share/cdbs/1/rules/buildcore.mk +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/python-distutils.mk + +MKHOWTO = /usr/lib/python2.3/doc/tools/mkhowto + +common-build-arch:: + cd Doc && $(MKHOWTO) --ps + +$(patsubst %,binary-post-install/%,$(DEB_PYTHON_REAL_LIB_PACKAGES)):: + sh -e debian/pathmangle.sh /usr/bin/$(shell echo $(cdbs_curpkg) | sed 's,-crypto$$,,') debian/$(cdbs_curpkg) + +clean:: + rm -rf build + rm -f Doc/*.ps diff --git a/src/Crypto/setup.py b/src/Crypto/setup.py new file mode 100644 index 00000000..94f7a08e --- /dev/null +++ b/src/Crypto/setup.py @@ -0,0 +1,193 @@ +#! /usr/bin/env python + +__revision__ = "$Id: setup.py,v 1.30 2005/06/14 01:20:22 akuchling Exp $" + +from distutils import core +from distutils.core import Extension +from distutils.command.build_ext import build_ext +import os, sys + +if sys.version[0:1] == '1': + raise RuntimeError, ("The Python Cryptography Toolkit requires " + "Python 2.x to build.") + +debug_build_kw = {} + +DEBUG_BUILD=False +# DEBUG_BUILD=True +if DEBUG_BUILD: + debug_build_kw.update({ + 'extra_compile_args': ['-O0', '-g',], + 'extra_link_args': ['-g',], + 'undef_macros': ['NDEBUG',], }) + +if sys.platform == 'win32': + HTONS_LIBS = ['ws2_32'] + plat_ext = [ + Extension("Crypto.Util.winrandom", + libraries = HTONS_LIBS + ['advapi32'], + include_dirs=['src/'], + extra_compile_args=['-O0 -g',], + extra_link_args=['-g',], + undef_macros=['NDEBUG',], + sources=["src/winrand.c"], + **debug_build_kw) + ] +else: + HTONS_LIBS = [] + plat_ext = [] + +# Functions for finding libraries and files, copied from Python's setup.py. + +def find_file(filename, std_dirs, paths): + """Searches for the directory where a given file is located, + and returns a possibly-empty list of additional directories, or None + if the file couldn't be found at all. + + 'filename' is the name of a file, such as readline.h or libcrypto.a. + 'std_dirs' is the list of standard system directories; if the + file is found in one of them, no additional directives are needed. + 'paths' is a list of additional locations to check; if the file is + found in one of them, the resulting list will contain the directory. + """ + + # Check the standard locations + for dir in std_dirs: + f = os.path.join(dir, filename) + if os.path.exists(f): return [] + + # Check the additional directories + for dir in paths: + f = os.path.join(dir, filename) + if os.path.exists(f): + return [dir] + + # Not found anywhere + return None + +def find_library_file(compiler, libname, std_dirs, paths): + filename = compiler.library_filename(libname, lib_type='shared') + result = find_file(filename, std_dirs, paths) + if result is not None: return result + + filename = compiler.library_filename(libname, lib_type='static') + result = find_file(filename, std_dirs, paths) + return result + + +def cc_remove_option (compiler, option): + """ + Remove option from Unix-style compiler. + """ + for optlist in (compiler.compiler, compiler.compiler_so): + if option in optlist: + optlist.remove(option) + + +class PCTBuildExt (build_ext): + def build_extensions(self): + self.extensions += [ + # Hash functions + Extension("Crypto.Hash.MD4", + include_dirs=['src/'], + sources=["src/MD4.c"], + **debug_build_kw), + Extension("Crypto.Hash.SHA256", + include_dirs=['src/'], + sources=["src/SHA256.c"], + **debug_build_kw), + + # Block encryption algorithms + Extension("Crypto.Cipher.AES", + include_dirs=['src/'], + sources=["src/AES.c"], + **debug_build_kw), + Extension("Crypto.Cipher.ARC2", + include_dirs=['src/'], + sources=["src/ARC2.c"], + **debug_build_kw), + Extension("Crypto.Cipher.Blowfish", + include_dirs=['src/'], + sources=["src/Blowfish.c"], + **debug_build_kw), + Extension("Crypto.Cipher.CAST", + include_dirs=['src/'], + sources=["src/CAST.c"], + **debug_build_kw), + Extension("Crypto.Cipher.DES", + include_dirs=['src/'], + sources=["src/DES.c"], + **debug_build_kw), + Extension("Crypto.Cipher.DES3", + include_dirs=['src/'], + sources=["src/DES3.c"], + **debug_build_kw), + + # Stream ciphers + Extension("Crypto.Cipher.ARC4", + include_dirs=['src/'], + sources=["src/ARC4.c"], + **debug_build_kw), + Extension("Crypto.Cipher.XOR", + include_dirs=['src/'], + sources=["src/XOR.c"], + **debug_build_kw), + ] + + # Detect which modules should be compiled + self.detect_modules() + if self.compiler.compiler_type == 'unix': + if os.uname()[4] == 'm68k': + # work around ICE on m68k machines in gcc 4.0.1 + cc_remove_option(self.compiler, "-O3") + build_ext.build_extensions(self) + + def detect_modules (self): + lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib'] + inc_dirs = self.compiler.include_dirs + ['/usr/include'] + exts = [] + if (self.compiler.find_library_file(lib_dirs, 'gmp')): + exts.append(Extension("Crypto.PublicKey._fastmath", + include_dirs=['src/'], + libraries=['gmp'], + sources=["src/_fastmath.c"])) + self.extensions += exts + + +kw = {'name':"pycrypto", + 'version':"2.0.1", + 'description':"Cryptographic modules for Python.", + 'author':"A.M. Kuchling", + 'author_email':"amk@amk.ca", + 'url':"http://www.amk.ca/python/code/crypto", + + 'cmdclass' : {'build_ext':PCTBuildExt}, + 'packages' : ["Crypto", "Crypto.Hash", "Crypto.Cipher", "Crypto.Util", + "Crypto.Protocol", "Crypto.PublicKey"], + 'package_dir' : { "Crypto":"." }, + # One module is defined here, because build_ext won't be + # called unless there's at least one extension module defined. + 'ext_modules':[Extension("Crypto.Hash.MD2", + include_dirs=['src/'], + sources=["src/MD2.c"], + **debug_build_kw)] + } + +# If we're running Python 2.3, add extra information +if hasattr(core, 'setup_keywords'): + if 'classifiers' in core.setup_keywords: + kw['classifiers'] = [ + 'Development Status :: 4 - Beta', + 'License :: Public Domain', + 'Intended Audience :: Developers', + 'Operating System :: Unix', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: MacOS :: MacOS X', + 'Topic :: Security :: Cryptography', + ] + if 'download_url' in core.setup_keywords: + kw['download_url'] = ('http://www.amk.ca/files/python/crypto/' + '%s-%s.tar.gz' % (kw['name'], kw['version']) ) + +core.setup(**kw) + diff --git a/src/Crypto/src/AES.c b/src/Crypto/src/AES.c new file mode 100644 index 00000000..cf9bba9f --- /dev/null +++ b/src/Crypto/src/AES.c @@ -0,0 +1,1459 @@ +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ + +#include +#include +#include "Python.h" + +#define MODULE_NAME AES +#define BLOCK_SIZE 16 +#define KEY_SIZE 0 + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +typedef struct { + u32 ek[ 4*(MAXNR+1) ]; + u32 dk[ 4*(MAXNR+1) ]; + int rounds; +} block_state; + +void rijndaelEncrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]); +void rijndaelDecrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]); + +#ifdef INTERMEDIATE_VALUE_KAT +void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); +void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); +#endif /* INTERMEDIATE_VALUE_KAT */ + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) + +#ifdef _MSC_VER +#define GETU32(p) SWAP(*((u32 *)(p))) +#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ + +int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { + int i = 0; + u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 10; + } + rk += 4; + } + } + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + if (keyBits == 192) { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + if (keyBits == 256) { + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { + int Nr, i, j; + u32 temp; + + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return Nr; +} + +void rijndaelEncrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); +} + +void rijndaelDecrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct ) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(pt , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(pt + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(pt + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(pt + 12, s3); +} + +#ifdef INTERMEDIATE_VALUE_KAT + +void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { + int r; + u32 s0, s1, s2, s3, t0, t1, t2, t3; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(block ) ^ rk[0]; + s1 = GETU32(block + 4) ^ rk[1]; + s2 = GETU32(block + 8) ^ rk[2]; + s3 = GETU32(block + 12) ^ rk[3]; + rk += 4; + + /* + * Nr - 1 full rounds: + */ + for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[0]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[1]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[2]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + rk += 4; + + } + + /* + * apply last round and + * map cipher state to byte array block: + */ + if (rounds == Nr) { + t0 = + (Te4[(s0 >> 24) ] & 0xff000000) ^ + (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + t1 = + (Te4[(s1 >> 24) ] & 0xff000000) ^ + (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + t2 = + (Te4[(s2 >> 24) ] & 0xff000000) ^ + (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + t3 = + (Te4[(s3 >> 24) ] & 0xff000000) ^ + (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + PUTU32(block , s0); + PUTU32(block + 4, s1); + PUTU32(block + 8, s2); + PUTU32(block + 12, s3); +} + +void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { + int r; + u32 s0, s1, s2, s3, t0, t1, t2, t3; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(block ) ^ rk[0]; + s1 = GETU32(block + 4) ^ rk[1]; + s2 = GETU32(block + 8) ^ rk[2]; + s3 = GETU32(block + 12) ^ rk[3]; + rk += 4; + + /* + * Nr - 1 full rounds: + */ + for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[0]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[1]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[2]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + rk += 4; + + } + + /* + * complete the last round and + * map cipher state to byte array block: + */ + t0 = + (Td4[(s0 >> 24) ] & 0xff000000) ^ + (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s1 ) & 0xff] & 0x000000ff); + t1 = + (Td4[(s1 >> 24) ] & 0xff000000) ^ + (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s2 ) & 0xff] & 0x000000ff); + t2 = + (Td4[(s2 >> 24) ] & 0xff000000) ^ + (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s3 ) & 0xff] & 0x000000ff); + t3 = + (Td4[(s3 >> 24) ] & 0xff000000) ^ + (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s0 ) & 0xff] & 0x000000ff); + + if (rounds == Nr) { + t0 ^= rk[0]; + t1 ^= rk[1]; + t2 ^= rk[2]; + t3 ^= rk[3]; + } + + PUTU32(block , t0); + PUTU32(block + 4, t1); + PUTU32(block + 8, t2); + PUTU32(block + 12, t3); +} + +#endif /* INTERMEDIATE_VALUE_KAT */ + +static void block_init(block_state *state, unsigned char *key, + int keylen) +{ + int Nr = 0; + + if (keylen != 16 && keylen != 24 && keylen != 32) { + PyErr_SetString(PyExc_ValueError, + "AES key must be either 16, 24, or 32 bytes long"); + return; + } + switch (keylen) { + case(16): Nr = 10; break; + case(24): Nr = 12; break; + case(32): Nr = 14; break; + } + state->rounds = Nr; + rijndaelKeySetupEnc(state->ek, key, keylen*8); + rijndaelKeySetupDec(state->dk, key, keylen*8); +} + +static void block_encrypt(block_state *self, u8 *in, u8 *out) +{ + rijndaelEncrypt(self->ek, self->rounds, in, out); +} + +static void block_decrypt(block_state *self, u8 *in, u8 *out) +{ + rijndaelDecrypt(self->dk, self->rounds, in, out); +} + +#include "block_template.c" diff --git a/src/Crypto/src/ARC2.c b/src/Crypto/src/ARC2.c new file mode 100644 index 00000000..f1292e82 --- /dev/null +++ b/src/Crypto/src/ARC2.c @@ -0,0 +1,185 @@ + +/* + * rc2.c : Source code for the RC2 block cipher + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#include + +#define MODULE_NAME ARC2 +#define BLOCK_SIZE 8 +#define KEY_SIZE 0 + +typedef unsigned int U32; +typedef unsigned short U16; +typedef unsigned char U8; + +typedef struct +{ + U16 xkey[64]; +} block_state; + +static void +block_encrypt(block_state *self, U8 *in, U8 *out) +{ + U16 x76, x54, x32, x10; + int i; + + x76 = (in[7] << 8) + in[6]; + x54 = (in[5] << 8) + in[4]; + x32 = (in[3] << 8) + in[2]; + x10 = (in[1] << 8) + in[0]; + + for (i = 0; i < 16; i++) + { + x10 += (x32 & ~x76) + (x54 & x76) + self->xkey[4*i+0]; + x10 = (x10 << 1) + (x10 >> 15 & 1); + + x32 += (x54 & ~x10) + (x76 & x10) + self->xkey[4*i+1]; + x32 = (x32 << 2) + (x32 >> 14 & 3); + + x54 += (x76 & ~x32) + (x10 & x32) + self->xkey[4*i+2]; + x54 = (x54 << 3) + (x54 >> 13 & 7); + + x76 += (x10 & ~x54) + (x32 & x54) + self->xkey[4*i+3]; + x76 = (x76 << 5) + (x76 >> 11 & 31); + + if (i == 4 || i == 10) { + x10 += self->xkey[x76 & 63]; + x32 += self->xkey[x10 & 63]; + x54 += self->xkey[x32 & 63]; + x76 += self->xkey[x54 & 63]; + } + } + + out[0] = (U8)x10; + out[1] = (U8)(x10 >> 8); + out[2] = (U8)x32; + out[3] = (U8)(x32 >> 8); + out[4] = (U8)x54; + out[5] = (U8)(x54 >> 8); + out[6] = (U8)x76; + out[7] = (U8)(x76 >> 8); +} + + +static void +block_decrypt(block_state *self, U8 *in, U8 *out) +{ + U16 x76, x54, x32, x10; + int i; + + x76 = (in[7] << 8) + in[6]; + x54 = (in[5] << 8) + in[4]; + x32 = (in[3] << 8) + in[2]; + x10 = (in[1] << 8) + in[0]; + + i = 15; + do { + x76 &= 65535; + x76 = (x76 << 11) + (x76 >> 5); + x76 -= (x10 & ~x54) + (x32 & x54) + self->xkey[4*i+3]; + + x54 &= 65535; + x54 = (x54 << 13) + (x54 >> 3); + x54 -= (x76 & ~x32) + (x10 & x32) + self->xkey[4*i+2]; + + x32 &= 65535; + x32 = (x32 << 14) + (x32 >> 2); + x32 -= (x54 & ~x10) + (x76 & x10) + self->xkey[4*i+1]; + + x10 &= 65535; + x10 = (x10 << 15) + (x10 >> 1); + x10 -= (x32 & ~x76) + (x54 & x76) + self->xkey[4*i+0]; + + if (i == 5 || i == 11) { + x76 -= self->xkey[x54 & 63]; + x54 -= self->xkey[x32 & 63]; + x32 -= self->xkey[x10 & 63]; + x10 -= self->xkey[x76 & 63]; + } + } while (i--); + + out[0] = (U8)x10; + out[1] = (U8)(x10 >> 8); + out[2] = (U8)x32; + out[3] = (U8)(x32 >> 8); + out[4] = (U8)x54; + out[5] = (U8)(x54 >> 8); + out[6] = (U8)x76; + out[7] = (U8)(x76 >> 8); +} + + +static void +block_init(block_state *self, U8 *key, int keylength) +{ + U8 x; + U16 i; + /* 256-entry permutation table, probably derived somehow from pi */ + static const U8 permute[256] = { + 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, + 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, + 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, + 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, + 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, + 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, + 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, + 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, + 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, + 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, + 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, + 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, + 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, + 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, + 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, + 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 + }; + + /* The "bits" value may be some sort of export control weakening. + We'll hardwire it to 1024. */ +#define bits 1024 + + memcpy(self->xkey, key, keylength); + + /* Phase 1: Expand input key to 128 bytes */ + if (keylength < 128) { + i = 0; + x = ((U8 *)self->xkey)[keylength-1]; + do { + x = permute[(x + ((U8 *)self->xkey)[i++]) & 255]; + ((U8 *)self->xkey)[keylength++] = x; + } while (keylength < 128); + } + + /* Phase 2 - reduce effective key size to "bits" */ + keylength = (bits+7) >> 3; + i = 128-keylength; + x = permute[((U8 *)self->xkey)[i] & (255 >> + (7 & + ((bits %8 ) ? 8-(bits%8): 0)) + )]; + ((U8 *)self->xkey)[i] = x; + + while (i--) { + x = permute[ x ^ ((U8 *)self->xkey)[i+keylength] ]; + ((U8 *)self->xkey)[i] = x; + } + + /* Phase 3 - copy to self->xkey in little-endian order */ + i = 63; + do { + self->xkey[i] = ((U8 *)self->xkey)[2*i] + + (((U8 *)self->xkey)[2*i+1] << 8); + } while (i--); +} + +#undef bits + +#include "block_template.c" diff --git a/src/Crypto/src/ARC4.c b/src/Crypto/src/ARC4.c new file mode 100644 index 00000000..71df6fe7 --- /dev/null +++ b/src/Crypto/src/ARC4.c @@ -0,0 +1,72 @@ + +/* + * arc4.c : Implementation for the Alleged-RC4 stream cipher + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#define MODULE_NAME ARC4 +#define BLOCK_SIZE 1 +#define KEY_SIZE 0 + +typedef struct +{ + unsigned char state[256]; + unsigned char x,y; +} stream_state; + +/* Encryption and decryption are symmetric */ +#define stream_decrypt stream_encrypt + +static void stream_encrypt(stream_state *self, unsigned char *block, + int len) +{ + register int i, x=self->x, y=self->y; + + for (i=0; istate[x]) % 256; + { + register int t; /* Exchange state[x] and state[y] */ + t = self->state[x]; + self->state[x] = self->state[y]; + self->state[y] = t; + } + { + register int xorIndex; /* XOR the data with the stream data */ + xorIndex=(self->state[x]+self->state[y]) % 256; + block[i] ^= self->state[xorIndex]; + } + } + self->x=x; + self->y=y; +} + + +static void stream_init(stream_state *self, unsigned char *key, int keylen) +{ + register int i, index1, index2; + + for(i=0; i<256; i++) self->state[i]=i; + self->x=0; self->y=0; + index1=0; index2=0; + for(i=0; i<256; i++) + { + register int t; + index2 = ( key[index1] + self->state[i] + index2) % 256; + t = self->state[i]; + self->state[i] = self->state[index2]; + self->state[index2] = t; + index1 = (index1 + 1) % keylen; + } +} + +#include "stream_template.c" + + diff --git a/src/Crypto/src/Blowfish.c b/src/Crypto/src/Blowfish.c new file mode 100644 index 00000000..df69afad --- /dev/null +++ b/src/Crypto/src/Blowfish.c @@ -0,0 +1,499 @@ + +/* + * blowfish.c : Source code for the Blowfish block cipher + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +/*************************************************************************/ +/* File: bf.c + Blowfish cipher by Bruce Schneier, + Code by Bryan Olson, based partly on Schneier's. +*/ + +#include "Python.h" + +#define MODULE_NAME Blowfish +#define BLOCK_SIZE 8 +#define KEY_SIZE 0 + +/* Define IntU32 to be an unsigned in 32 bits long */ +typedef unsigned int IntU32 ; +typedef unsigned char IntU8 ; +#define NROUNDS 16 + + + +/* Define IntP to be an integer which + is the same size as a pointer. */ +typedef unsigned long IntP ; + + +typedef struct +{ + IntU32 p[2][NROUNDS+2], + sbox[4][256] ; +} BFkey_type ; + +typedef struct +{ + BFkey_type bfkey; +} block_state; + +/* File bfinit.h + Data to initialize P and S in BlowFish. +*/ + +static IntU32 p_init[NROUNDS+2] = +{ + 608135816UL, 2242054355UL, 320440878UL, 57701188UL, + 2752067618UL, 698298832UL, 137296536UL, 3964562569UL, + 1160258022UL, 953160567UL, 3193202383UL, 887688300UL, + 3232508343UL, 3380367581UL, 1065670069UL, 3041331479UL, + 2450970073UL, 2306472731UL +} ; + +static IntU32 s_init[4][256] = { + {3509652390UL, 2564797868UL, 805139163UL, 3491422135UL, + 3101798381UL, 1780907670UL, 3128725573UL, 4046225305UL, + 614570311UL, 3012652279UL, 134345442UL, 2240740374UL, + 1667834072UL, 1901547113UL, 2757295779UL, 4103290238UL, + 227898511UL, 1921955416UL, 1904987480UL, 2182433518UL, + 2069144605UL, 3260701109UL, 2620446009UL, 720527379UL, + 3318853667UL, 677414384UL, 3393288472UL, 3101374703UL, + 2390351024UL, 1614419982UL, 1822297739UL, 2954791486UL, + 3608508353UL, 3174124327UL, 2024746970UL, 1432378464UL, + 3864339955UL, 2857741204UL, 1464375394UL, 1676153920UL, + 1439316330UL, 715854006UL, 3033291828UL, 289532110UL, + 2706671279UL, 2087905683UL, 3018724369UL, 1668267050UL, + 732546397UL, 1947742710UL, 3462151702UL, 2609353502UL, + 2950085171UL, 1814351708UL, 2050118529UL, 680887927UL, + 999245976UL, 1800124847UL, 3300911131UL, 1713906067UL, + 1641548236UL, 4213287313UL, 1216130144UL, 1575780402UL, + 4018429277UL, 3917837745UL, 3693486850UL, 3949271944UL, + 596196993UL, 3549867205UL, 258830323UL, 2213823033UL, + 772490370UL, 2760122372UL, 1774776394UL, 2652871518UL, + 566650946UL, 4142492826UL, 1728879713UL, 2882767088UL, + 1783734482UL, 3629395816UL, 2517608232UL, 2874225571UL, + 1861159788UL, 326777828UL, 3124490320UL, 2130389656UL, + 2716951837UL, 967770486UL, 1724537150UL, 2185432712UL, + 2364442137UL, 1164943284UL, 2105845187UL, 998989502UL, + 3765401048UL, 2244026483UL, 1075463327UL, 1455516326UL, + 1322494562UL, 910128902UL, 469688178UL, 1117454909UL, + 936433444UL, 3490320968UL, 3675253459UL, 1240580251UL, + 122909385UL, 2157517691UL, 634681816UL, 4142456567UL, + 3825094682UL, 3061402683UL, 2540495037UL, 79693498UL, + 3249098678UL, 1084186820UL, 1583128258UL, 426386531UL, + 1761308591UL, 1047286709UL, 322548459UL, 995290223UL, + 1845252383UL, 2603652396UL, 3431023940UL, 2942221577UL, + 3202600964UL, 3727903485UL, 1712269319UL, 422464435UL, + 3234572375UL, 1170764815UL, 3523960633UL, 3117677531UL, + 1434042557UL, 442511882UL, 3600875718UL, 1076654713UL, + 1738483198UL, 4213154764UL, 2393238008UL, 3677496056UL, + 1014306527UL, 4251020053UL, 793779912UL, 2902807211UL, + 842905082UL, 4246964064UL, 1395751752UL, 1040244610UL, + 2656851899UL, 3396308128UL, 445077038UL, 3742853595UL, + 3577915638UL, 679411651UL, 2892444358UL, 2354009459UL, + 1767581616UL, 3150600392UL, 3791627101UL, 3102740896UL, + 284835224UL, 4246832056UL, 1258075500UL, 768725851UL, + 2589189241UL, 3069724005UL, 3532540348UL, 1274779536UL, + 3789419226UL, 2764799539UL, 1660621633UL, 3471099624UL, + 4011903706UL, 913787905UL, 3497959166UL, 737222580UL, + 2514213453UL, 2928710040UL, 3937242737UL, 1804850592UL, + 3499020752UL, 2949064160UL, 2386320175UL, 2390070455UL, + 2415321851UL, 4061277028UL, 2290661394UL, 2416832540UL, + 1336762016UL, 1754252060UL, 3520065937UL, 3014181293UL, + 791618072UL, 3188594551UL, 3933548030UL, 2332172193UL, + 3852520463UL, 3043980520UL, 413987798UL, 3465142937UL, + 3030929376UL, 4245938359UL, 2093235073UL, 3534596313UL, + 375366246UL, 2157278981UL, 2479649556UL, 555357303UL, + 3870105701UL, 2008414854UL, 3344188149UL, 4221384143UL, + 3956125452UL, 2067696032UL, 3594591187UL, 2921233993UL, + 2428461UL, 544322398UL, 577241275UL, 1471733935UL, + 610547355UL, 4027169054UL, 1432588573UL, 1507829418UL, + 2025931657UL, 3646575487UL, 545086370UL, 48609733UL, + 2200306550UL, 1653985193UL, 298326376UL, 1316178497UL, + 3007786442UL, 2064951626UL, 458293330UL, 2589141269UL, + 3591329599UL, 3164325604UL, 727753846UL, 2179363840UL, + 146436021UL, 1461446943UL, 4069977195UL, 705550613UL, + 3059967265UL, 3887724982UL, 4281599278UL, 3313849956UL, + 1404054877UL, 2845806497UL, 146425753UL, 1854211946UL}, + + { 1266315497UL, 3048417604UL, 3681880366UL, 3289982499UL, + 2909710000UL, 1235738493UL, 2632868024UL, 2414719590UL, + 3970600049UL, 1771706367UL, 1449415276UL, 3266420449UL, + 422970021UL, 1963543593UL, 2690192192UL, 3826793022UL, + 1062508698UL, 1531092325UL, 1804592342UL, 2583117782UL, + 2714934279UL, 4024971509UL, 1294809318UL, 4028980673UL, + 1289560198UL, 2221992742UL, 1669523910UL, 35572830UL, + 157838143UL, 1052438473UL, 1016535060UL, 1802137761UL, + 1753167236UL, 1386275462UL, 3080475397UL, 2857371447UL, + 1040679964UL, 2145300060UL, 2390574316UL, 1461121720UL, + 2956646967UL, 4031777805UL, 4028374788UL, 33600511UL, + 2920084762UL, 1018524850UL, 629373528UL, 3691585981UL, + 3515945977UL, 2091462646UL, 2486323059UL, 586499841UL, + 988145025UL, 935516892UL, 3367335476UL, 2599673255UL, + 2839830854UL, 265290510UL, 3972581182UL, 2759138881UL, + 3795373465UL, 1005194799UL, 847297441UL, 406762289UL, + 1314163512UL, 1332590856UL, 1866599683UL, 4127851711UL, + 750260880UL, 613907577UL, 1450815602UL, 3165620655UL, + 3734664991UL, 3650291728UL, 3012275730UL, 3704569646UL, + 1427272223UL, 778793252UL, 1343938022UL, 2676280711UL, + 2052605720UL, 1946737175UL, 3164576444UL, 3914038668UL, + 3967478842UL, 3682934266UL, 1661551462UL, 3294938066UL, + 4011595847UL, 840292616UL, 3712170807UL, 616741398UL, + 312560963UL, 711312465UL, 1351876610UL, 322626781UL, + 1910503582UL, 271666773UL, 2175563734UL, 1594956187UL, + 70604529UL, 3617834859UL, 1007753275UL, 1495573769UL, + 4069517037UL, 2549218298UL, 2663038764UL, 504708206UL, + 2263041392UL, 3941167025UL, 2249088522UL, 1514023603UL, + 1998579484UL, 1312622330UL, 694541497UL, 2582060303UL, + 2151582166UL, 1382467621UL, 776784248UL, 2618340202UL, + 3323268794UL, 2497899128UL, 2784771155UL, 503983604UL, + 4076293799UL, 907881277UL, 423175695UL, 432175456UL, + 1378068232UL, 4145222326UL, 3954048622UL, 3938656102UL, + 3820766613UL, 2793130115UL, 2977904593UL, 26017576UL, + 3274890735UL, 3194772133UL, 1700274565UL, 1756076034UL, + 4006520079UL, 3677328699UL, 720338349UL, 1533947780UL, + 354530856UL, 688349552UL, 3973924725UL, 1637815568UL, + 332179504UL, 3949051286UL, 53804574UL, 2852348879UL, + 3044236432UL, 1282449977UL, 3583942155UL, 3416972820UL, + 4006381244UL, 1617046695UL, 2628476075UL, 3002303598UL, + 1686838959UL, 431878346UL, 2686675385UL, 1700445008UL, + 1080580658UL, 1009431731UL, 832498133UL, 3223435511UL, + 2605976345UL, 2271191193UL, 2516031870UL, 1648197032UL, + 4164389018UL, 2548247927UL, 300782431UL, 375919233UL, + 238389289UL, 3353747414UL, 2531188641UL, 2019080857UL, + 1475708069UL, 455242339UL, 2609103871UL, 448939670UL, + 3451063019UL, 1395535956UL, 2413381860UL, 1841049896UL, + 1491858159UL, 885456874UL, 4264095073UL, 4001119347UL, + 1565136089UL, 3898914787UL, 1108368660UL, 540939232UL, + 1173283510UL, 2745871338UL, 3681308437UL, 4207628240UL, + 3343053890UL, 4016749493UL, 1699691293UL, 1103962373UL, + 3625875870UL, 2256883143UL, 3830138730UL, 1031889488UL, + 3479347698UL, 1535977030UL, 4236805024UL, 3251091107UL, + 2132092099UL, 1774941330UL, 1199868427UL, 1452454533UL, + 157007616UL, 2904115357UL, 342012276UL, 595725824UL, + 1480756522UL, 206960106UL, 497939518UL, 591360097UL, + 863170706UL, 2375253569UL, 3596610801UL, 1814182875UL, + 2094937945UL, 3421402208UL, 1082520231UL, 3463918190UL, + 2785509508UL, 435703966UL, 3908032597UL, 1641649973UL, + 2842273706UL, 3305899714UL, 1510255612UL, 2148256476UL, + 2655287854UL, 3276092548UL, 4258621189UL, 236887753UL, + 3681803219UL, 274041037UL, 1734335097UL, 3815195456UL, + 3317970021UL, 1899903192UL, 1026095262UL, 4050517792UL, + 356393447UL, 2410691914UL, 3873677099UL, 3682840055UL}, + + { 3913112168UL, 2491498743UL, 4132185628UL, 2489919796UL, + 1091903735UL, 1979897079UL, 3170134830UL, 3567386728UL, + 3557303409UL, 857797738UL, 1136121015UL, 1342202287UL, + 507115054UL, 2535736646UL, 337727348UL, 3213592640UL, + 1301675037UL, 2528481711UL, 1895095763UL, 1721773893UL, + 3216771564UL, 62756741UL, 2142006736UL, 835421444UL, + 2531993523UL, 1442658625UL, 3659876326UL, 2882144922UL, + 676362277UL, 1392781812UL, 170690266UL, 3921047035UL, + 1759253602UL, 3611846912UL, 1745797284UL, 664899054UL, + 1329594018UL, 3901205900UL, 3045908486UL, 2062866102UL, + 2865634940UL, 3543621612UL, 3464012697UL, 1080764994UL, + 553557557UL, 3656615353UL, 3996768171UL, 991055499UL, + 499776247UL, 1265440854UL, 648242737UL, 3940784050UL, + 980351604UL, 3713745714UL, 1749149687UL, 3396870395UL, + 4211799374UL, 3640570775UL, 1161844396UL, 3125318951UL, + 1431517754UL, 545492359UL, 4268468663UL, 3499529547UL, + 1437099964UL, 2702547544UL, 3433638243UL, 2581715763UL, + 2787789398UL, 1060185593UL, 1593081372UL, 2418618748UL, + 4260947970UL, 69676912UL, 2159744348UL, 86519011UL, + 2512459080UL, 3838209314UL, 1220612927UL, 3339683548UL, + 133810670UL, 1090789135UL, 1078426020UL, 1569222167UL, + 845107691UL, 3583754449UL, 4072456591UL, 1091646820UL, + 628848692UL, 1613405280UL, 3757631651UL, 526609435UL, + 236106946UL, 48312990UL, 2942717905UL, 3402727701UL, + 1797494240UL, 859738849UL, 992217954UL, 4005476642UL, + 2243076622UL, 3870952857UL, 3732016268UL, 765654824UL, + 3490871365UL, 2511836413UL, 1685915746UL, 3888969200UL, + 1414112111UL, 2273134842UL, 3281911079UL, 4080962846UL, + 172450625UL, 2569994100UL, 980381355UL, 4109958455UL, + 2819808352UL, 2716589560UL, 2568741196UL, 3681446669UL, + 3329971472UL, 1835478071UL, 660984891UL, 3704678404UL, + 4045999559UL, 3422617507UL, 3040415634UL, 1762651403UL, + 1719377915UL, 3470491036UL, 2693910283UL, 3642056355UL, + 3138596744UL, 1364962596UL, 2073328063UL, 1983633131UL, + 926494387UL, 3423689081UL, 2150032023UL, 4096667949UL, + 1749200295UL, 3328846651UL, 309677260UL, 2016342300UL, + 1779581495UL, 3079819751UL, 111262694UL, 1274766160UL, + 443224088UL, 298511866UL, 1025883608UL, 3806446537UL, + 1145181785UL, 168956806UL, 3641502830UL, 3584813610UL, + 1689216846UL, 3666258015UL, 3200248200UL, 1692713982UL, + 2646376535UL, 4042768518UL, 1618508792UL, 1610833997UL, + 3523052358UL, 4130873264UL, 2001055236UL, 3610705100UL, + 2202168115UL, 4028541809UL, 2961195399UL, 1006657119UL, + 2006996926UL, 3186142756UL, 1430667929UL, 3210227297UL, + 1314452623UL, 4074634658UL, 4101304120UL, 2273951170UL, + 1399257539UL, 3367210612UL, 3027628629UL, 1190975929UL, + 2062231137UL, 2333990788UL, 2221543033UL, 2438960610UL, + 1181637006UL, 548689776UL, 2362791313UL, 3372408396UL, + 3104550113UL, 3145860560UL, 296247880UL, 1970579870UL, + 3078560182UL, 3769228297UL, 1714227617UL, 3291629107UL, + 3898220290UL, 166772364UL, 1251581989UL, 493813264UL, + 448347421UL, 195405023UL, 2709975567UL, 677966185UL, + 3703036547UL, 1463355134UL, 2715995803UL, 1338867538UL, + 1343315457UL, 2802222074UL, 2684532164UL, 233230375UL, + 2599980071UL, 2000651841UL, 3277868038UL, 1638401717UL, + 4028070440UL, 3237316320UL, 6314154UL, 819756386UL, + 300326615UL, 590932579UL, 1405279636UL, 3267499572UL, + 3150704214UL, 2428286686UL, 3959192993UL, 3461946742UL, + 1862657033UL, 1266418056UL, 963775037UL, 2089974820UL, + 2263052895UL, 1917689273UL, 448879540UL, 3550394620UL, + 3981727096UL, 150775221UL, 3627908307UL, 1303187396UL, + 508620638UL, 2975983352UL, 2726630617UL, 1817252668UL, + 1876281319UL, 1457606340UL, 908771278UL, 3720792119UL, + 3617206836UL, 2455994898UL, 1729034894UL, 1080033504UL}, + + { 976866871UL, 3556439503UL, 2881648439UL, 1522871579UL, + 1555064734UL, 1336096578UL, 3548522304UL, 2579274686UL, + 3574697629UL, 3205460757UL, 3593280638UL, 3338716283UL, + 3079412587UL, 564236357UL, 2993598910UL, 1781952180UL, + 1464380207UL, 3163844217UL, 3332601554UL, 1699332808UL, + 1393555694UL, 1183702653UL, 3581086237UL, 1288719814UL, + 691649499UL, 2847557200UL, 2895455976UL, 3193889540UL, + 2717570544UL, 1781354906UL, 1676643554UL, 2592534050UL, + 3230253752UL, 1126444790UL, 2770207658UL, 2633158820UL, + 2210423226UL, 2615765581UL, 2414155088UL, 3127139286UL, + 673620729UL, 2805611233UL, 1269405062UL, 4015350505UL, + 3341807571UL, 4149409754UL, 1057255273UL, 2012875353UL, + 2162469141UL, 2276492801UL, 2601117357UL, 993977747UL, + 3918593370UL, 2654263191UL, 753973209UL, 36408145UL, + 2530585658UL, 25011837UL, 3520020182UL, 2088578344UL, + 530523599UL, 2918365339UL, 1524020338UL, 1518925132UL, + 3760827505UL, 3759777254UL, 1202760957UL, 3985898139UL, + 3906192525UL, 674977740UL, 4174734889UL, 2031300136UL, + 2019492241UL, 3983892565UL, 4153806404UL, 3822280332UL, + 352677332UL, 2297720250UL, 60907813UL, 90501309UL, + 3286998549UL, 1016092578UL, 2535922412UL, 2839152426UL, + 457141659UL, 509813237UL, 4120667899UL, 652014361UL, + 1966332200UL, 2975202805UL, 55981186UL, 2327461051UL, + 676427537UL, 3255491064UL, 2882294119UL, 3433927263UL, + 1307055953UL, 942726286UL, 933058658UL, 2468411793UL, + 3933900994UL, 4215176142UL, 1361170020UL, 2001714738UL, + 2830558078UL, 3274259782UL, 1222529897UL, 1679025792UL, + 2729314320UL, 3714953764UL, 1770335741UL, 151462246UL, + 3013232138UL, 1682292957UL, 1483529935UL, 471910574UL, + 1539241949UL, 458788160UL, 3436315007UL, 1807016891UL, + 3718408830UL, 978976581UL, 1043663428UL, 3165965781UL, + 1927990952UL, 4200891579UL, 2372276910UL, 3208408903UL, + 3533431907UL, 1412390302UL, 2931980059UL, 4132332400UL, + 1947078029UL, 3881505623UL, 4168226417UL, 2941484381UL, + 1077988104UL, 1320477388UL, 886195818UL, 18198404UL, + 3786409000UL, 2509781533UL, 112762804UL, 3463356488UL, + 1866414978UL, 891333506UL, 18488651UL, 661792760UL, + 1628790961UL, 3885187036UL, 3141171499UL, 876946877UL, + 2693282273UL, 1372485963UL, 791857591UL, 2686433993UL, + 3759982718UL, 3167212022UL, 3472953795UL, 2716379847UL, + 445679433UL, 3561995674UL, 3504004811UL, 3574258232UL, + 54117162UL, 3331405415UL, 2381918588UL, 3769707343UL, + 4154350007UL, 1140177722UL, 4074052095UL, 668550556UL, + 3214352940UL, 367459370UL, 261225585UL, 2610173221UL, + 4209349473UL, 3468074219UL, 3265815641UL, 314222801UL, + 3066103646UL, 3808782860UL, 282218597UL, 3406013506UL, + 3773591054UL, 379116347UL, 1285071038UL, 846784868UL, + 2669647154UL, 3771962079UL, 3550491691UL, 2305946142UL, + 453669953UL, 1268987020UL, 3317592352UL, 3279303384UL, + 3744833421UL, 2610507566UL, 3859509063UL, 266596637UL, + 3847019092UL, 517658769UL, 3462560207UL, 3443424879UL, + 370717030UL, 4247526661UL, 2224018117UL, 4143653529UL, + 4112773975UL, 2788324899UL, 2477274417UL, 1456262402UL, + 2901442914UL, 1517677493UL, 1846949527UL, 2295493580UL, + 3734397586UL, 2176403920UL, 1280348187UL, 1908823572UL, + 3871786941UL, 846861322UL, 1172426758UL, 3287448474UL, + 3383383037UL, 1655181056UL, 3139813346UL, 901632758UL, + 1897031941UL, 2986607138UL, 3066810236UL, 3447102507UL, + 1393639104UL, 373351379UL, 950779232UL, 625454576UL, + 3124240540UL, 4148612726UL, 2007998917UL, 544563296UL, + 2244738638UL, 2330496472UL, 2058025392UL, 1291430526UL, + 424198748UL, 50039436UL, 29584100UL, 3605783033UL, + 2429876329UL, 2791104160UL, 1057563949UL, 3255363231UL, + 3075367218UL, 3463963227UL, 1469046755UL, 985887462UL} +} ; + +/* sLb(s,n) allows us to subsript s by byte offsets, which + allows us to avoid a subscript scaling. +*/ +#define sub(s,n) *((IntU32 *)((IntP)s+(n))) + +/* Below is one BlowFish round including the F function +*/ +#define bf_round(l,r,n) \ + l ^= P[n]; \ + r ^= ( (sub(S[0],l>>22 & 0x3fc) + sub(S[1],l>>14 & 0x3fc)) \ + ^ sub(S[2],l>>6 & 0x3fc) ) +S[3][l & 0xff] + + + +/* This function requires the block to be two 32 bit integers, in +whatever endian form the machine uses. On little endian machines +use crypt_8bytes() on user data. make_bfkey should call crypt_block +on either endian machine. Pass direction 0 to encrypt, 1 to decrypt. +*/ +static void crypt_block(IntU32 block[2], BFkey_type *bfkey, int direction) +{ + register IntU32 left, right, + (*S)[256], + *P ; + + left = block[0] ; right = block[1] ; + + S = bfkey->sbox ; + P = bfkey->p[direction] ; + + bf_round( left, right, 0 ) ; bf_round( right, left, 1 ) ; + bf_round( left, right, 2 ) ; bf_round( right, left, 3 ) ; + bf_round( left, right, 4 ) ; bf_round( right, left, 5 ) ; + bf_round( left, right, 6 ) ; bf_round( right, left, 7 ) ; + bf_round( left, right, 8 ) ; bf_round( right, left, 9 ) ; + bf_round( left, right, 10 ) ; bf_round( right, left, 11 ) ; + bf_round( left, right, 12 ) ; bf_round( right, left, 13 ) ; + bf_round( left, right, 14 ) ; bf_round( right, left, 15 ) ; + + left = left ^ P[NROUNDS] ; + right = right ^ P[NROUNDS+1] ; + block[0] = right ; + block[1] = left ; +} + +/* The following should be allignment and endian independent. + I have not tested it on a little-endian machine. + It takes the input block from source, and puts the output + in dest. They can be the same. It takes the same direction + parameter as crypt_block(). +*/ +static void crypt_8bytes(IntU8 *source, IntU8 *dest, BFkey_type *bfkey, + int direction) +{ + IntU32 block[2] ; + + block[0] = source[3] | source[2]<<8 | source[1]<<16 | source[0]<<24 ; + block[1] = source[7] | source[6]<<8 | source[5]<<16 | source[4]<<24 ; + + crypt_block( block, bfkey, direction ) ; + + dest[0]= block[0]>>24 ; + dest[1]= block[0]>>16 & 0xff ; + dest[2]= block[0]>>8 & 0xff ; + dest[3]= block[0] & 0xff ; + dest[4]= block[1]>>24 ; + dest[5]= block[1]>>16 & 0xff ; + dest[6]= block[1]>> 8 & 0xff ; + dest[7]= block[1] & 0xff ; +} + +/* make_bfkey() takes the address of the key data as a char*, + and the length of the key in bytes. It generates and returns + a pointer to an object of BFkey_type, which can be passed + to the crypt functions. It does some simple testing of the + init data and crypt routine, and returns 0 on error. +*/ +static void make_bfkey(unsigned char *key_string, int keylength, + BFkey_type *bfkey) +{ + int i, j, k ; + IntU32 dspace[2], + checksum=0 ; + + /* Copy constant initial data to P vector */ + for( i=0 ; ip[0][i] = p_init[i] ; + bfkey->p[1][NROUNDS+1-i] = p_init[i] ; + checksum = (checksum<<1 | checksum>>31)+p_init[i] ; + } + + /* Copy constant initial data to sboxes */ + for( i=0 ; i<4 ; ++i ) + for( j=0 ; j<256 ; ++j ) + { + bfkey->sbox[i][j] = s_init[i][j] ; + checksum = ((checksum*13)<<11 | (checksum*13)>>21) + + s_init[i][j] ; + } + + /* Test init data. */ + if( checksum != 0x55861a61 ) + { + PyErr_SetString(PyExc_SystemError, + "Blowfish: Bad initialization data"); + return; + } + + dspace[0] = 0 ; + dspace[1] = 0 ; + + /* Test the crypt_block() routine. */ + for( i=0 ; i<10 ; ++i ) + crypt_block( dspace, bfkey, 0 ) ; + checksum = dspace[0] ; + for( i=0 ; i<10 ; ++i ) + crypt_block( dspace, bfkey, 1 ) ; + if( (checksum!=0xaafe4ebd) || dspace[0] || dspace[1] ) + { + PyErr_SetString(PyExc_SystemError, + "Blowfish: Error in crypt_block routine"); + return; + } + + + /* Xor key string into encryption key vector */ + j = 0 ; + for (i=0 ; ip)[0][i] ^= data; + } + + + for (i = 0 ; ip[0][i] = dspace[0] ; + bfkey->p[1][NROUNDS+1-i] = dspace[0] ; + bfkey->p[0][i+1] = dspace[1] ; + bfkey->p[1][NROUNDS-i] = dspace[1] ; + } + + for ( i=0 ; i<4 ; ++i ) + for ( j=0 ; j<256 ; j+=2 ) + { + crypt_block( dspace, bfkey, 0 ) ; + bfkey->sbox[i][j] = dspace[0] ; + bfkey->sbox[i][j+1] = dspace[1] ; + } +} + + +static void +block_encrypt(block_state *self, unsigned char *in, unsigned char *out) +{ + crypt_8bytes(in, out, &(self->bfkey), 0); +} + + +static void +block_decrypt(block_state *self, unsigned char *in, unsigned char *out) +{ + crypt_8bytes(in, out, &(self->bfkey), 1); +} + +static void +block_init(block_state *self, unsigned char *key, int keylength) +{ + make_bfkey(key, keylength, &(self->bfkey)); +} + +#include "block_template.c" diff --git a/src/Crypto/src/CAST.c b/src/Crypto/src/CAST.c new file mode 100644 index 00000000..395318db --- /dev/null +++ b/src/Crypto/src/CAST.c @@ -0,0 +1,436 @@ +/* + cast.c -- implementation of CAST-128 (aka CAST5) as described in RFC2144 + + compile -DTEST to include main() which performs the tests + specified in RFC2144 + + Written by Wim Lewis based entirely on RFC2144. This code + is in the public domain. Consult your local laws for possible restrictions + on use, distribution, and import/export. RFC2144 states that this + algorithm "is available worldwide on a royalty-free basis for commercial + and non-commercial uses". + + This code is a pretty straightforward transliteration of the RFC into C. + It has not been optimized much at all: byte-order-independent arithmetic + operations are used where order-dependent pointer ops or unions might be + faster; the code could be rearranged to give the optimizer a better + chance to speed things up; etc. + + This code requires a vaguely ANSI-ish compiler. + + Tested with gcc 2.5.8 on i486, i586, i686, hp pa-risc, mc68040, sparc; + also with gcc 2.7.2 and (with minor changes) native Sun compiler on sparc + + History: + 21 Jul 1997: wiml : first working version & Python module +*/ + +#include "Python.h" + +#define MODULE_NAME CAST +#define BLOCK_SIZE 8 +#define KEY_SIZE 0 + +/* adjust these according to your compiler/platform. On some machines + uint32 will have to be a long. It's OK if uint32 is more than 32 bits. */ +typedef unsigned int uint32; +typedef unsigned char uint8; + +/* this struct probably belongs in cast.h */ +typedef struct { + /* masking and rotate keys */ + uint32 Km[16]; + uint8 Kr[16]; + /* number of rounds (depends on original unpadded keylength) */ + int rounds; +} block_state; + +/* these are the eight 32*256 S-boxes */ +#include "cast5.c" + +/* fetch a uint32 from an array of uint8s (with a given offset) */ +#define fetch(ptr, base) (((((( ptr[base]<< 8 ) | ptr[base+1] )<< 8 ) | ptr[base+2] )<< 8 ) | ptr[base+3]) + +/* this is the round function f(D, Km, Kr) */ +static uint32 castfunc(uint32 D, uint32 Kmi, uint8 Kri, int type) +{ + uint32 I, f; + short Ia, Ib, Ic, Id; + + switch(type) { + case 0: + I = (Kmi + D) ; + break; + case 1: + I = (Kmi ^ D) ; + break; + default: + case 2: + I = (Kmi - D) ; + break; + } + + I &= 0xFFFFFFFF; + I = ( I << Kri ) | ( I >> ( 32-Kri ) ); + Ia = ( I >> 24 ) & 0xFF; + Ib = ( I >> 16 ) & 0xFF; + Ic = ( I >> 8 ) & 0xFF; + Id = ( I ) & 0xFF; + + switch(type) { + case 0: + f = ((S1[Ia] ^ S2[Ib]) - S3[Ic]) + S4[Id]; + break; + case 1: + f = ((S1[Ia] - S2[Ib]) + S3[Ic]) ^ S4[Id]; + break; + default: + case 2: + f = ((S1[Ia] + S2[Ib]) ^ S3[Ic]) - S4[Id]; + break; + } + + return f; +} + +/* encrypts/decrypts one block of data according to the key schedule + pointed to by `key'. Encrypts if decrypt=0, otherwise decrypts. */ +static void castcrypt(block_state *key, uint8 *block, int decrypt) +{ + uint32 L, R, tmp, f; + uint32 Kmi; + uint8 Kri; + short functype, round; + + L = fetch(block, 0); + R = fetch(block, 4); + +/* printf("L0 = %08x R0 = %08x\n", L, R); */ + + for(round = 0; round < key->rounds; round ++) { + + if (!decrypt) { + Kmi = key->Km[round]; + Kri = key->Kr[round]; + functype = round % 3; + } else { + Kmi = key->Km[(key->rounds) - round - 1]; + Kri = key->Kr[(key->rounds) - round - 1]; + functype = (((key->rounds) - round - 1) % 3); + } + + f = castfunc(R, Kmi, Kri, functype); + + tmp = L; + L = R; + R = tmp ^ f; + +/* printf("L%d = %08x R%d = %08x\n", round+1, L, round+1, R); */ + } + + block[0] = ( R & 0xFF000000 ) >> 24; + block[1] = ( R & 0x00FF0000 ) >> 16; + block[2] = ( R & 0x0000FF00 ) >> 8; + block[3] = ( R & 0x000000FF ); + block[4] = ( L & 0xFF000000 ) >> 24; + block[5] = ( L & 0x00FF0000 ) >> 16; + block[6] = ( L & 0x0000FF00 ) >> 8; + block[7] = ( L & 0x000000FF ); +} + +/* fetch a uint8 from an array of uint32s */ +#define b(a,n) (((a)[n/4] >> (24-((n&3)*8))) & 0xFF) + +/* key schedule round functions */ + +#define XZRound(T, F, ki1, ki2, ki3, ki4, \ + si11, si12, si13, si14, si15,\ + si25,\ + si35,\ + si45 ) \ + T[0] = F[ki1] ^ S5[si11 ] ^ S6[si12 ] ^ S7[si13 ] ^ S8[si14 ] ^ S7[si15];\ + T[1] = F[ki2] ^ S5[b(T, 0)] ^ S6[b(T,2)] ^ S7[b(T, 1)] ^ S8[b(T,3)] ^ S8[si25];\ + T[2] = F[ki3] ^ S5[b(T, 7)] ^ S6[b(T,6)] ^ S7[b(T, 5)] ^ S8[b(T,4)] ^ S5[si35];\ + T[3] = F[ki4] ^ S5[b(T,10)] ^ S6[b(T,9)] ^ S7[b(T,11)] ^ S8[b(T,8)] ^ S6[si45]; + +#define zxround() XZRound(z, x, 0, 2, 3, 1, \ + b(x,13), b(x,15), b(x,12), b(x,14),\ + b(x, 8), b(x,10), b(x, 9), b(x,11)) + +#define xzround() XZRound(x, z, 2, 0, 1, 3, \ + b(z,5), b(z,7), b(z,4), b(z,6), \ + b(z,0), b(z,2), b(z,1), b(z,3)) + +#define Kround(T, base, F,\ + i11, i12, i13, i14, i15,\ + i21, i22, i23, i24, i25,\ + i31, i32, i33, i34, i35,\ + i41, i42, i43, i44, i45)\ + T[base+0] = S5[b(F,i11)] ^ S6[b(F,i12)] ^ S7[b(F,i13)] ^ S8[b(F,i14)] ^ S5[b(F,i15)];\ + T[base+1] = S5[b(F,i21)] ^ S6[b(F,i22)] ^ S7[b(F,i23)] ^ S8[b(F,i24)] ^ S6[b(F,i25)];\ + T[base+2] = S5[b(F,i31)] ^ S6[b(F,i32)] ^ S7[b(F,i33)] ^ S8[b(F,i34)] ^ S7[b(F,i35)];\ + T[base+3] = S5[b(F,i41)] ^ S6[b(F,i42)] ^ S7[b(F,i43)] ^ S8[b(F,i44)] ^ S8[b(F,i45)]; + +/* generates sixteen 32-bit subkeys based on a 4x32-bit input key; + modifies the input key *in as well. */ +static void schedulekeys_half(uint32 *in, uint32 *keys) +{ + uint32 x[4], z[4]; + + x[0] = in[0]; + x[1] = in[1]; + x[2] = in[2]; + x[3] = in[3]; + + zxround(); + Kround(keys, 0, z, + 8, 9, 7, 6, 2, + 10, 11, 5, 4, 6, + 12, 13, 3, 2, 9, + 14, 15, 1, 0, 12); + xzround(); + Kround(keys, 4, x, + 3, 2, 12, 13, 8, + 1, 0, 14, 15, 13, + 7, 6, 8, 9, 3, + 5, 4, 10, 11, 7); + zxround(); + Kround(keys, 8, z, + 3, 2, 12, 13, 9, + 1, 0, 14, 15, 12, + 7, 6, 8, 9, 2, + 5, 4, 10, 11, 6); + xzround(); + Kround(keys, 12, x, + 8, 9, 7, 6, 3, + 10, 11, 5, 4, 7, + 12, 13, 3, 2, 8, + 14, 15, 1, 0, 13); + + in[0] = x[0]; + in[1] = x[1]; + in[2] = x[2]; + in[3] = x[3]; +} + +/* generates a key schedule from an input key */ +static void castschedulekeys(block_state *schedule, uint8 *key, int keybytes) +{ + uint32 x[4]; + uint8 paddedkey[16]; + uint32 Kr_wide[16]; + int i; + + for(i = 0; i < keybytes; i++) + paddedkey[i] = key[i]; + for( ; i < 16 ; i++) + paddedkey[i] = 0; + + if (keybytes <= 10) + schedule->rounds = 12; + else + schedule->rounds = 16; + + x[0] = fetch(paddedkey, 0); + x[1] = fetch(paddedkey, 4); + x[2] = fetch(paddedkey, 8); + x[3] = fetch(paddedkey, 12); + + schedulekeys_half(x, schedule->Km); + schedulekeys_half(x, Kr_wide); + + for(i = 0; i < 16; i ++) { + /* The Kr[] subkeys are used for 32-bit circular shifts, + so we only need to keep them modulo 32 */ + schedule->Kr[i] = (uint8)(Kr_wide[i] & 0x1F); + } +} + +#ifdef TEST + +/* This performs a variety of encryptions and verifies that the results + match those specified in RFC2144 appendix B. Also verifies that + decryption restores the original data. */ + +#include + +static block_state sched; + +void encrypt(key, keylen, in, out) + uint8 *key; + int keylen; + uint8 *in, *out; +{ + int i; + uint8 k[16]; + + castschedulekeys(&sched, key, keylen); + + for(i = 0; i < 8; i++) + out[i] = in[i]; + castcrypt(&sched, out, 0); +} + +void tst(key, keylen, data, result) + uint8 *key; + int keylen; + uint8 *data, *result; +{ + uint8 d[8]; + int i; + + encrypt(key, keylen, data, d); + + for(i = 0; i < 8; i++) + if (d[i] != result[i]) + break; + + if (i == 8) { + printf("-- test ok (encrypt)\n"); + } else { + for(i = 0; i < 8; i++) + printf(" %02x", d[i]); + printf(" (computed)\n"); + for(i = 0; i < 8; i++) + printf(" %02x", result[i]); + printf(" (expected)\n"); + } + + /* uses key schedule already set up */ + castcrypt(&sched, d, 1); + if (bcmp(d, data, 8)) + printf(" test FAILED (decrypt)\n"); + else + printf(" test ok (decrypt)\n"); + +} + +uint8 key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; +uint8 data[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + +/* expected results of encrypting the above with 128, 80, and 40 + bits of key length */ +uint8 out1[8] = { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; +uint8 out2[8] = { 0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B }; +uint8 out3[8] = { 0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E }; + +/* expected results of the "full maintenance test" */ +uint8 afinal[16] = { 0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6, + 0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92 }; +uint8 bfinal[16] = { 0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71, + 0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E }; + +main() +{ + /* Appendix B.1 : Single Plaintext-Key-Ciphertext Sets */ + tst(key, 16, data, out1); + tst(key, 10, data, out2); + tst(key, 5, data, out3); + + /* Appendix B.2 : Full Maintenance Test */ + { + uint8 abuf[16]; + uint8 bbuf[16]; + int i; + + bcopy(key, abuf, 16); + bcopy(key, bbuf, 16); + + printf("\nrunning full maintenance test...\n"); + + for(i = 0; i < 1000000; i++) { + castschedulekeys(&sched, bbuf, 16); + castcrypt(&sched, abuf, 0); + castcrypt(&sched, abuf+8, 0); + + castschedulekeys(&sched, abuf, 16); + castcrypt(&sched, bbuf, 0); + castcrypt(&sched, bbuf+8, 0); + + if (!(i % 10000)) { + fprintf(stdout, "\r%d%% ", i / 10000); + fflush(stdout); + } + } + + printf("\r \r"); + + for(i = 0; i < 16; i ++) + if (abuf[i] != afinal[i] || bbuf[i] != bfinal[i]) + break; + + if(i == 16) { + printf("-- full maintenance test ok\n"); + } else { + for(i = 0; i < 16; i++) + printf(" %02x", abuf[i]); + printf("\n"); + for(i = 0; i < 16; i++) + printf(" %02x", bbuf[i]); + printf("\n"); + } + + printf("running maintenance test in reverse...\n"); + for(i = 0; i < 1000000; i++) { + castschedulekeys(&sched, abuf, 16); + castcrypt(&sched, bbuf+8, 1); + castcrypt(&sched, bbuf, 1); + + castschedulekeys(&sched, bbuf, 16); + castcrypt(&sched, abuf+8, 1); + castcrypt(&sched, abuf, 1); + + if (!(i % 10000)) { + fprintf(stdout, "\r%d%% ", i / 10000); + fflush(stdout); + } + } + + printf("\r \r"); + if (bcmp(abuf, key, 16) || bcmp(bbuf, key, 16)) + printf("-- reverse maintenance test FAILED\n"); + else + printf("-- reverse maintenance test ok\n"); + } +} + +#endif + +static void +block_init(block_state *self, unsigned char *key, int keylength) +{ + /* presumably this will optimize out */ + if (sizeof(uint32) < 4 || sizeof(uint8) != 1) { + PyErr_SetString(PyExc_SystemError, + "CAST module compiled with bad typedefs!"); + } + + /* make sure the key length is within bounds */ + if (keylength < 5 || keylength > 16) { + PyErr_SetString(PyExc_ValueError, "CAST key must be " + "at least 5 bytes and no more than 16 bytes long"); + return; + } + + /* do the actual key schedule setup */ + castschedulekeys(self, key, keylength); +} + +static void +block_encrypt(block_state *self, unsigned char *in, + unsigned char *out) +{ + memcpy(out, in, 8); + castcrypt(self, out, 0); +} + +static void block_decrypt(block_state *self, + unsigned char *in, + unsigned char *out) +{ + memcpy(out, in, 8); + castcrypt(self, out, 1); +} + +#include "block_template.c" diff --git a/src/Crypto/src/DES.c b/src/Crypto/src/DES.c new file mode 100644 index 00000000..e35699f5 --- /dev/null +++ b/src/Crypto/src/DES.c @@ -0,0 +1,665 @@ +/* + * des.c : Source code for the DES block cipher + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#include "Python.h" + +/* des.c */ +/* Copyright (C) 1993 Eric Young */ +/* Integrated into the PCT by A.M. Kuchling, November 1994 */ + +#define MODULE_NAME DES +#define BLOCK_SIZE 8 +#define KEY_SIZE 8 + + +typedef unsigned char des_cblock[8]; + +/* ecb_enc.c */ +/* Copyright (C) 1993 Eric Young - see README for more details */ + +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<<24) + +/* NOTE - c is not incremented as per c2l */ +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2|=((unsigned long)(*(--(c))))<<24; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1|=((unsigned long)(*(--(c))))<<24; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +/* replacements for htonl and ntohl since I have no idea what to do + * when faced with machines with 8 byte longs. */ +#define HDRSIZE 4 + +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))) + +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +#define D_ENCRYPT(L,R,S) \ + u=(R^s[S ]); \ + t=R^s[S+1]; \ + t=((t>>4)+(t<<28)); \ + L^= des_SPtrans[1][(t )&0x3f]| \ + des_SPtrans[3][(t>> 8)&0x3f]| \ + des_SPtrans[5][(t>>16)&0x3f]| \ + des_SPtrans[7][(t>>24)&0x3f]| \ + des_SPtrans[0][(u )&0x3f]| \ + des_SPtrans[2][(u>> 8)&0x3f]| \ + des_SPtrans[4][(u>>16)&0x3f]| \ + des_SPtrans[6][(u>>24)&0x3f]; + + /* IP and FP + * The problem is more of a geometric problem that random bit fiddling. + 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 + 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 + 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + + 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 + 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 + 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 + 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + + The output has been subject to swaps of the form + 0 1 -> 3 1 but the odd and even bits have been put into + 2 3 2 0 + different words. The main trick is to remember that + t=((l>>size)^r)&(mask); + r^=t; + l^=(t<>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + + + +/* spr.h */ +/* Copyright (C) 1993 Eric Young - see README for more details */ +static unsigned long des_SPtrans[8][64]={ +/* nibble 0 */ + {0x00820200, 0x00020000, 0x80800000, 0x80820200, + 0x00800000, 0x80020200, 0x80020000, 0x80800000, + 0x80020200, 0x00820200, 0x00820000, 0x80000200, + 0x80800200, 0x00800000, 0x00000000, 0x80020000, + 0x00020000, 0x80000000, 0x00800200, 0x00020200, + 0x80820200, 0x00820000, 0x80000200, 0x00800200, + 0x80000000, 0x00000200, 0x00020200, 0x80820000, + 0x00000200, 0x80800200, 0x80820000, 0x00000000, + 0x00000000, 0x80820200, 0x00800200, 0x80020000, + 0x00820200, 0x00020000, 0x80000200, 0x00800200, + 0x80820000, 0x00000200, 0x00020200, 0x80800000, + 0x80020200, 0x80000000, 0x80800000, 0x00820000, + 0x80820200, 0x00020200, 0x00820000, 0x80800200, + 0x00800000, 0x80000200, 0x80020000, 0x00000000, + 0x00020000, 0x00800000, 0x80800200, 0x00820200, + 0x80000000, 0x80820000, 0x00000200, 0x80020200}, + +/* nibble 1 */ + {0x10042004, 0x00000000, 0x00042000, 0x10040000, + 0x10000004, 0x00002004, 0x10002000, 0x00042000, + 0x00002000, 0x10040004, 0x00000004, 0x10002000, + 0x00040004, 0x10042000, 0x10040000, 0x00000004, + 0x00040000, 0x10002004, 0x10040004, 0x00002000, + 0x00042004, 0x10000000, 0x00000000, 0x00040004, + 0x10002004, 0x00042004, 0x10042000, 0x10000004, + 0x10000000, 0x00040000, 0x00002004, 0x10042004, + 0x00040004, 0x10042000, 0x10002000, 0x00042004, + 0x10042004, 0x00040004, 0x10000004, 0x00000000, + 0x10000000, 0x00002004, 0x00040000, 0x10040004, + 0x00002000, 0x10000000, 0x00042004, 0x10002004, + 0x10042000, 0x00002000, 0x00000000, 0x10000004, + 0x00000004, 0x10042004, 0x00042000, 0x10040000, + 0x10040004, 0x00040000, 0x00002004, 0x10002000, + 0x10002004, 0x00000004, 0x10040000, 0x00042000}, + +/* nibble 2 */ + {0x41000000, 0x01010040, 0x00000040, 0x41000040, + 0x40010000, 0x01000000, 0x41000040, 0x00010040, + 0x01000040, 0x00010000, 0x01010000, 0x40000000, + 0x41010040, 0x40000040, 0x40000000, 0x41010000, + 0x00000000, 0x40010000, 0x01010040, 0x00000040, + 0x40000040, 0x41010040, 0x00010000, 0x41000000, + 0x41010000, 0x01000040, 0x40010040, 0x01010000, + 0x00010040, 0x00000000, 0x01000000, 0x40010040, + 0x01010040, 0x00000040, 0x40000000, 0x00010000, + 0x40000040, 0x40010000, 0x01010000, 0x41000040, + 0x00000000, 0x01010040, 0x00010040, 0x41010000, + 0x40010000, 0x01000000, 0x41010040, 0x40000000, + 0x40010040, 0x41000000, 0x01000000, 0x41010040, + 0x00010000, 0x01000040, 0x41000040, 0x00010040, + 0x01000040, 0x00000000, 0x41010000, 0x40000040, + 0x41000000, 0x40010040, 0x00000040, 0x01010000}, + +/* nibble 3 */ + {0x00100402, 0x04000400, 0x00000002, 0x04100402, + 0x00000000, 0x04100000, 0x04000402, 0x00100002, + 0x04100400, 0x04000002, 0x04000000, 0x00000402, + 0x04000002, 0x00100402, 0x00100000, 0x04000000, + 0x04100002, 0x00100400, 0x00000400, 0x00000002, + 0x00100400, 0x04000402, 0x04100000, 0x00000400, + 0x00000402, 0x00000000, 0x00100002, 0x04100400, + 0x04000400, 0x04100002, 0x04100402, 0x00100000, + 0x04100002, 0x00000402, 0x00100000, 0x04000002, + 0x00100400, 0x04000400, 0x00000002, 0x04100000, + 0x04000402, 0x00000000, 0x00000400, 0x00100002, + 0x00000000, 0x04100002, 0x04100400, 0x00000400, + 0x04000000, 0x04100402, 0x00100402, 0x00100000, + 0x04100402, 0x00000002, 0x04000400, 0x00100402, + 0x00100002, 0x00100400, 0x04100000, 0x04000402, + 0x00000402, 0x04000000, 0x04000002, 0x04100400}, + +/* nibble 4 */ + {0x02000000, 0x00004000, 0x00000100, 0x02004108, + 0x02004008, 0x02000100, 0x00004108, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x00004100, + 0x02000108, 0x02004008, 0x02004100, 0x00000000, + 0x00004100, 0x02000000, 0x00004008, 0x00000108, + 0x02000100, 0x00004108, 0x00000000, 0x02000008, + 0x00000008, 0x02000108, 0x02004108, 0x00004008, + 0x02004000, 0x00000100, 0x00000108, 0x02004100, + 0x02004100, 0x02000108, 0x00004008, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x02000100, + 0x02000000, 0x00004100, 0x02004108, 0x00000000, + 0x00004108, 0x02000000, 0x00000100, 0x00004008, + 0x02000108, 0x00000100, 0x00000000, 0x02004108, + 0x02004008, 0x02004100, 0x00000108, 0x00004000, + 0x00004100, 0x02004008, 0x02000100, 0x00000108, + 0x00000008, 0x00004108, 0x02004000, 0x02000008}, + +/* nibble 5 */ + {0x20000010, 0x00080010, 0x00000000, 0x20080800, + 0x00080010, 0x00000800, 0x20000810, 0x00080000, + 0x00000810, 0x20080810, 0x00080800, 0x20000000, + 0x20000800, 0x20000010, 0x20080000, 0x00080810, + 0x00080000, 0x20000810, 0x20080010, 0x00000000, + 0x00000800, 0x00000010, 0x20080800, 0x20080010, + 0x20080810, 0x20080000, 0x20000000, 0x00000810, + 0x00000010, 0x00080800, 0x00080810, 0x20000800, + 0x00000810, 0x20000000, 0x20000800, 0x00080810, + 0x20080800, 0x00080010, 0x00000000, 0x20000800, + 0x20000000, 0x00000800, 0x20080010, 0x00080000, + 0x00080010, 0x20080810, 0x00080800, 0x00000010, + 0x20080810, 0x00080800, 0x00080000, 0x20000810, + 0x20000010, 0x20080000, 0x00080810, 0x00000000, + 0x00000800, 0x20000010, 0x20000810, 0x20080800, + 0x20080000, 0x00000810, 0x00000010, 0x20080010}, + +/* nibble 6 */ + {0x00001000, 0x00000080, 0x00400080, 0x00400001, + 0x00401081, 0x00001001, 0x00001080, 0x00000000, + 0x00400000, 0x00400081, 0x00000081, 0x00401000, + 0x00000001, 0x00401080, 0x00401000, 0x00000081, + 0x00400081, 0x00001000, 0x00001001, 0x00401081, + 0x00000000, 0x00400080, 0x00400001, 0x00001080, + 0x00401001, 0x00001081, 0x00401080, 0x00000001, + 0x00001081, 0x00401001, 0x00000080, 0x00400000, + 0x00001081, 0x00401000, 0x00401001, 0x00000081, + 0x00001000, 0x00000080, 0x00400000, 0x00401001, + 0x00400081, 0x00001081, 0x00001080, 0x00000000, + 0x00000080, 0x00400001, 0x00000001, 0x00400080, + 0x00000000, 0x00400081, 0x00400080, 0x00001080, + 0x00000081, 0x00001000, 0x00401081, 0x00400000, + 0x00401080, 0x00000001, 0x00001001, 0x00401081, + 0x00400001, 0x00401080, 0x00401000, 0x00001001}, + +/* nibble 7 */ + {0x08200020, 0x08208000, 0x00008020, 0x00000000, + 0x08008000, 0x00200020, 0x08200000, 0x08208020, + 0x00000020, 0x08000000, 0x00208000, 0x00008020, + 0x00208020, 0x08008020, 0x08000020, 0x08200000, + 0x00008000, 0x00208020, 0x00200020, 0x08008000, + 0x08208020, 0x08000020, 0x00000000, 0x00208000, + 0x08000000, 0x00200000, 0x08008020, 0x08200020, + 0x00200000, 0x00008000, 0x08208000, 0x00000020, + 0x00200000, 0x00008000, 0x08000020, 0x08208020, + 0x00008020, 0x08000000, 0x00000000, 0x00208000, + 0x08200020, 0x08008020, 0x08008000, 0x00200020, + 0x08208000, 0x00000020, 0x00200020, 0x08008000, + 0x08208020, 0x00200000, 0x08200000, 0x08000020, + 0x00208000, 0x00008020, 0x08008020, 0x08200000, + 0x00000020, 0x08208000, 0x00208020, 0x00000000, + 0x08000000, 0x08200020, 0x00008000, 0x00208020}}; + +static unsigned long des_skb[8][64]={ +/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + {0x00000000,0x00000010,0x20000000,0x20000010, + 0x00010000,0x00010010,0x20010000,0x20010010, + 0x00000800,0x00000810,0x20000800,0x20000810, + 0x00010800,0x00010810,0x20010800,0x20010810, + 0x00000020,0x00000030,0x20000020,0x20000030, + 0x00010020,0x00010030,0x20010020,0x20010030, + 0x00000820,0x00000830,0x20000820,0x20000830, + 0x00010820,0x00010830,0x20010820,0x20010830, + 0x00080000,0x00080010,0x20080000,0x20080010, + 0x00090000,0x00090010,0x20090000,0x20090010, + 0x00080800,0x00080810,0x20080800,0x20080810, + 0x00090800,0x00090810,0x20090800,0x20090810, + 0x00080020,0x00080030,0x20080020,0x20080030, + 0x00090020,0x00090030,0x20090020,0x20090030, + 0x00080820,0x00080830,0x20080820,0x20080830, + 0x00090820,0x00090830,0x20090820,0x20090830}, +/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + {0x00000000,0x02000000,0x00002000,0x02002000, + 0x00200000,0x02200000,0x00202000,0x02202000, + 0x00000004,0x02000004,0x00002004,0x02002004, + 0x00200004,0x02200004,0x00202004,0x02202004, + 0x00000400,0x02000400,0x00002400,0x02002400, + 0x00200400,0x02200400,0x00202400,0x02202400, + 0x00000404,0x02000404,0x00002404,0x02002404, + 0x00200404,0x02200404,0x00202404,0x02202404, + 0x10000000,0x12000000,0x10002000,0x12002000, + 0x10200000,0x12200000,0x10202000,0x12202000, + 0x10000004,0x12000004,0x10002004,0x12002004, + 0x10200004,0x12200004,0x10202004,0x12202004, + 0x10000400,0x12000400,0x10002400,0x12002400, + 0x10200400,0x12200400,0x10202400,0x12202400, + 0x10000404,0x12000404,0x10002404,0x12002404, + 0x10200404,0x12200404,0x10202404,0x12202404}, +/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + {0x00000000,0x00000001,0x00040000,0x00040001, + 0x01000000,0x01000001,0x01040000,0x01040001, + 0x00000002,0x00000003,0x00040002,0x00040003, + 0x01000002,0x01000003,0x01040002,0x01040003, + 0x00000200,0x00000201,0x00040200,0x00040201, + 0x01000200,0x01000201,0x01040200,0x01040201, + 0x00000202,0x00000203,0x00040202,0x00040203, + 0x01000202,0x01000203,0x01040202,0x01040203, + 0x08000000,0x08000001,0x08040000,0x08040001, + 0x09000000,0x09000001,0x09040000,0x09040001, + 0x08000002,0x08000003,0x08040002,0x08040003, + 0x09000002,0x09000003,0x09040002,0x09040003, + 0x08000200,0x08000201,0x08040200,0x08040201, + 0x09000200,0x09000201,0x09040200,0x09040201, + 0x08000202,0x08000203,0x08040202,0x08040203, + 0x09000202,0x09000203,0x09040202,0x09040203}, +/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + {0x00000000,0x00100000,0x00000100,0x00100100, + 0x00000008,0x00100008,0x00000108,0x00100108, + 0x00001000,0x00101000,0x00001100,0x00101100, + 0x00001008,0x00101008,0x00001108,0x00101108, + 0x04000000,0x04100000,0x04000100,0x04100100, + 0x04000008,0x04100008,0x04000108,0x04100108, + 0x04001000,0x04101000,0x04001100,0x04101100, + 0x04001008,0x04101008,0x04001108,0x04101108, + 0x00020000,0x00120000,0x00020100,0x00120100, + 0x00020008,0x00120008,0x00020108,0x00120108, + 0x00021000,0x00121000,0x00021100,0x00121100, + 0x00021008,0x00121008,0x00021108,0x00121108, + 0x04020000,0x04120000,0x04020100,0x04120100, + 0x04020008,0x04120008,0x04020108,0x04120108, + 0x04021000,0x04121000,0x04021100,0x04121100, + 0x04021008,0x04121008,0x04021108,0x04121108}, +/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + {0x00000000,0x10000000,0x00010000,0x10010000, + 0x00000004,0x10000004,0x00010004,0x10010004, + 0x20000000,0x30000000,0x20010000,0x30010000, + 0x20000004,0x30000004,0x20010004,0x30010004, + 0x00100000,0x10100000,0x00110000,0x10110000, + 0x00100004,0x10100004,0x00110004,0x10110004, + 0x20100000,0x30100000,0x20110000,0x30110000, + 0x20100004,0x30100004,0x20110004,0x30110004, + 0x00001000,0x10001000,0x00011000,0x10011000, + 0x00001004,0x10001004,0x00011004,0x10011004, + 0x20001000,0x30001000,0x20011000,0x30011000, + 0x20001004,0x30001004,0x20011004,0x30011004, + 0x00101000,0x10101000,0x00111000,0x10111000, + 0x00101004,0x10101004,0x00111004,0x10111004, + 0x20101000,0x30101000,0x20111000,0x30111000, + 0x20101004,0x30101004,0x20111004,0x30111004}, +/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + {0x00000000,0x08000000,0x00000008,0x08000008, + 0x00000400,0x08000400,0x00000408,0x08000408, + 0x00020000,0x08020000,0x00020008,0x08020008, + 0x00020400,0x08020400,0x00020408,0x08020408, + 0x00000001,0x08000001,0x00000009,0x08000009, + 0x00000401,0x08000401,0x00000409,0x08000409, + 0x00020001,0x08020001,0x00020009,0x08020009, + 0x00020401,0x08020401,0x00020409,0x08020409, + 0x02000000,0x0A000000,0x02000008,0x0A000008, + 0x02000400,0x0A000400,0x02000408,0x0A000408, + 0x02020000,0x0A020000,0x02020008,0x0A020008, + 0x02020400,0x0A020400,0x02020408,0x0A020408, + 0x02000001,0x0A000001,0x02000009,0x0A000009, + 0x02000401,0x0A000401,0x02000409,0x0A000409, + 0x02020001,0x0A020001,0x02020009,0x0A020009, + 0x02020401,0x0A020401,0x02020409,0x0A020409}, +/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + {0x00000000,0x00000100,0x00080000,0x00080100, + 0x01000000,0x01000100,0x01080000,0x01080100, + 0x00000010,0x00000110,0x00080010,0x00080110, + 0x01000010,0x01000110,0x01080010,0x01080110, + 0x00200000,0x00200100,0x00280000,0x00280100, + 0x01200000,0x01200100,0x01280000,0x01280100, + 0x00200010,0x00200110,0x00280010,0x00280110, + 0x01200010,0x01200110,0x01280010,0x01280110, + 0x00000200,0x00000300,0x00080200,0x00080300, + 0x01000200,0x01000300,0x01080200,0x01080300, + 0x00000210,0x00000310,0x00080210,0x00080310, + 0x01000210,0x01000310,0x01080210,0x01080310, + 0x00200200,0x00200300,0x00280200,0x00280300, + 0x01200200,0x01200300,0x01280200,0x01280300, + 0x00200210,0x00200310,0x00280210,0x00280310, + 0x01200210,0x01200310,0x01280210,0x01280310}, +/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + {0x00000000,0x04000000,0x00040000,0x04040000, + 0x00000002,0x04000002,0x00040002,0x04040002, + 0x00002000,0x04002000,0x00042000,0x04042000, + 0x00002002,0x04002002,0x00042002,0x04042002, + 0x00000020,0x04000020,0x00040020,0x04040020, + 0x00000022,0x04000022,0x00040022,0x04040022, + 0x00002020,0x04002020,0x00042020,0x04042020, + 0x00002022,0x04002022,0x00042022,0x04042022, + 0x00000800,0x04000800,0x00040800,0x04040800, + 0x00000802,0x04000802,0x00040802,0x04040802, + 0x00002800,0x04002800,0x00042800,0x04042800, + 0x00002802,0x04002802,0x00042802,0x04042802, + 0x00000820,0x04000820,0x00040820,0x04040820, + 0x00000822,0x04000822,0x00040822,0x04040822, + 0x00002820,0x04002820,0x00042820,0x04042820, + 0x00002822,0x04002822,0x00042822,0x04042822} +}; + +typedef struct des_ks_struct +{ + union { + des_cblock _; + /* make sure things are correct size on machines with + * 8 byte longs */ + unsigned long pad[2]; + } ks; +#define _ ks._ +} block_state[16]; + +static int des_encrypt(unsigned long *input, unsigned long *output, + block_state ks, int encrypt) +{ + unsigned long l,r,t,u; + int i; + unsigned long *s; + + l=input[0]; + r=input[1]; + + /* do IP */ + PERM_OP(r,l,t, 4,0x0f0f0f0f); + PERM_OP(l,r,t,16,0x0000ffff); + PERM_OP(r,l,t, 2,0x33333333); + PERM_OP(l,r,t, 8,0x00ff00ff); + PERM_OP(r,l,t, 1,0x55555555); + /* r and l are reversed - remember that :-) - fix + * it in the next step */ + + /* Things have been modified so that the initial rotate is + * done outside the loop. This required the + * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * One perl script later and things have a 5% speed up on a sparc2. + * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> + * for pointing this out. */ + t=(r<<1)|(r>>31); + r=(l<<1)|(l>>31); + l=t; + + /* clear the top bits on machines with 8byte longs */ + l&=0xffffffff; + r&=0xffffffff; + + s=(unsigned long *)ks; + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (encrypt) + { + for (i=0; i<32; i+=4) + { + D_ENCRYPT(l,r,i+0); /* 1 */ + D_ENCRYPT(r,l,i+2); /* 2 */ + } + } + else + { + for (i=30; i>0; i-=4) + { + D_ENCRYPT(l,r,i-0); /* 16 */ + D_ENCRYPT(r,l,i-2); /* 15 */ + } + } + l=(l>>1)|(l<<31); + r=(r>>1)|(r<<31); + /* clear the top bits on machines with 8byte longs */ + l&=0xffffffff; + r&=0xffffffff; + + /* swap l and r + * we will not do the swap so just remember they are + * reversed for the rest of the subroutine + * luckily FP fixes this problem :-) */ + + PERM_OP(r,l,t, 1,0x55555555); + PERM_OP(l,r,t, 8,0x00ff00ff); + PERM_OP(r,l,t, 2,0x33333333); + PERM_OP(l,r,t,16,0x0000ffff); + PERM_OP(r,l,t, 4,0x0f0f0f0f); + + output[0]=l; + output[1]=r; + l=r=t=u=0; + return(0); +} + +static int des_ecb_encrypt(des_cblock *input, des_cblock *output, + block_state ks, int encrypt) +{ + register unsigned long l0,l1; + register unsigned char *in,*out; + unsigned long ll[2]; + + in=(unsigned char *)input; + out=(unsigned char *)output; + c2l(in,l0); + c2l(in,l1); + ll[0]=l0; + ll[1]=l1; + des_encrypt(ll,ll,ks,encrypt); + l0=ll[0]; + l1=ll[1]; + l2c(l0,out); + l2c(l1,out); + l0=l1=ll[0]=ll[1]=0; + return(0); +} + + + +static void block_decrypt(block_state *state, + unsigned char *in, + unsigned char *out) +{ + des_ecb_encrypt((des_cblock *)in, (des_cblock *)out, *state, 0); +} + +static void block_encrypt(block_state *state, + unsigned char *in, + unsigned char *out) +{ + des_ecb_encrypt((des_cblock *)in, (des_cblock *)out, *state, 1); +} + +/* NOW DEFINED IN des_local.h + * See ecb_encrypt.c for a pseudo description of these macros. + * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ + * (b)^=(t),\ + * (a)=((a)^((t)<<(n)))) + */ + +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n)))) + +static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; + +/* return 0 if key parity is odd (correct), + * return -1 if key parity error, + * return -2 if illegal weak key. + */ +static int des_set_key(des_cblock *key, block_state schedule) +{ + register unsigned long c,d,t,s; + register unsigned char *in; + register unsigned long *k; + register int i; + + k=(unsigned long *)schedule; + in=(unsigned char *)key; + + c2l(in,c); + c2l(in,d); + + /* do PC1 in 60 simple operations */ +/* PERM_OP(d,c,t,4,0x0f0f0f0f); + HPERM_OP(c,t,-2, 0xcccc0000); + HPERM_OP(c,t,-1, 0xaaaa0000); + HPERM_OP(c,t, 8, 0x00ff0000); + HPERM_OP(c,t,-1, 0xaaaa0000); + HPERM_OP(d,t,-8, 0xff000000); + HPERM_OP(d,t, 8, 0x00ff0000); + HPERM_OP(d,t, 2, 0x33330000); + d=((d&0x00aa00aa)<<7)|((d&0x55005500)>>7)|(d&0xaa55aa55); + d=(d>>8)|((c&0xf0000000)>>4); + c&=0x0fffffff; */ + + /* I now do it in 47 simple operations :-) + * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) + * for the inspiration. :-) */ + PERM_OP (d,c,t,4,0x0f0f0f0f); + HPERM_OP(c,t,-2,0xcccc0000); + HPERM_OP(d,t,-2,0xcccc0000); + PERM_OP (d,c,t,1,0x55555555); + PERM_OP (c,d,t,8,0x00ff00ff); + PERM_OP (d,c,t,1,0x55555555); + d= (((d&0x000000ff)<<16)| (d&0x0000ff00) | + ((d&0x00ff0000)>>16)|((c&0xf0000000)>>4)); + c&=0x0fffffff; + + for (i=0; i<16; i++) + { + if (shifts2[i]) + { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); } + else + { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); } + c&=0x0fffffff; + d&=0x0fffffff; + /* could be a few less shifts but I am to lazy at this + * point in time to investigate */ + s= des_skb[0][ (c )&0x3f ]| + des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]| + des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]| + des_skb[3][((c>>20)&0x01)|((c>>21)&0x06) | + ((c>>22)&0x38)]; + t= des_skb[4][ (d )&0x3f ]| + des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]| + des_skb[6][ (d>>15)&0x3f ]| + des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)]; + + /* table contained 0213 4657 */ + *(k++)=((t<<16)|(s&0x0000ffff))&0xffffffff; + s= ((s>>16)|(t&0xffff0000)); + + s=(s<<4)|(s>>28); + *(k++)=s&0xffffffff; + } + return(0); +} + +static const unsigned char odd_parity[256]={ + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, + 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, + 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, + 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, + 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, + 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, + 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, + 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, + 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, + 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; + +static void block_init(block_state *state, unsigned char *key, + int keylen) +{ + char oddkey[8]; + int i; + + for (i=0; i<8; i++) + { + oddkey[i]=odd_parity[ key[i] ]; + } + des_set_key((des_cblock *)oddkey, *state); +} + +#include "block_template.c" diff --git a/src/Crypto/src/DES3.c b/src/Crypto/src/DES3.c new file mode 100644 index 00000000..49bf6f48 --- /dev/null +++ b/src/Crypto/src/DES3.c @@ -0,0 +1,688 @@ + +/* + * des.c : Source code for the DES block cipher + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +/* des.c */ +/* Copyright (C) 1993 Eric Young */ +/* Integrated into the PCT by A.M. Kuchling, November 1994 */ +/* Fully independent key mode added by Wim Lewis, July 1997 */ + +#include "Python.h" + +#define MODULE_NAME DES3 +#define BLOCK_SIZE 8 +#define KEY_SIZE 0 + +typedef unsigned char des_cblock[8]; + +/* ecb_enc.c */ +/* Copyright (C) 1993 Eric Young - see README for more details */ + +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<<24) + +/* NOTE - c is not incremented as per c2l */ +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2|=((unsigned long)(*(--(c))))<<24; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1|=((unsigned long)(*(--(c))))<<24; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +/* replacements for htonl and ntohl since I have no idea what to do + * when faced with machines with 8 byte longs. */ +#define HDRSIZE 4 + +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))) + +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +#define D_ENCRYPT(L,R,S) \ + u=(R^s[S ]); \ + t=R^s[S+1]; \ + t=((t>>4)+(t<<28)); \ + L^= des_SPtrans[1][(t )&0x3f]| \ + des_SPtrans[3][(t>> 8)&0x3f]| \ + des_SPtrans[5][(t>>16)&0x3f]| \ + des_SPtrans[7][(t>>24)&0x3f]| \ + des_SPtrans[0][(u )&0x3f]| \ + des_SPtrans[2][(u>> 8)&0x3f]| \ + des_SPtrans[4][(u>>16)&0x3f]| \ + des_SPtrans[6][(u>>24)&0x3f]; + + /* IP and FP + * The problem is more of a geometric problem that random bit fiddling. + 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 + 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 + 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + + 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 + 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 + 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 + 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + + The output has been subject to swaps of the form + 0 1 -> 3 1 but the odd and even bits have been put into + 2 3 2 0 + different words. The main trick is to remember that + t=((l>>size)^r)&(mask); + r^=t; + l^=(t<>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + + + +/* spr.h */ +/* Copyright (C) 1993 Eric Young - see README for more details */ +static unsigned long des_SPtrans[8][64]={ +/* nibble 0 */ + {0x00820200, 0x00020000, 0x80800000, 0x80820200, + 0x00800000, 0x80020200, 0x80020000, 0x80800000, + 0x80020200, 0x00820200, 0x00820000, 0x80000200, + 0x80800200, 0x00800000, 0x00000000, 0x80020000, + 0x00020000, 0x80000000, 0x00800200, 0x00020200, + 0x80820200, 0x00820000, 0x80000200, 0x00800200, + 0x80000000, 0x00000200, 0x00020200, 0x80820000, + 0x00000200, 0x80800200, 0x80820000, 0x00000000, + 0x00000000, 0x80820200, 0x00800200, 0x80020000, + 0x00820200, 0x00020000, 0x80000200, 0x00800200, + 0x80820000, 0x00000200, 0x00020200, 0x80800000, + 0x80020200, 0x80000000, 0x80800000, 0x00820000, + 0x80820200, 0x00020200, 0x00820000, 0x80800200, + 0x00800000, 0x80000200, 0x80020000, 0x00000000, + 0x00020000, 0x00800000, 0x80800200, 0x00820200, + 0x80000000, 0x80820000, 0x00000200, 0x80020200}, + +/* nibble 1 */ + {0x10042004, 0x00000000, 0x00042000, 0x10040000, + 0x10000004, 0x00002004, 0x10002000, 0x00042000, + 0x00002000, 0x10040004, 0x00000004, 0x10002000, + 0x00040004, 0x10042000, 0x10040000, 0x00000004, + 0x00040000, 0x10002004, 0x10040004, 0x00002000, + 0x00042004, 0x10000000, 0x00000000, 0x00040004, + 0x10002004, 0x00042004, 0x10042000, 0x10000004, + 0x10000000, 0x00040000, 0x00002004, 0x10042004, + 0x00040004, 0x10042000, 0x10002000, 0x00042004, + 0x10042004, 0x00040004, 0x10000004, 0x00000000, + 0x10000000, 0x00002004, 0x00040000, 0x10040004, + 0x00002000, 0x10000000, 0x00042004, 0x10002004, + 0x10042000, 0x00002000, 0x00000000, 0x10000004, + 0x00000004, 0x10042004, 0x00042000, 0x10040000, + 0x10040004, 0x00040000, 0x00002004, 0x10002000, + 0x10002004, 0x00000004, 0x10040000, 0x00042000}, + +/* nibble 2 */ + {0x41000000, 0x01010040, 0x00000040, 0x41000040, + 0x40010000, 0x01000000, 0x41000040, 0x00010040, + 0x01000040, 0x00010000, 0x01010000, 0x40000000, + 0x41010040, 0x40000040, 0x40000000, 0x41010000, + 0x00000000, 0x40010000, 0x01010040, 0x00000040, + 0x40000040, 0x41010040, 0x00010000, 0x41000000, + 0x41010000, 0x01000040, 0x40010040, 0x01010000, + 0x00010040, 0x00000000, 0x01000000, 0x40010040, + 0x01010040, 0x00000040, 0x40000000, 0x00010000, + 0x40000040, 0x40010000, 0x01010000, 0x41000040, + 0x00000000, 0x01010040, 0x00010040, 0x41010000, + 0x40010000, 0x01000000, 0x41010040, 0x40000000, + 0x40010040, 0x41000000, 0x01000000, 0x41010040, + 0x00010000, 0x01000040, 0x41000040, 0x00010040, + 0x01000040, 0x00000000, 0x41010000, 0x40000040, + 0x41000000, 0x40010040, 0x00000040, 0x01010000}, + +/* nibble 3 */ + {0x00100402, 0x04000400, 0x00000002, 0x04100402, + 0x00000000, 0x04100000, 0x04000402, 0x00100002, + 0x04100400, 0x04000002, 0x04000000, 0x00000402, + 0x04000002, 0x00100402, 0x00100000, 0x04000000, + 0x04100002, 0x00100400, 0x00000400, 0x00000002, + 0x00100400, 0x04000402, 0x04100000, 0x00000400, + 0x00000402, 0x00000000, 0x00100002, 0x04100400, + 0x04000400, 0x04100002, 0x04100402, 0x00100000, + 0x04100002, 0x00000402, 0x00100000, 0x04000002, + 0x00100400, 0x04000400, 0x00000002, 0x04100000, + 0x04000402, 0x00000000, 0x00000400, 0x00100002, + 0x00000000, 0x04100002, 0x04100400, 0x00000400, + 0x04000000, 0x04100402, 0x00100402, 0x00100000, + 0x04100402, 0x00000002, 0x04000400, 0x00100402, + 0x00100002, 0x00100400, 0x04100000, 0x04000402, + 0x00000402, 0x04000000, 0x04000002, 0x04100400}, + +/* nibble 4 */ + {0x02000000, 0x00004000, 0x00000100, 0x02004108, + 0x02004008, 0x02000100, 0x00004108, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x00004100, + 0x02000108, 0x02004008, 0x02004100, 0x00000000, + 0x00004100, 0x02000000, 0x00004008, 0x00000108, + 0x02000100, 0x00004108, 0x00000000, 0x02000008, + 0x00000008, 0x02000108, 0x02004108, 0x00004008, + 0x02004000, 0x00000100, 0x00000108, 0x02004100, + 0x02004100, 0x02000108, 0x00004008, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x02000100, + 0x02000000, 0x00004100, 0x02004108, 0x00000000, + 0x00004108, 0x02000000, 0x00000100, 0x00004008, + 0x02000108, 0x00000100, 0x00000000, 0x02004108, + 0x02004008, 0x02004100, 0x00000108, 0x00004000, + 0x00004100, 0x02004008, 0x02000100, 0x00000108, + 0x00000008, 0x00004108, 0x02004000, 0x02000008}, + +/* nibble 5 */ + {0x20000010, 0x00080010, 0x00000000, 0x20080800, + 0x00080010, 0x00000800, 0x20000810, 0x00080000, + 0x00000810, 0x20080810, 0x00080800, 0x20000000, + 0x20000800, 0x20000010, 0x20080000, 0x00080810, + 0x00080000, 0x20000810, 0x20080010, 0x00000000, + 0x00000800, 0x00000010, 0x20080800, 0x20080010, + 0x20080810, 0x20080000, 0x20000000, 0x00000810, + 0x00000010, 0x00080800, 0x00080810, 0x20000800, + 0x00000810, 0x20000000, 0x20000800, 0x00080810, + 0x20080800, 0x00080010, 0x00000000, 0x20000800, + 0x20000000, 0x00000800, 0x20080010, 0x00080000, + 0x00080010, 0x20080810, 0x00080800, 0x00000010, + 0x20080810, 0x00080800, 0x00080000, 0x20000810, + 0x20000010, 0x20080000, 0x00080810, 0x00000000, + 0x00000800, 0x20000010, 0x20000810, 0x20080800, + 0x20080000, 0x00000810, 0x00000010, 0x20080010}, + +/* nibble 6 */ + {0x00001000, 0x00000080, 0x00400080, 0x00400001, + 0x00401081, 0x00001001, 0x00001080, 0x00000000, + 0x00400000, 0x00400081, 0x00000081, 0x00401000, + 0x00000001, 0x00401080, 0x00401000, 0x00000081, + 0x00400081, 0x00001000, 0x00001001, 0x00401081, + 0x00000000, 0x00400080, 0x00400001, 0x00001080, + 0x00401001, 0x00001081, 0x00401080, 0x00000001, + 0x00001081, 0x00401001, 0x00000080, 0x00400000, + 0x00001081, 0x00401000, 0x00401001, 0x00000081, + 0x00001000, 0x00000080, 0x00400000, 0x00401001, + 0x00400081, 0x00001081, 0x00001080, 0x00000000, + 0x00000080, 0x00400001, 0x00000001, 0x00400080, + 0x00000000, 0x00400081, 0x00400080, 0x00001080, + 0x00000081, 0x00001000, 0x00401081, 0x00400000, + 0x00401080, 0x00000001, 0x00001001, 0x00401081, + 0x00400001, 0x00401080, 0x00401000, 0x00001001}, + +/* nibble 7 */ + {0x08200020, 0x08208000, 0x00008020, 0x00000000, + 0x08008000, 0x00200020, 0x08200000, 0x08208020, + 0x00000020, 0x08000000, 0x00208000, 0x00008020, + 0x00208020, 0x08008020, 0x08000020, 0x08200000, + 0x00008000, 0x00208020, 0x00200020, 0x08008000, + 0x08208020, 0x08000020, 0x00000000, 0x00208000, + 0x08000000, 0x00200000, 0x08008020, 0x08200020, + 0x00200000, 0x00008000, 0x08208000, 0x00000020, + 0x00200000, 0x00008000, 0x08000020, 0x08208020, + 0x00008020, 0x08000000, 0x00000000, 0x00208000, + 0x08200020, 0x08008020, 0x08008000, 0x00200020, + 0x08208000, 0x00000020, 0x00200020, 0x08008000, + 0x08208020, 0x00200000, 0x08200000, 0x08000020, + 0x00208000, 0x00008020, 0x08008020, 0x08200000, + 0x00000020, 0x08208000, 0x00208020, 0x00000000, + 0x08000000, 0x08200020, 0x00008000, 0x00208020}}; + +static unsigned long des_skb[8][64]={ +/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + {0x00000000,0x00000010,0x20000000,0x20000010, + 0x00010000,0x00010010,0x20010000,0x20010010, + 0x00000800,0x00000810,0x20000800,0x20000810, + 0x00010800,0x00010810,0x20010800,0x20010810, + 0x00000020,0x00000030,0x20000020,0x20000030, + 0x00010020,0x00010030,0x20010020,0x20010030, + 0x00000820,0x00000830,0x20000820,0x20000830, + 0x00010820,0x00010830,0x20010820,0x20010830, + 0x00080000,0x00080010,0x20080000,0x20080010, + 0x00090000,0x00090010,0x20090000,0x20090010, + 0x00080800,0x00080810,0x20080800,0x20080810, + 0x00090800,0x00090810,0x20090800,0x20090810, + 0x00080020,0x00080030,0x20080020,0x20080030, + 0x00090020,0x00090030,0x20090020,0x20090030, + 0x00080820,0x00080830,0x20080820,0x20080830, + 0x00090820,0x00090830,0x20090820,0x20090830}, +/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + {0x00000000,0x02000000,0x00002000,0x02002000, + 0x00200000,0x02200000,0x00202000,0x02202000, + 0x00000004,0x02000004,0x00002004,0x02002004, + 0x00200004,0x02200004,0x00202004,0x02202004, + 0x00000400,0x02000400,0x00002400,0x02002400, + 0x00200400,0x02200400,0x00202400,0x02202400, + 0x00000404,0x02000404,0x00002404,0x02002404, + 0x00200404,0x02200404,0x00202404,0x02202404, + 0x10000000,0x12000000,0x10002000,0x12002000, + 0x10200000,0x12200000,0x10202000,0x12202000, + 0x10000004,0x12000004,0x10002004,0x12002004, + 0x10200004,0x12200004,0x10202004,0x12202004, + 0x10000400,0x12000400,0x10002400,0x12002400, + 0x10200400,0x12200400,0x10202400,0x12202400, + 0x10000404,0x12000404,0x10002404,0x12002404, + 0x10200404,0x12200404,0x10202404,0x12202404}, +/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + {0x00000000,0x00000001,0x00040000,0x00040001, + 0x01000000,0x01000001,0x01040000,0x01040001, + 0x00000002,0x00000003,0x00040002,0x00040003, + 0x01000002,0x01000003,0x01040002,0x01040003, + 0x00000200,0x00000201,0x00040200,0x00040201, + 0x01000200,0x01000201,0x01040200,0x01040201, + 0x00000202,0x00000203,0x00040202,0x00040203, + 0x01000202,0x01000203,0x01040202,0x01040203, + 0x08000000,0x08000001,0x08040000,0x08040001, + 0x09000000,0x09000001,0x09040000,0x09040001, + 0x08000002,0x08000003,0x08040002,0x08040003, + 0x09000002,0x09000003,0x09040002,0x09040003, + 0x08000200,0x08000201,0x08040200,0x08040201, + 0x09000200,0x09000201,0x09040200,0x09040201, + 0x08000202,0x08000203,0x08040202,0x08040203, + 0x09000202,0x09000203,0x09040202,0x09040203}, +/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + {0x00000000,0x00100000,0x00000100,0x00100100, + 0x00000008,0x00100008,0x00000108,0x00100108, + 0x00001000,0x00101000,0x00001100,0x00101100, + 0x00001008,0x00101008,0x00001108,0x00101108, + 0x04000000,0x04100000,0x04000100,0x04100100, + 0x04000008,0x04100008,0x04000108,0x04100108, + 0x04001000,0x04101000,0x04001100,0x04101100, + 0x04001008,0x04101008,0x04001108,0x04101108, + 0x00020000,0x00120000,0x00020100,0x00120100, + 0x00020008,0x00120008,0x00020108,0x00120108, + 0x00021000,0x00121000,0x00021100,0x00121100, + 0x00021008,0x00121008,0x00021108,0x00121108, + 0x04020000,0x04120000,0x04020100,0x04120100, + 0x04020008,0x04120008,0x04020108,0x04120108, + 0x04021000,0x04121000,0x04021100,0x04121100, + 0x04021008,0x04121008,0x04021108,0x04121108}, +/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + {0x00000000,0x10000000,0x00010000,0x10010000, + 0x00000004,0x10000004,0x00010004,0x10010004, + 0x20000000,0x30000000,0x20010000,0x30010000, + 0x20000004,0x30000004,0x20010004,0x30010004, + 0x00100000,0x10100000,0x00110000,0x10110000, + 0x00100004,0x10100004,0x00110004,0x10110004, + 0x20100000,0x30100000,0x20110000,0x30110000, + 0x20100004,0x30100004,0x20110004,0x30110004, + 0x00001000,0x10001000,0x00011000,0x10011000, + 0x00001004,0x10001004,0x00011004,0x10011004, + 0x20001000,0x30001000,0x20011000,0x30011000, + 0x20001004,0x30001004,0x20011004,0x30011004, + 0x00101000,0x10101000,0x00111000,0x10111000, + 0x00101004,0x10101004,0x00111004,0x10111004, + 0x20101000,0x30101000,0x20111000,0x30111000, + 0x20101004,0x30101004,0x20111004,0x30111004}, +/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + {0x00000000,0x08000000,0x00000008,0x08000008, + 0x00000400,0x08000400,0x00000408,0x08000408, + 0x00020000,0x08020000,0x00020008,0x08020008, + 0x00020400,0x08020400,0x00020408,0x08020408, + 0x00000001,0x08000001,0x00000009,0x08000009, + 0x00000401,0x08000401,0x00000409,0x08000409, + 0x00020001,0x08020001,0x00020009,0x08020009, + 0x00020401,0x08020401,0x00020409,0x08020409, + 0x02000000,0x0A000000,0x02000008,0x0A000008, + 0x02000400,0x0A000400,0x02000408,0x0A000408, + 0x02020000,0x0A020000,0x02020008,0x0A020008, + 0x02020400,0x0A020400,0x02020408,0x0A020408, + 0x02000001,0x0A000001,0x02000009,0x0A000009, + 0x02000401,0x0A000401,0x02000409,0x0A000409, + 0x02020001,0x0A020001,0x02020009,0x0A020009, + 0x02020401,0x0A020401,0x02020409,0x0A020409}, +/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + {0x00000000,0x00000100,0x00080000,0x00080100, + 0x01000000,0x01000100,0x01080000,0x01080100, + 0x00000010,0x00000110,0x00080010,0x00080110, + 0x01000010,0x01000110,0x01080010,0x01080110, + 0x00200000,0x00200100,0x00280000,0x00280100, + 0x01200000,0x01200100,0x01280000,0x01280100, + 0x00200010,0x00200110,0x00280010,0x00280110, + 0x01200010,0x01200110,0x01280010,0x01280110, + 0x00000200,0x00000300,0x00080200,0x00080300, + 0x01000200,0x01000300,0x01080200,0x01080300, + 0x00000210,0x00000310,0x00080210,0x00080310, + 0x01000210,0x01000310,0x01080210,0x01080310, + 0x00200200,0x00200300,0x00280200,0x00280300, + 0x01200200,0x01200300,0x01280200,0x01280300, + 0x00200210,0x00200310,0x00280210,0x00280310, + 0x01200210,0x01200310,0x01280210,0x01280310}, +/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + {0x00000000,0x04000000,0x00040000,0x04040000, + 0x00000002,0x04000002,0x00040002,0x04040002, + 0x00002000,0x04002000,0x00042000,0x04042000, + 0x00002002,0x04002002,0x00042002,0x04042002, + 0x00000020,0x04000020,0x00040020,0x04040020, + 0x00000022,0x04000022,0x00040022,0x04040022, + 0x00002020,0x04002020,0x00042020,0x04042020, + 0x00002022,0x04002022,0x00042022,0x04042022, + 0x00000800,0x04000800,0x00040800,0x04040800, + 0x00000802,0x04000802,0x00040802,0x04040802, + 0x00002800,0x04002800,0x00042800,0x04042800, + 0x00002802,0x04002802,0x00042802,0x04042802, + 0x00000820,0x04000820,0x00040820,0x04040820, + 0x00000822,0x04000822,0x00040822,0x04040822, + 0x00002820,0x04002820,0x00042820,0x04042820, + 0x00002822,0x04002822,0x00042822,0x04042822} +}; + +typedef struct des_ks_struct +{ + union { + des_cblock _; + /* make sure things are correct size on machines with + * 8 byte longs */ + unsigned long pad[2]; + } ks; +#define _ ks._ +} des_key_schedule[16]; + +typedef struct +{ + des_key_schedule KeySched1, KeySched2, KeySched3; +} block_state; + +static int des_encrypt(unsigned long *input, unsigned long *output, + des_key_schedule ks, int encrypt) +{ + register unsigned long l,r,t,u; + register int i; + register unsigned long *s; + + l=input[0]; + r=input[1]; + + /* do IP */ + PERM_OP(r,l,t, 4,0x0f0f0f0f); + PERM_OP(l,r,t,16,0x0000ffff); + PERM_OP(r,l,t, 2,0x33333333); + PERM_OP(l,r,t, 8,0x00ff00ff); + PERM_OP(r,l,t, 1,0x55555555); + /* r and l are reversed - remember that :-) - fix + * it in the next step */ + + /* Things have been modified so that the initial rotate is + * done outside the loop. This required the + * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * One perl script later and things have a 5% speed up on a sparc2. + * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> + * for pointing this out. */ + t=(r<<1)|(r>>31); + r=(l<<1)|(l>>31); + l=t; + + /* clear the top bits on machines with 8byte longs */ + l&=0xffffffff; + r&=0xffffffff; + + s=(unsigned long *)ks; + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (encrypt) + { + for (i=0; i<32; i+=4) + { + D_ENCRYPT(l,r,i+0); /* 1 */ + D_ENCRYPT(r,l,i+2); /* 2 */ + } + } + else + { + for (i=30; i>0; i-=4) + { + D_ENCRYPT(l,r,i-0); /* 16 */ + D_ENCRYPT(r,l,i-2); /* 15 */ + } + } + l=(l>>1)|(l<<31); + r=(r>>1)|(r<<31); + /* clear the top bits on machines with 8byte longs */ + l&=0xffffffff; + r&=0xffffffff; + + /* swap l and r + * we will not do the swap so just remember they are + * reversed for the rest of the subroutine + * luckily FP fixes this problem :-) */ + + PERM_OP(r,l,t, 1,0x55555555); + PERM_OP(l,r,t, 8,0x00ff00ff); + PERM_OP(r,l,t, 2,0x33333333); + PERM_OP(l,r,t,16,0x0000ffff); + PERM_OP(r,l,t, 4,0x0f0f0f0f); + + output[0]=l; + output[1]=r; + l=r=t=u=0; + return(0); +} + +static int des_ecb_encrypt(des_cblock *input, des_cblock *output, + des_key_schedule ks, int encrypt) +{ + register unsigned long l0,l1; + register unsigned char *in,*out; + unsigned long ll[2]; + + in=(unsigned char *)input; + out=(unsigned char *)output; + c2l(in,l0); + c2l(in,l1); + ll[0]=l0; + ll[1]=l1; + des_encrypt(ll,ll,ks,encrypt); + l0=ll[0]; + l1=ll[1]; + l2c(l0,out); + l2c(l1,out); + l0=l1=ll[0]=ll[1]=0; + return(0); +} + + + +static void block_decrypt(block_state *self, + unsigned char *in, + unsigned char *out) +{ + des_cblock output, output2; + + des_ecb_encrypt((des_cblock *)in, &output, self->KeySched3, 0); + des_ecb_encrypt(&output, &output2, self->KeySched2, 1); + des_ecb_encrypt(&output2, (des_cblock *)out, self->KeySched1, 0); +} + +static void block_encrypt(block_state *self, + unsigned char *in, + unsigned char *out) +{ + des_cblock output, output2; + + des_ecb_encrypt((des_cblock *)in, &output, self->KeySched1, 1); + des_ecb_encrypt(&output, &output2, self->KeySched2, 0); + des_ecb_encrypt(&output2, (des_cblock *)out, self->KeySched3, 1); +} + +/* NOW DEFINED IN des_local.h + * See ecb_encrypt.c for a pseudo description of these macros. + * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ + * (b)^=(t),\ + * (a)=((a)^((t)<<(n)))) + */ + +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n)))) + +static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; + +static int des_set_key(des_cblock *key, des_key_schedule schedule) +{ + register unsigned long c,d,t,s; + register unsigned char *in; + register unsigned long *k; + register int i; + + k=(unsigned long *)schedule; + in=(unsigned char *)key; + + c2l(in,c); + c2l(in,d); + + /* do PC1 in 60 simple operations */ +/* PERM_OP(d,c,t,4,0x0f0f0f0f); + HPERM_OP(c,t,-2, 0xcccc0000); + HPERM_OP(c,t,-1, 0xaaaa0000); + HPERM_OP(c,t, 8, 0x00ff0000); + HPERM_OP(c,t,-1, 0xaaaa0000); + HPERM_OP(d,t,-8, 0xff000000); + HPERM_OP(d,t, 8, 0x00ff0000); + HPERM_OP(d,t, 2, 0x33330000); + d=((d&0x00aa00aa)<<7)|((d&0x55005500)>>7)|(d&0xaa55aa55); + d=(d>>8)|((c&0xf0000000)>>4); + c&=0x0fffffff; */ + + /* I now do it in 47 simple operations :-) + * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) + * for the inspiration. :-) */ + PERM_OP (d,c,t,4,0x0f0f0f0f); + HPERM_OP(c,t,-2,0xcccc0000); + HPERM_OP(d,t,-2,0xcccc0000); + PERM_OP (d,c,t,1,0x55555555); + PERM_OP (c,d,t,8,0x00ff00ff); + PERM_OP (d,c,t,1,0x55555555); + d= (((d&0x000000ff)<<16)| (d&0x0000ff00) | + ((d&0x00ff0000)>>16)|((c&0xf0000000)>>4)); + c&=0x0fffffff; + + for (i=0; i<16; i++) + { + if (shifts2[i]) + { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); } + else + { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); } + c&=0x0fffffff; + d&=0x0fffffff; + /* could be a few less shifts but I am to lazy at this + * point in time to investigate */ + s= des_skb[0][ (c )&0x3f ]| + des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]| + des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]| + des_skb[3][((c>>20)&0x01)|((c>>21)&0x06) | + ((c>>22)&0x38)]; + t= des_skb[4][ (d )&0x3f ]| + des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]| + des_skb[6][ (d>>15)&0x3f ]| + des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)]; + + /* table contained 0213 4657 */ + *(k++)=((t<<16)|(s&0x0000ffff))&0xffffffff; + s= ((s>>16)|(t&0xffff0000)); + + s=(s<<4)|(s>>28); + *(k++)=s&0xffffffff; + } + return(0); +} + +static const unsigned char odd_parity[256]={ + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, + 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, + 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, + 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, + 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, + 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, + 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, + 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, + 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, + 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; + +static void block_init(block_state *self, unsigned char *key, + int keylength) +{ + char oddkey[24]; + int i; + + if (keylength != 16 && keylength != 24) { + PyErr_SetString(PyExc_ValueError, + "DES3 key must be either 16 or 24 bytes long"); + return; + } + + for (i=0; iKeySched1); + des_set_key((des_cblock *)(oddkey+8), self->KeySched2); + if (keylength == 24) { + des_set_key((des_cblock *)(oddkey+16), self->KeySched3); + } else { + memcpy(self->KeySched3, self->KeySched1, + sizeof(self->KeySched3)); + } +} + +#include "block_template.c" diff --git a/src/Crypto/src/MD2.c b/src/Crypto/src/MD2.c new file mode 100644 index 00000000..aa53c59c --- /dev/null +++ b/src/Crypto/src/MD2.c @@ -0,0 +1,118 @@ + +/* + * md2.c : MD2 hash algorithm. + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + + +#include +#include "Python.h" + +#define MODULE_NAME MD2 +#define DIGEST_SIZE 16 + +typedef unsigned char U8; +typedef unsigned int U32; + +typedef struct { + U8 C[16], X[48]; + int count; + U8 buf[16]; +} hash_state; + +static void hash_init (hash_state *ptr) +{ + memset(ptr->X, 0, 48); + memset(ptr->C, 0, 16); + ptr->count=0; +} + +static U8 S[256] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 +}; + +static void +hash_copy(hash_state *src, hash_state *dest) +{ + dest->count=src->count; + memcpy(dest->buf, src->buf, dest->count); + memcpy(dest->X, src->X, 48); + memcpy(dest->C, src->C, 16); +} + + +static void hash_update (hash_state *self, const U8 *buf, U32 len) +{ + U32 L; + while (len) + { + L=(16-self->count) < len ? (16-self->count) : len; + memcpy(self->buf+self->count, buf, L); + self->count+=L; + buf+=L; + len-=L; + if (self->count==16) + { + U8 t; + int i,j; + + self->count=0; + memcpy(self->X+16, self->buf, 16); + t=self->C[15]; + for(i=0; i<16; i++) + { + self->X[32+i]=self->X[16+i]^self->X[i]; + t=self->C[i]^=S[self->buf[i]^t]; + } + + t=0; + for(i=0; i<18; i++) + { + for(j=0; j<48; j++) + t=self->X[j]^=S[t]; + t=(t+i) & 0xFF; + } + } + } +} + +static PyObject * +hash_digest (const hash_state *self) +{ + U8 padding[16]; + U32 padlen; + hash_state temp; + int i; + + memcpy(&temp, self, sizeof(hash_state)); + padlen= 16-self->count; + for(i=0; i +#include + +#define MODULE_NAME MD4 +#define DIGEST_SIZE 16 + +typedef unsigned int U32; +typedef unsigned char U8; +#define U32_MAX (U32)4294967295 + +typedef struct { + U32 A,B,C,D, count; + U32 len1, len2; + U8 buf[64]; +} hash_state; + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROL(x, n) (((x) << n) | ((x) >> (32-n) )) + +static void +hash_init (hash_state *ptr) +{ + ptr->A=(U32)0x67452301; + ptr->B=(U32)0xefcdab89; + ptr->C=(U32)0x98badcfe; + ptr->D=(U32)0x10325476; + ptr->count=ptr->len1=ptr->len2=0; +} + +static void +hash_copy(hash_state *src, hash_state *dest) +{ + dest->len1=src->len1; + dest->len2=src->len2; + dest->A=src->A; + dest->B=src->B; + dest->C=src->C; + dest->D=src->D; + dest->count=src->count; + memcpy(dest->buf, src->buf, dest->count); +} + +static void +hash_update (hash_state *self, const U8 *buf, U32 len) +{ + U32 L; + + if ((self->len1+(len<<3))len1) + { + self->len2++; + } + self->len1+=len<< 3; + self->len2+=len>>29; + while (len>0) + { + L=(64-self->count) < len ? (64-self->count) : len; + memcpy(self->buf+self->count, buf, L); + self->count+=L; + buf+=L; + len-=L; + if (self->count==64) + { + U32 X[16], A, B, C, D; + int i,j; + self->count=0; + for(i=j=0; j<16; i+=4, j++) + X[j]=((U32)self->buf[i] + ((U32)self->buf[i+1]<<8) + + ((U32)self->buf[i+2]<<16) + ((U32)self->buf[i+3]<<24)); + + + A=self->A; B=self->B; C=self->C; D=self->D; + +#define function(a,b,c,d,k,s) a=ROL(a+F(b,c,d)+X[k],s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 1, 7); + function(C,D,A,B, 2,11); + function(B,C,D,A, 3,19); + function(A,B,C,D, 4, 3); + function(D,A,B,C, 5, 7); + function(C,D,A,B, 6,11); + function(B,C,D,A, 7,19); + function(A,B,C,D, 8, 3); + function(D,A,B,C, 9, 7); + function(C,D,A,B,10,11); + function(B,C,D,A,11,19); + function(A,B,C,D,12, 3); + function(D,A,B,C,13, 7); + function(C,D,A,B,14,11); + function(B,C,D,A,15,19); + +#undef function +#define function(a,b,c,d,k,s) a=ROL(a+G(b,c,d)+X[k]+(U32)0x5a827999,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 4, 5); + function(C,D,A,B, 8, 9); + function(B,C,D,A,12,13); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 5, 5); + function(C,D,A,B, 9, 9); + function(B,C,D,A,13,13); + function(A,B,C,D, 2, 3); + function(D,A,B,C, 6, 5); + function(C,D,A,B,10, 9); + function(B,C,D,A,14,13); + function(A,B,C,D, 3, 3); + function(D,A,B,C, 7, 5); + function(C,D,A,B,11, 9); + function(B,C,D,A,15,13); + +#undef function +#define function(a,b,c,d,k,s) a=ROL(a+H(b,c,d)+X[k]+(U32)0x6ed9eba1,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 8, 9); + function(C,D,A,B, 4,11); + function(B,C,D,A,12,15); + function(A,B,C,D, 2, 3); + function(D,A,B,C,10, 9); + function(C,D,A,B, 6,11); + function(B,C,D,A,14,15); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 9, 9); + function(C,D,A,B, 5,11); + function(B,C,D,A,13,15); + function(A,B,C,D, 3, 3); + function(D,A,B,C,11, 9); + function(C,D,A,B, 7,11); + function(B,C,D,A,15,15); + + self->A+=A; self->B+=B; self->C+=C; self->D+=D; + } + } +} + +static PyObject * +hash_digest (const hash_state *self) +{ + U8 digest[16]; + static U8 s[8]; + U32 padlen, oldlen1, oldlen2; + hash_state temp; + static U8 padding[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + memcpy(&temp, self, sizeof(hash_state)); + oldlen1=temp.len1; oldlen2=temp.len2; /* Save current length */ + padlen= (56<=self->count) ? 56-self->count+64: 56-self->count; + hash_update(&temp, padding, padlen); + s[0]= oldlen1 & 255; + s[1]=(oldlen1 >> 8) & 255; + s[2]=(oldlen1 >> 16) & 255; + s[3]=(oldlen1 >> 24) & 255; + s[4]= oldlen2 & 255; + s[5]=(oldlen2 >> 8) & 255; + s[6]=(oldlen2 >> 16) & 255; + s[7]=(oldlen2 >> 24) & 255; + hash_update(&temp, s, 8); + + digest[ 0]= temp.A & 255; + digest[ 1]=(temp.A >> 8) & 255; + digest[ 2]=(temp.A >> 16) & 255; + digest[ 3]=(temp.A >> 24) & 255; + digest[ 4]= temp.B & 255; + digest[ 5]=(temp.B >> 8) & 255; + digest[ 6]=(temp.B >> 16) & 255; + digest[ 7]=(temp.B >> 24) & 255; + digest[ 8]= temp.C & 255; + digest[ 9]=(temp.C >> 8) & 255; + digest[10]=(temp.C >> 16) & 255; + digest[11]=(temp.C >> 24) & 255; + digest[12]= temp.D & 255; + digest[13]=(temp.D >> 8) & 255; + digest[14]=(temp.D >> 16) & 255; + digest[15]=(temp.D >> 24) & 255; + + return PyString_FromStringAndSize(digest, 16); +} + +#include "hash_template.c" diff --git a/src/Crypto/src/SHA256.c b/src/Crypto/src/SHA256.c new file mode 100644 index 00000000..6bd9df2b --- /dev/null +++ b/src/Crypto/src/SHA256.c @@ -0,0 +1,200 @@ +/* + * An implementation of the SHA-256 hash function, this is endian neutral + * so should work just about anywhere. + * + * This code works much like the MD5 code provided by RSA. You sha_init() + * a "sha_state" then sha_process() the bytes you want and sha_done() to get + * the output. + * + * Revised Code: Complies to SHA-256 standard now. + * + * Tom St Denis -- http://tomstdenis.home.dhs.org + * */ +#include "Python.h" +#define MODULE_NAME SHA256 +#define DIGEST_SIZE 32 + +typedef unsigned char U8; +#ifdef __alpha__ +typedef unsigned int U32; +#elif defined(__amd64__) +#include +typedef uint32_t U32; +#else +typedef unsigned int U32; +#endif + +typedef struct { + U32 state[8], length, curlen; + unsigned char buf[64]; +} +hash_state; + +/* the K array */ +static const U32 K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Various logical functions */ +#define Ch(x,y,z) ((x & y) ^ (~x & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) +#define S(x, n) (((x)>>((n)&31))|((x)<<(32-((n)&31)))) +#define R(x, n) ((x)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +static void sha_compress(hash_state * md) +{ + U32 S[8], W[64], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) + S[i] = md->state[i]; + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) + W[i] = (((U32) md->buf[(4 * i) + 0]) << 24) | + (((U32) md->buf[(4 * i) + 1]) << 16) | + (((U32) md->buf[(4 * i) + 2]) << 8) | + (((U32) md->buf[(4 * i) + 3])); + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + + /* Compress */ + for (i = 0; i < 64; i++) { + t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + t0; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t0 + t1; + } + + /* feedback */ + for (i = 0; i < 8; i++) + md->state[i] += S[i]; +} + +/* init the SHA state */ +void sha_init(hash_state * md) +{ + md->curlen = md->length = 0; + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; +} + +void sha_process(hash_state * md, unsigned char *buf, int len) +{ + while (len--) { + /* copy byte */ + md->buf[md->curlen++] = *buf++; + + /* is 64 bytes full? */ + if (md->curlen == 64) { + sha_compress(md); + md->length += 512; + md->curlen = 0; + } + } +} + +void sha_done(hash_state * md, unsigned char *hash) +{ + int i; + + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = 0x80; + + /* if the length is currenlly above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen >= 56) { + for (; md->curlen < 64;) + md->buf[md->curlen++] = 0; + sha_compress(md); + md->curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + for (; md->curlen < 56;) + md->buf[md->curlen++] = 0; + + /* since all messages are under 2^32 bits we mark the top bits zero */ + for (i = 56; i < 60; i++) + md->buf[i] = 0; + + /* append length */ + for (i = 60; i < 64; i++) + md->buf[i] = (md->length >> ((63 - i) * 8)) & 255; + sha_compress(md); + + /* copy output */ + for (i = 0; i < 32; i++) + hash[i] = (md->state[i >> 2] >> (((3 - i) & 3) << 3)) & 255; +} + +// Done +static void hash_init (hash_state *ptr) +{ + sha_init(ptr); +} + +// Done +static void +hash_update (hash_state *self, const U8 *buf, U32 len) +{ + sha_process(self,(unsigned char *)buf,len); +} + +// Done +static void +hash_copy(hash_state *src, hash_state *dest) +{ + memcpy(dest,src,sizeof(hash_state)); +} + +// Done +static PyObject * +hash_digest (const hash_state *self) +{ + unsigned char digest[32]; + hash_state temp; + + hash_copy((hash_state*)self,&temp); + sha_done(&temp,digest); + return PyString_FromStringAndSize(digest, 32); +} + +#include "hash_template.c" diff --git a/src/Crypto/src/XOR.c b/src/Crypto/src/XOR.c new file mode 100644 index 00000000..f2c74afa --- /dev/null +++ b/src/Crypto/src/XOR.c @@ -0,0 +1,52 @@ +/* + * xor.c : Source for the trivial cipher which XORs the message with the key. + * The key can be up to 32 bytes long. + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#define MODULE_NAME XOR +#define BLOCK_SIZE 1 +#define KEY_SIZE 0 + +typedef struct +{ + unsigned char key[32]; + int keylen, last_pos; +} stream_state; + +static void +stream_init(stream_state *self, unsigned char *key, int len) +{ + int i; + + if (32 <= len) len=32; + self->keylen = len; + self->last_pos = 0; + + for(i=0; ikey[i] = key[i]; + } +} + +/* Encryption and decryption are symmetric */ +#define stream_decrypt stream_encrypt + +static void stream_encrypt(stream_state *self, unsigned char *block, + int len) +{ + int i, j = self->last_pos; + for(i=0; ikeylen) + { + block[i] ^= self->key[j]; + } + self->last_pos = j; +} + +#include "stream_template.c" diff --git a/src/Crypto/src/_dsa.c b/src/Crypto/src/_dsa.c new file mode 100644 index 00000000..4752f438 --- /dev/null +++ b/src/Crypto/src/_dsa.c @@ -0,0 +1,331 @@ + +/* + * _dsa.c: C implementation of the DSA algorithm. + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#include +#include +#include +#include /* for conversions */ +#include + +PyObject *_dsa_module; +PyObject *_dsa_dict; + +void +longObjToMPZ (mpz_t m, PyLongObject * p) +{ + int size, i; + mpz_t temp, temp2; + mpz_init (temp); + mpz_init (temp2); + if (p->ob_size > 0) + size = p->ob_size; + else + size = -p->ob_size; + for (i = 0; i < size; i++) + { + mpz_set_ui (temp, p->ob_digit[i]); + mpz_mul_2exp (temp2, temp, SHIFT * i); + mpz_add (m, m, temp2); + } + mpz_clear (temp); + mpz_clear (temp2); +} + +PyObject * +mpzToLongObj (mpz_t m) +{ + /* borrowed from gmpy */ + int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT; + int i; + mpz_t temp; + PyLongObject *l = _PyLong_New (size); + if (!l) + { + return NULL; + } + mpz_init_set (temp, m); + for (i = 0; i < size; i++) + { + l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK); + mpz_fdiv_q_2exp (temp, temp, SHIFT); + } + i = size; + while ((i > 0) && (l->ob_digit[i - 1] == 0)) + i--; + l->ob_size = i; + mpz_clear (temp); + return (PyObject *) l; +} + +PyObject *dsaKey_new (PyObject *, PyObject *); + +static PyMethodDef _dsa__methods__[] = { + {"construct", dsaKey_new, METH_VARARGS}, + {NULL, NULL} +}; + +typedef struct +{ + PyObject_HEAD mpz_t y; + mpz_t g; + mpz_t p; + mpz_t q; + mpz_t x; +} +dsaKey; + +static int +dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s) +{ + mpz_t temp; + if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0) + { + return 1; + } + mpz_init (temp); + mpz_powm (r, key->g, k, key->p); + mpz_mod (r, r, key->q); + mpz_invert (s, k, key->q); + mpz_mul (temp, key->x, r); + mpz_add (temp, m, temp); + mpz_mul (s, s, temp); + mpz_mod (s, s, key->q); + mpz_clear (temp); + return 0; +} + +static int +dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s) +{ + int result; + mpz_t u1, u2, v1, v2, w; + if (mpz_cmp_ui (r, 0) <= 0 || mpz_cmp (r, key->q) >= 0 || + mpz_cmp_ui (s, 0) <= 0 || mpz_cmp (s, key->q) >= 0) + return 0; + mpz_init (u1); + mpz_init (u2); + mpz_init (v1); + mpz_init (v2); + mpz_init (w); + mpz_invert (w, s, key->q); + mpz_mul (u1, m, w); + mpz_mod (u1, u1, key->q); + mpz_mul (u2, r, w); + mpz_mod (u2, u2, key->q); + mpz_powm (v1, key->g, u1, key->p); + mpz_powm (v2, key->y, u2, key->p); + mpz_mul (w, v1, v2); + mpz_mod (w, w, key->p); + mpz_mod (w, w, key->q); + if (mpz_cmp (r, w) == 0) + result = 1; + else + result = 0; + mpz_clear (u1); + mpz_clear (u2); + mpz_clear (v1); + mpz_clear (v2); + mpz_clear (w); + return result; +} + +static void dsaKey_dealloc (dsaKey *); +static PyObject *dsaKey_getattr (dsaKey *, char *); +static PyObject *dsaKey__sign (dsaKey *, PyObject *); +static PyObject *dsaKey__verify (dsaKey *, PyObject *); +static PyObject *dsaKey_size (dsaKey *, PyObject *); +static PyObject *dsaKey_hasprivate (dsaKey *, PyObject *); + +PyObject *dsaError; /* raised on errors */ + +static PyTypeObject dsaKeyType = { + PyObject_HEAD_INIT (NULL) 0, + "dsaKey", + sizeof (dsaKey), + 0, + (destructor) dsaKey_dealloc, /* dealloc */ + 0, /* print */ + (getattrfunc) dsaKey_getattr, /* getattr */ + 0, /* setattr */ + 0, /* compare */ + 0, /* repr */ + 0, /* as_number */ + 0, /* as_sequence */ + 0, /* as_mapping */ + 0, /* hash */ + 0, /* call */ +}; + +static PyMethodDef dsaKey__methods__[] = { + {"_sign", (PyCFunction) dsaKey__sign, METH_VARARGS, "Sign the given long."}, + {"_verify", (PyCFunction) dsaKey__verify, METH_VARARGS, + "Verify that the signature is valid."}, + {"size", (PyCFunction) dsaKey_size, METH_VARARGS, + "Return the number of bits that this key can handle."}, + {"hasprivate", (PyCFunction) dsaKey_hasprivate, METH_VARARGS, + "Return 1 or 0 if this key does/doesn't have a private key."}, + {NULL, NULL, 0, NULL} +}; + +PyObject * +dsaKey_new (PyObject * self, PyObject * args) +{ + PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL; + dsaKey *key; + key = PyObject_New (dsaKey, &dsaKeyType); + mpz_init (key->y); + mpz_init (key->g); + mpz_init (key->p); + mpz_init (key->q); + mpz_init (key->x); + PyArg_ParseTuple (args, "O!O!O!O!|O!", &PyLong_Type, &y, + &PyLong_Type, &g, + &PyLong_Type, &p, &PyLong_Type, &q, &PyLong_Type, &x); + longObjToMPZ (key->y, y); + longObjToMPZ (key->g, g); + longObjToMPZ (key->p, p); + longObjToMPZ (key->q, q); + if (x) + { + longObjToMPZ (key->x, x); + } + /*Py_XDECREF(n); + Py_XDECREF(e); + Py_XDECREF(d); + Py_XDECREF(p); + Py_XDECREF(q); */ + return (PyObject *) key; +} + +static void +dsaKey_dealloc (dsaKey * key) +{ + mpz_clear (key->y); + mpz_clear (key->g); + mpz_clear (key->p); + mpz_clear (key->q); + mpz_clear (key->x); + PyObject_Del (key); +} + +static PyObject * +dsaKey_getattr (dsaKey * key, char *attr) +{ + if (strcmp (attr, "y") == 0) + return mpzToLongObj (key->y); + else if (strcmp (attr, "g") == 0) + return mpzToLongObj (key->g); + else if (strcmp (attr, "p") == 0) + return mpzToLongObj (key->p); + else if (strcmp (attr, "q") == 0) + return mpzToLongObj (key->q); + else if (strcmp (attr, "x") == 0) + { + if (mpz_size (key->x) == 0) + { + PyErr_SetString (PyExc_AttributeError, + "rsaKey instance has no attribute 'x'"); + return NULL; + } + return mpzToLongObj (key->x); + } + else + { + return Py_FindMethod (dsaKey__methods__, (PyObject *) key, attr); + } +} + +PyObject * +dsaKey__sign (dsaKey * key, PyObject * args) +{ + PyObject *lm, *lk, *lr, *ls; + mpz_t m, k, r, s; + int result; + if (!(PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm, + &PyLong_Type, &lk))) + { + return NULL; + } + mpz_init (m); + mpz_init (k); + mpz_init (r); + mpz_init (s); + longObjToMPZ (m, (PyLongObject *) lm); + longObjToMPZ (k, (PyLongObject *) lk); + result = dsaSign (key, m, k, r, s); + if (result == 1) + { + PyErr_SetString (dsaError, "K not between 2 and q"); + return NULL; + } + lr = mpzToLongObj (r); + ls = mpzToLongObj (s); + mpz_clear (m); + mpz_clear (k); + mpz_clear (r); + mpz_clear (s); + return Py_BuildValue ("(NN)", lr, ls); +} + +PyObject * +dsaKey__verify (dsaKey * key, PyObject * args) +{ + PyObject *lm, *lr, *ls; + mpz_t m, r, s; + int result; + if (!(PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm, + &PyLong_Type, &lr, &PyLong_Type, &ls))) + { + return NULL; + } + mpz_init (m); + mpz_init (r); + mpz_init (s); + longObjToMPZ (m, (PyLongObject *) lm); + longObjToMPZ (r, (PyLongObject *) lr); + longObjToMPZ (s, (PyLongObject *) ls); + result = dsaVerify (key, m, r, s); + mpz_clear (m); + mpz_clear (r); + mpz_clear (s); + return Py_BuildValue ("i", result); +} + +PyObject * +dsaKey_size (dsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1); +} + +PyObject * +dsaKey_hasprivate (dsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + if (mpz_size (key->x) == 0) + return Py_BuildValue ("i", 0); + else + return Py_BuildValue ("i", 1); +} + + +void +init_dsa (void) +{ + dsaKeyType.ob_type = &PyType_Type; + _dsa_module = Py_InitModule ("_dsa", _dsa__methods__); + _dsa_dict = PyModule_GetDict (_dsa_module); + dsaError = PyErr_NewException ("_dsa.error", NULL, NULL); + PyDict_SetItemString (_dsa_dict, "error", dsaError); +} diff --git a/src/Crypto/src/_fastmath.c b/src/Crypto/src/_fastmath.c new file mode 100644 index 00000000..7fe7abec --- /dev/null +++ b/src/Crypto/src/_fastmath.c @@ -0,0 +1,804 @@ + +/* + * _fastmath.c: Accelerator module that uses GMP for faster numerics. + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + * $Id: _fastmath.c,v 1.13 2003/04/04 19:20:29 jbontje Exp $ + */ + +#include +#include +#include +#include /* for conversions */ +#include + +void +longObjToMPZ (mpz_t m, PyLongObject * p) +{ + int size, i; + mpz_t temp, temp2; + mpz_init (temp); + mpz_init (temp2); + if (p->ob_size > 0) + size = p->ob_size; + else + size = -p->ob_size; + for (i = 0; i < size; i++) + { + mpz_set_ui (temp, p->ob_digit[i]); + mpz_mul_2exp (temp2, temp, SHIFT * i); + mpz_add (m, m, temp2); + } + mpz_clear (temp); + mpz_clear (temp2); +} + +PyObject * +mpzToLongObj (mpz_t m) +{ + /* borrowed from gmpy */ + int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT; + int i; + mpz_t temp; + PyLongObject *l = _PyLong_New (size); + if (!l) + return NULL; + mpz_init_set (temp, m); + for (i = 0; i < size; i++) + { + l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK); + mpz_fdiv_q_2exp (temp, temp, SHIFT); + } + i = size; + while ((i > 0) && (l->ob_digit[i - 1] == 0)) + i--; + l->ob_size = i; + mpz_clear (temp); + return (PyObject *) l; +} + +typedef struct +{ + PyObject_HEAD mpz_t y; + mpz_t g; + mpz_t p; + mpz_t q; + mpz_t x; +} +dsaKey; + +typedef struct +{ + PyObject_HEAD mpz_t n; + mpz_t e; + mpz_t d; + mpz_t p; + mpz_t q; + mpz_t u; +} +rsaKey; + +PyObject *rsaKey_new (PyObject *, PyObject *); +PyObject *dsaKey_new (PyObject *, PyObject *); + +static void dsaKey_dealloc (dsaKey *); +static PyObject *dsaKey_getattr (dsaKey *, char *); +static PyObject *dsaKey__sign (dsaKey *, PyObject *); +static PyObject *dsaKey__verify (dsaKey *, PyObject *); +static PyObject *dsaKey_size (dsaKey *, PyObject *); +static PyObject *dsaKey_has_private (dsaKey *, PyObject *); + +static void rsaKey_dealloc (rsaKey *); +static PyObject *rsaKey_getattr (rsaKey *, char *); +static PyObject *rsaKey__encrypt (rsaKey *, PyObject *); +static PyObject *rsaKey__decrypt (rsaKey *, PyObject *); +static PyObject *rsaKey__verify (rsaKey *, PyObject *); +static PyObject *rsaKey__blind (rsaKey *, PyObject *); +static PyObject *rsaKey__unblind (rsaKey *, PyObject *); +static PyObject *rsaKey_size (rsaKey *, PyObject *); +static PyObject *rsaKey_has_private (rsaKey *, PyObject *); + +static int +dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s) +{ + mpz_t temp; + if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0) + { + return 1; + } + mpz_init (temp); + mpz_powm (r, key->g, k, key->p); + mpz_mod (r, r, key->q); + mpz_invert (s, k, key->q); + mpz_mul (temp, key->x, r); + mpz_add (temp, m, temp); + mpz_mul (s, s, temp); + mpz_mod (s, s, key->q); + mpz_clear (temp); + return 0; +} + +static int +dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s) +{ + int result; + mpz_t u1, u2, v1, v2, w; + if (mpz_cmp_ui (r, 0) <= 0 || mpz_cmp (r, key->q) >= 0 || + mpz_cmp_ui (s, 0) <= 0 || mpz_cmp (s, key->q) >= 0) + return 0; + mpz_init (u1); + mpz_init (u2); + mpz_init (v1); + mpz_init (v2); + mpz_init (w); + mpz_invert (w, s, key->q); + mpz_mul (u1, m, w); + mpz_mod (u1, u1, key->q); + mpz_mul (u2, r, w); + mpz_mod (u2, u2, key->q); + mpz_powm (v1, key->g, u1, key->p); + mpz_powm (v2, key->y, u2, key->p); + mpz_mul (w, v1, v2); + mpz_mod (w, w, key->p); + mpz_mod (w, w, key->q); + if (mpz_cmp (r, w) == 0) + result = 1; + else + result = 0; + mpz_clear (u1); + mpz_clear (u2); + mpz_clear (v1); + mpz_clear (v2); + mpz_clear (w); + return result; +} + + +static int +rsaEncrypt (rsaKey * key, mpz_t v) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + mpz_powm (v, v, key->e, key->n); + return 0; +} + +static int +rsaDecrypt (rsaKey * key, mpz_t v) +{ + mpz_t m1, m2, h; + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + if (mpz_size (key->d) == 0) + { + return 2; + } + + if ((mpz_size (key->p) != 0) && (mpz_size (key->q) != 0) && + (mpz_size (key->u) != 0)) + { + /* fast path */ + mpz_init(m1); + mpz_init(m2); + mpz_init(h); + + /* m1 = c ^ (d mod (p-1)) mod p */ + mpz_sub_ui(h, key->p, 1); + mpz_fdiv_r(h, key->d, h); + mpz_powm(m1, v, h, key->p); + /* m2 = c ^ (d mod (q-1)) mod q */ + mpz_sub_ui(h, key->q, 1); + mpz_fdiv_r(h, key->d, h); + mpz_powm(m2, v, h, key->q); + /* h = u * ( m2 - m1 ) mod q */ + mpz_sub(h, m2, m1); + if (mpz_sgn(h)==-1) + mpz_add(h, h, key->q); + mpz_mul(h, key->u, h); + mpz_mod(h, h, key->q); + /* m = m2 + h * p */ + mpz_mul(h, h, key->p); + mpz_add(v, m1, h); + /* ready */ + + mpz_clear(m1); + mpz_clear(m2); + mpz_clear(h); + return 0; + } + + /* slow */ + mpz_powm (v, v, key->d, key->n); + return 0; +} + +static int +rsaBlind (rsaKey * key, mpz_t v, mpz_t b) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + if (mpz_cmp (b, key->n) >= 0) + { + return 2; + } + mpz_powm (b, b, key->e, key->n); + mpz_mul (v, v, b); + mpz_mod (v, v, key->n); + return 0; +} + +static int +rsaUnBlind (rsaKey * key, mpz_t v, mpz_t b) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + if (mpz_cmp (b, key->n) >= 0) + { + return 2; + } + if (!mpz_invert (b, b, key->n)) + { + return 3; + } + mpz_mul (v, v, b); + mpz_mod (v, v, key->n); + return 0; +} + + +static PyTypeObject dsaKeyType = { + PyObject_HEAD_INIT (NULL) 0, + "dsaKey", + sizeof (dsaKey), + 0, + (destructor) dsaKey_dealloc, /* dealloc */ + 0, /* print */ + (getattrfunc) dsaKey_getattr, /* getattr */ + 0, /* setattr */ + 0, /* compare */ + 0, /* repr */ + 0, /* as_number */ + 0, /* as_sequence */ + 0, /* as_mapping */ + 0, /* hash */ + 0, /* call */ +}; + +static PyMethodDef dsaKey__methods__[] = { + {"_sign", (PyCFunction) dsaKey__sign, METH_VARARGS, + "Sign the given long."}, + {"_verify", (PyCFunction) dsaKey__verify, METH_VARARGS, + "Verify that the signature is valid."}, + {"size", (PyCFunction) dsaKey_size, METH_VARARGS, + "Return the number of bits that this key can handle."}, + {"has_private", (PyCFunction) dsaKey_has_private, METH_VARARGS, + "Return 1 or 0 if this key does/doesn't have a private key."}, + {NULL, NULL, 0, NULL} +}; + +PyObject *fastmathError; /* raised on errors */ + +static PyTypeObject rsaKeyType = { + PyObject_HEAD_INIT (NULL) 0, + "rsaKey", + sizeof (rsaKey), + 0, + (destructor) rsaKey_dealloc, /* dealloc */ + 0, /* print */ + (getattrfunc) rsaKey_getattr, /* getattr */ + 0, /* setattr */ + 0, /* compare */ + 0, /* repr */ + 0, /* as_number */ + 0, /* as_sequence */ + 0, /* as_mapping */ + 0, /* hash */ + 0, /* call */ +}; + +static PyMethodDef rsaKey__methods__[] = { + {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS, + "Encrypt the given long."}, + {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS, + "Decrypt the given long."}, + {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS, + "Sign the given long."}, + {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS, + "Verify that the signature is valid."}, + {"_blind", (PyCFunction) rsaKey__blind, METH_VARARGS, + "Blind the given long."}, + {"_unblind", (PyCFunction) rsaKey__unblind, METH_VARARGS, + "Unblind the given long."}, + {"size", (PyCFunction) rsaKey_size, METH_VARARGS, + "Return the number of bits that this key can handle."}, + {"has_private", (PyCFunction) rsaKey_has_private, METH_VARARGS, + "Return 1 or 0 if this key does/doesn't have a private key."}, + {NULL, NULL, 0, NULL} +}; + +PyObject * +dsaKey_new (PyObject * self, PyObject * args) +{ + PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL; + dsaKey *key; + if (!PyArg_ParseTuple(args, "O!O!O!O!|O!", &PyLong_Type, &y, + &PyLong_Type, &g, &PyLong_Type, &p, + &PyLong_Type, &q, &PyLong_Type, &x)) + return NULL; + + key = PyObject_New (dsaKey, &dsaKeyType); + mpz_init (key->y); + mpz_init (key->g); + mpz_init (key->p); + mpz_init (key->q); + mpz_init (key->x); + longObjToMPZ (key->y, y); + longObjToMPZ (key->g, g); + longObjToMPZ (key->p, p); + longObjToMPZ (key->q, q); + if (x) + { + longObjToMPZ (key->x, x); + } + return (PyObject *) key; +} + +static void +dsaKey_dealloc (dsaKey * key) +{ + mpz_clear (key->y); + mpz_clear (key->g); + mpz_clear (key->p); + mpz_clear (key->q); + mpz_clear (key->x); + PyObject_Del (key); +} + +static PyObject * +dsaKey_getattr (dsaKey * key, char *attr) +{ + if (strcmp (attr, "y") == 0) + return mpzToLongObj (key->y); + else if (strcmp (attr, "g") == 0) + return mpzToLongObj (key->g); + else if (strcmp (attr, "p") == 0) + return mpzToLongObj (key->p); + else if (strcmp (attr, "q") == 0) + return mpzToLongObj (key->q); + else if (strcmp (attr, "x") == 0) + { + if (mpz_size (key->x) == 0) + { + PyErr_SetString (PyExc_AttributeError, + "dsaKey instance has no attribute 'x'"); + return NULL; + } + return mpzToLongObj (key->x); + } + else + { + return Py_FindMethod (dsaKey__methods__, (PyObject *) key, attr); + } +} + +PyObject * +dsaKey__sign (dsaKey * key, PyObject * args) +{ + PyObject *lm, *lk, *lr, *ls; + mpz_t m, k, r, s; + int result; + if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm, + &PyLong_Type, &lk)) + { + return NULL; + } + mpz_init (m); + mpz_init (k); + mpz_init (r); + mpz_init (s); + longObjToMPZ (m, (PyLongObject *) lm); + longObjToMPZ (k, (PyLongObject *) lk); + result = dsaSign (key, m, k, r, s); + if (result == 1) + { + PyErr_SetString (fastmathError, "K not between 2 and q"); + return NULL; + } + lr = mpzToLongObj (r); + ls = mpzToLongObj (s); + mpz_clear (m); + mpz_clear (k); + mpz_clear (r); + mpz_clear (s); + return Py_BuildValue ("(NN)", lr, ls); +} + +PyObject * +dsaKey__verify (dsaKey * key, PyObject * args) +{ + PyObject *lm, *lr, *ls; + mpz_t m, r, s; + int result; + if (!PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm, + &PyLong_Type, &lr, &PyLong_Type, &ls)) + { + return NULL; + } + mpz_init (m); + mpz_init (r); + mpz_init (s); + longObjToMPZ (m, (PyLongObject *) lm); + longObjToMPZ (r, (PyLongObject *) lr); + longObjToMPZ (s, (PyLongObject *) ls); + result = dsaVerify (key, m, r, s); + mpz_clear (m); + mpz_clear (r); + mpz_clear (s); + if (result) { + Py_INCREF(Py_True); + return Py_True; + } else { + Py_INCREF(Py_False); + return Py_False; + } +} + +PyObject * +dsaKey_size (dsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1); +} + +PyObject * +dsaKey_has_private (dsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + if (mpz_size (key->x) == 0) { + Py_INCREF(Py_False); + return Py_False; + } else { + Py_INCREF(Py_True); + return Py_True; + } +} + +PyObject * +rsaKey_new (PyObject * self, PyObject * args) +{ + PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, + *u = NULL; + rsaKey *key; + + if (!PyArg_ParseTuple(args, "O!O!|O!O!O!O!", &PyLong_Type, &n, + &PyLong_Type, &e, &PyLong_Type, &d, + &PyLong_Type, &p, &PyLong_Type, &q, + &PyLong_Type, &u)) + return NULL; + + key = PyObject_New (rsaKey, &rsaKeyType); + mpz_init (key->n); + mpz_init (key->e); + mpz_init (key->d); + mpz_init (key->p); + mpz_init (key->q); + mpz_init (key->u); + longObjToMPZ (key->n, n); + longObjToMPZ (key->e, e); + if (!d) + { + return (PyObject *) key; + } + longObjToMPZ (key->d, d); + if (p && q) + { + longObjToMPZ (key->p, p); + longObjToMPZ (key->q, q); + if (u) { + longObjToMPZ (key->u, u); + } else { + mpz_invert (key->u, key->p, key->q); + } + } + return (PyObject *) key; +} + +static void +rsaKey_dealloc (rsaKey * key) +{ + mpz_clear (key->n); + mpz_clear (key->e); + mpz_clear (key->d); + mpz_clear (key->p); + mpz_clear (key->q); + mpz_clear (key->u); + PyObject_Del (key); +} + +static PyObject * +rsaKey_getattr (rsaKey * key, char *attr) +{ + if (strcmp (attr, "n") == 0) + return mpzToLongObj (key->n); + else if (strcmp (attr, "e") == 0) + return mpzToLongObj (key->e); + else if (strcmp (attr, "d") == 0) + { + if (mpz_size (key->d) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'd'"); + return NULL; + } + return mpzToLongObj (key->d); + } + else if (strcmp (attr, "p") == 0) + { + if (mpz_size (key->p) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'p'"); + return NULL; + } + return mpzToLongObj (key->p); + } + else if (strcmp (attr, "q") == 0) + { + if (mpz_size (key->q) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'q'"); + return NULL; + } + return mpzToLongObj (key->q); + } + else if (strcmp (attr, "u") == 0) + { + if (mpz_size (key->u) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'u'"); + return NULL; + } + return mpzToLongObj (key->u); + } + else + { + return Py_FindMethod (rsaKey__methods__, + (PyObject *) key, attr); + } +} + +PyObject * +rsaKey__encrypt (rsaKey * key, PyObject * args) +{ + PyObject *l, *r; + mpz_t v; + int result; + if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) + { + return NULL; + } + mpz_init (v); + longObjToMPZ (v, (PyLongObject *) l); + result = rsaEncrypt (key, v); + if (result == 1) + { + PyErr_SetString (fastmathError, "Plaintext too large"); + return NULL; + } + r = (PyObject *) mpzToLongObj (v); + mpz_clear (v); + return Py_BuildValue ("N", r); +} + +PyObject * +rsaKey__decrypt (rsaKey * key, PyObject * args) +{ + PyObject *l, *r; + mpz_t v; + int result; + if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) + { + return NULL; + } + mpz_init (v); + longObjToMPZ (v, (PyLongObject *) l); + result = rsaDecrypt (key, v); + if (result == 1) + { + PyErr_SetString (fastmathError, + "Ciphertext too large"); + return NULL; + } + else if (result == 2) + { + PyErr_SetString (fastmathError, + "Private key not available in this object"); + return NULL; + } + r = mpzToLongObj (v); + mpz_clear (v); + return Py_BuildValue ("N", r); +} + +PyObject * +rsaKey__verify (rsaKey * key, PyObject * args) +{ + PyObject *l, *lsig; + mpz_t v, vsig; + if (!PyArg_ParseTuple(args, "O!O!", + &PyLong_Type, &l, &PyLong_Type, &lsig)) + { + return NULL; + } + mpz_init (v); + mpz_init (vsig); + longObjToMPZ (v, (PyLongObject *) l); + longObjToMPZ (vsig, (PyLongObject *) lsig); + rsaEncrypt (key, vsig); + if (mpz_cmp (v, vsig) == 0) { + Py_INCREF(Py_True); + return Py_True; + } + else { + Py_INCREF(Py_False); + return Py_False; + } +} + +PyObject * +rsaKey__blind (rsaKey * key, PyObject * args) +{ + PyObject *l, *lblind, *r; + mpz_t v, vblind; + int result; + if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, + &PyLong_Type, &lblind)) + { + return NULL; + } + mpz_init (v); + mpz_init (vblind); + longObjToMPZ (v, (PyLongObject *) l); + longObjToMPZ (vblind, (PyLongObject *) lblind); + result = rsaBlind (key, v, vblind); + if (result == 1) + { + PyErr_SetString (fastmathError, "Message too large"); + return NULL; + } + else if (result == 2) + { + PyErr_SetString (fastmathError, "Blinding factor too large"); + return NULL; + } + r = (PyObject *) mpzToLongObj (v); + mpz_clear (v); + mpz_clear (vblind); + return Py_BuildValue ("N", r); +} + +PyObject * +rsaKey__unblind (rsaKey * key, PyObject * args) +{ + PyObject *l, *lblind, *r; + mpz_t v, vblind; + int result; + if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, + &PyLong_Type, &lblind)) + { + return NULL; + } + mpz_init (v); + mpz_init (vblind); + longObjToMPZ (v, (PyLongObject *) l); + longObjToMPZ (vblind, (PyLongObject *) lblind); + result = rsaUnBlind (key, v, vblind); + if (result == 1) + { + PyErr_SetString (fastmathError, "Message too large"); + return NULL; + } + else if (result == 2) + { + PyErr_SetString (fastmathError, "Blinding factor too large"); + return NULL; + } + else if (result == 3) + { + PyErr_SetString (fastmathError, "Inverse doesn't exist"); + return NULL; + } + r = (PyObject *) mpzToLongObj (v); + mpz_clear (v); + mpz_clear (vblind); + return Py_BuildValue ("N", r); +} + +PyObject * +rsaKey_size (rsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1); +} + +PyObject * +rsaKey_has_private (rsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + if (mpz_size (key->d) == 0) { + Py_INCREF(Py_False); + return Py_False; + } else { + Py_INCREF(Py_True); + return Py_True; + } +} + + +PyObject * +isPrime (PyObject * self, PyObject * args) +{ + PyObject *l; + mpz_t n; + int result; + + if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) + { + return NULL; + } + mpz_init (n); + longObjToMPZ (n, (PyLongObject *) l); + + result = mpz_probab_prime_p(n, 5); + + mpz_clear (n); + + if (result == 0) { + Py_INCREF(Py_False); + return Py_False; + } else { + Py_INCREF(Py_True); + return Py_True; + } +} + + +static PyMethodDef _fastmath__methods__[] = { + {"dsa_construct", dsaKey_new, METH_VARARGS}, + {"rsa_construct", rsaKey_new, METH_VARARGS}, + {"isPrime", isPrime, METH_VARARGS}, + {NULL, NULL} +}; + +void +init_fastmath (void) +{ + PyObject *_fastmath_module; + PyObject *_fastmath_dict; + + rsaKeyType.ob_type = &PyType_Type; + dsaKeyType.ob_type = &PyType_Type; + _fastmath_module = Py_InitModule ("_fastmath", _fastmath__methods__); + _fastmath_dict = PyModule_GetDict (_fastmath_module); + fastmathError = PyErr_NewException ("_fastmath.error", NULL, NULL); + PyDict_SetItemString (_fastmath_dict, "error", fastmathError); +} diff --git a/src/Crypto/src/_rsa.c b/src/Crypto/src/_rsa.c new file mode 100644 index 00000000..e51d1884 --- /dev/null +++ b/src/Crypto/src/_rsa.c @@ -0,0 +1,346 @@ + +/* + * _rsa.c: C implementation of the RSA algorithm. + * + * Part of the Python Cryptography Toolkit + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +#include +#include +#include +#include /* for conversions */ +#include + +PyObject *_rsa_module; +PyObject *_rsa_dict; + +void +longObjToMPZ (mpz_t m, PyLongObject * p) +{ + int size, i; + mpz_t temp, temp2; + mpz_init (temp); + mpz_init (temp2); + if (p->ob_size > 0) + size = p->ob_size; + else + size = -p->ob_size; + for (i = 0; i < size; i++) + { + mpz_set_ui (temp, p->ob_digit[i]); + mpz_mul_2exp (temp2, temp, SHIFT * i); + mpz_add (m, m, temp2); + } + mpz_clear (temp); + mpz_clear (temp2); +} + +PyObject * +mpzToLongObj (mpz_t m) +{ + /* borrowed from gmpy */ + int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT; + int i; + mpz_t temp; + PyLongObject *l = _PyLong_New (size); + if (!l) + return NULL; + mpz_init_set (temp, m); + for (i = 0; i < size; i++) + { + l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK); + mpz_fdiv_q_2exp (temp, temp, SHIFT); + } + i = size; + while ((i > 0) && (l->ob_digit[i - 1] == 0)) + i--; + l->ob_size = i; + mpz_clear (temp); + return (PyObject *) l; +} + +PyObject *rsaKey_new (PyObject *, PyObject *); + +static PyMethodDef _rsa__methods__[] = { + {"construct", rsaKey_new, METH_VARARGS}, + {NULL, NULL} +}; + +typedef struct +{ + PyObject_HEAD mpz_t n; + mpz_t e; + mpz_t d; + mpz_t p; + mpz_t q; +} +rsaKey; + +static int +rsaEncrypt (rsaKey * key, mpz_t v) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + mpz_powm (v, v, key->e, key->n); + return 0; +} + +static int +rsaDecrypt (rsaKey * key, mpz_t v) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + if (mpz_size (key->d) == 0) + { + return 2; + } + mpz_powm (v, v, key->d, key->n); + return 0; +} + +static void rsaKey_dealloc (rsaKey *); +static PyObject *rsaKey_getattr (rsaKey *, char *); +static PyObject *rsaKey__encrypt (rsaKey *, PyObject *); +static PyObject *rsaKey__decrypt (rsaKey *, PyObject *); +static PyObject *rsaKey__verify (rsaKey *, PyObject *); +static PyObject *rsaKey_size (rsaKey *, PyObject *); +static PyObject *rsaKey_hasprivate (rsaKey *, PyObject *); + +PyObject *rsaError; /* raised on errors */ + +static PyTypeObject rsaKeyType = { + PyObject_HEAD_INIT (NULL) 0, + "rsaKey", + sizeof (rsaKey), + 0, + (destructor) rsaKey_dealloc, /* dealloc */ + 0, /* print */ + (getattrfunc) rsaKey_getattr, /* getattr */ + 0, /* setattr */ + 0, /* compare */ + 0, /* repr */ + 0, /* as_number */ + 0, /* as_sequence */ + 0, /* as_mapping */ + 0, /* hash */ + 0, /* call */ +}; + +static PyMethodDef rsaKey__methods__[] = { + {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS, + "Encrypt the given long."}, + {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS, + "Decrypt the given long."}, + {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS, + "Sign the given long."}, + {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS, + "Verify that the signature is valid."}, + {"size", (PyCFunction) rsaKey_size, METH_VARARGS, + "Return the number of bits that this key can handle."}, + {"hasprivate", (PyCFunction) rsaKey_hasprivate, METH_VARARGS, + "Return 1 or 0 if this key does/doesn't have a private key."}, + {NULL, NULL, 0, NULL} +}; + +PyObject * +rsaKey_new (PyObject * self, PyObject * args) +{ + PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; + rsaKey *key; + key = PyObject_New (rsaKey, &rsaKeyType); + mpz_init (key->n); + mpz_init (key->e); + mpz_init (key->d); + mpz_init (key->p); + mpz_init (key->q); + PyArg_ParseTuple (args, "O!O!|O!O!O!", &PyLong_Type, &n, + &PyLong_Type, &e, + &PyLong_Type, &d, &PyLong_Type, &p, &PyLong_Type, &q); + longObjToMPZ (key->n, n); + longObjToMPZ (key->e, e); + if (!d) + { + return (PyObject *) key; + } + longObjToMPZ (key->d, d); + if (p) + { + if (q) + { + longObjToMPZ (key->p, p); + longObjToMPZ (key->q, q); + } + } + /*Py_XDECREF(n); + Py_XDECREF(e); + Py_XDECREF(d); + Py_XDECREF(p); + Py_XDECREF(q); */ + return (PyObject *) key; +} + +static void +rsaKey_dealloc (rsaKey * key) +{ + mpz_clear (key->n); + mpz_clear (key->e); + mpz_clear (key->d); + mpz_clear (key->p); + mpz_clear (key->q); + PyObject_Del (key); +} + +static PyObject * +rsaKey_getattr (rsaKey * key, char *attr) +{ + if (strcmp (attr, "n") == 0) + return mpzToLongObj (key->n); + else if (strcmp (attr, "e") == 0) + return mpzToLongObj (key->e); + else if (strcmp (attr, "d") == 0) + { + if (mpz_size (key->d) == 0) + { + PyErr_SetString (PyExc_AttributeError, + "rsaKey instance has no attribute 'd'"); + return NULL; + } + return mpzToLongObj (key->d); + } + else if (strcmp (attr, "p") == 0) + { + if (mpz_size (key->p) == 0) + { + PyErr_SetString (PyExc_AttributeError, + "rsaKey instance has no attribute 'p'"); + return NULL; + } + return mpzToLongObj (key->p); + } + else if (strcmp (attr, "q") == 0) + { + if (mpz_size (key->q) == 0) + { + PyErr_SetString (PyExc_AttributeError, + "rsaKey instance has no attribute 'q'"); + return NULL; + } + return mpzToLongObj (key->q); + } + else + { + return Py_FindMethod (rsaKey__methods__, (PyObject *) key, attr); + } +} + +PyObject * +rsaKey__encrypt (rsaKey * key, PyObject * args) +{ + PyObject *l, *r; + mpz_t v; + int result; + if (!(PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))) + { + return NULL; + } + mpz_init (v); + longObjToMPZ (v, (PyLongObject *) l); + result = rsaEncrypt (key, v); + if (result == 1) + { + PyErr_SetString (rsaError, "Plaintext too large"); + return NULL; + } + r = (PyObject *) mpzToLongObj (v); + mpz_clear (v); + return Py_BuildValue ("N", r); +} + +PyObject * +rsaKey__decrypt (rsaKey * key, PyObject * args) +{ + PyObject *l, *r; + mpz_t v; + int result; + if (!(PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))) + { + return NULL; + } + mpz_init (v); + longObjToMPZ (v, (PyLongObject *) l); + result = rsaDecrypt (key, v); + if (result == 1) + { + PyErr_SetString (rsaError, "Ciphertext too large"); + return NULL; + } + else if (result == 2) + { + PyErr_SetString (rsaError, "Private key not available in this object"); + return NULL; + } + r = mpzToLongObj (v); + mpz_clear (v); + return Py_BuildValue ("N", r); +} + +PyObject * +rsaKey__verify (rsaKey * key, PyObject * args) +{ + PyObject *l, *lsig; + mpz_t v, vsig; + if (! + (PyArg_ParseTuple + (args, "O!O!", &PyLong_Type, &l, &PyLong_Type, &lsig))) + { + return NULL; + } + mpz_init (v); + mpz_init (vsig); + longObjToMPZ (v, (PyLongObject *) l); + longObjToMPZ (vsig, (PyLongObject *) lsig); + rsaEncrypt (key, vsig); + if (mpz_cmp (v, vsig) == 0) + return Py_BuildValue ("i", 1); + else + return Py_BuildValue ("i", 0); +} + +PyObject * +rsaKey_size (rsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1); +} + +PyObject * +rsaKey_hasprivate (rsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + if (mpz_size (key->d) == 0) + return Py_BuildValue ("i", 0); + else + return Py_BuildValue ("i", 1); +} + + +void +init_rsa (void) +{ + rsaKeyType.ob_type = &PyType_Type; + _rsa_module = Py_InitModule ("_rsa", _rsa__methods__); + _rsa_dict = PyModule_GetDict (_rsa_module); + rsaError = PyErr_NewException ("_rsa.error", NULL, NULL); + PyDict_SetItemString (_rsa_dict, "error", rsaError); +} diff --git a/src/Crypto/src/block_template.c b/src/Crypto/src/block_template.c new file mode 100644 index 00000000..3c9f4e9f --- /dev/null +++ b/src/Crypto/src/block_template.c @@ -0,0 +1,750 @@ + +/* -*- C -*- */ +/* + * block_template.c : Generic framework for block encryption algorithms + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. This software is provided "as is" without + * warranty of fitness for use or suitability for any purpose, express + * or implied. Use at your own risk or not at all. + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef _HAVE_STDC_HEADERS +#include +#endif + +#include "Python.h" +#include "modsupport.h" + +/* Cipher operation modes */ + +#define MODE_ECB 1 +#define MODE_CBC 2 +#define MODE_CFB 3 +#define MODE_PGP 4 +#define MODE_OFB 5 +#define MODE_CTR 6 + +#define _STR(x) #x +#define _XSTR(x) _STR(x) +#define _PASTE(x,y) x##y +#define _PASTE2(x,y) _PASTE(x,y) +#define _MODULE_NAME _PASTE2(init,MODULE_NAME) +#define _MODULE_STRING _XSTR(MODULE_NAME) + +typedef struct +{ + PyObject_HEAD + int mode, count, segment_size; + unsigned char IV[BLOCK_SIZE], oldCipher[BLOCK_SIZE]; + unsigned char ctrval[BLOCK_SIZE]; /* carries counter value between block crypt calls */ + unsigned char ctroffset; /* carries offset into current block between block crypt calls */ + block_state st; +} ALGobject; + +staticforward PyTypeObject ALGtype; + +#define is_ALGobject(v) ((v)->ob_type == &ALGtype) + +static ALGobject * +newALGobject(void) +{ + ALGobject * new; + new = PyObject_New(ALGobject, &ALGtype); + new->mode = MODE_ECB; + memset(new->ctrval, 0, BLOCK_SIZE); + new->ctroffset = 0; + return new; +} + +static void +ALGdealloc(PyObject *ptr) +{ + ALGobject *self = (ALGobject *)ptr; + + /* Overwrite the contents of the object */ + memset(self->IV, 0, BLOCK_SIZE); + memset(self->oldCipher, 0, BLOCK_SIZE); + memset((char*)&(self->st), 0, sizeof(block_state)); + memset(self->ctrval, 0, BLOCK_SIZE); + self->ctroffset = 0; + self->mode = self->count = self->segment_size = 0; + PyObject_Del(ptr); +} + + +static char ALGnew__doc__[] = +"new(key, [mode], [IV]): Return a new " _MODULE_STRING " encryption object."; + +static char *kwlist[] = {"key", "mode", "IV", "counterstart", "segment_size", +#ifdef PCT_RC5_MODULE + "version", "word_size", "rounds", +#endif + NULL}; + +static ALGobject * +ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) +{ + unsigned char *key, *IV; + ALGobject * new=NULL; + int keylen, IVlen=0, mode=MODE_ECB, segment_size=0; + PyObject *counterstart = NULL; +#ifdef PCT_RC5_MODULE + int version = 0x10, word_size = 32, rounds = 16; /*XXX default rounds? */ +#endif + /* Set default values */ + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#|is#Oi" +#ifdef PCT_RC5_MODULE + "iii" +#endif + , kwlist, + &key, &keylen, &mode, &IV, &IVlen, + &counterstart, &segment_size +#ifdef PCT_RC5_MODULE + , &version, &word_size, &rounds +#endif + )) + { + return NULL; + } + + if (KEY_SIZE!=0 && keylen!=KEY_SIZE) + { + PyErr_Format(PyExc_ValueError, + "Key must be %i bytes long, not %i", + KEY_SIZE, keylen); + return NULL; + } + if (KEY_SIZE==0 && keylen==0) + { + PyErr_SetString(PyExc_ValueError, + "Key cannot be the null string"); + return NULL; + } + if (IVlen != BLOCK_SIZE && IVlen != 0) + { + PyErr_Format(PyExc_ValueError, + "IV must be %i bytes long", BLOCK_SIZE); + return NULL; + } + if (modeMODE_CTR) + { + PyErr_Format(PyExc_ValueError, + "Unknown cipher feedback mode %i", + mode); + return NULL; + } + + /* Mode-specific checks */ + if (mode == MODE_CFB) { + if (segment_size == 0) segment_size = 8; + if (segment_size < 1 || segment_size > BLOCK_SIZE*8) { + PyErr_Format(PyExc_ValueError, + "segment_size must be multiple of 8 " + "between 1 and %i", BLOCK_SIZE); + } + } + + if (mode == MODE_CTR) { + if ((counterstart == NULL) || (!PyString_Check(counterstart))) { + PyErr_SetString(PyExc_ValueError, + "'counterstart' parameter is required to be a string"); + return NULL; + } + if (PyString_Size(counterstart) != BLOCK_SIZE) { + PyErr_SetString(PyExc_ValueError, + "'counterstart' parameter is required to be of length block size"); + return NULL; + } + } else { + if (counterstart != NULL) { + PyErr_SetString(PyExc_ValueError, + "'counterstart' parameter only useful with CTR mode"); + return NULL; + } + } + + /* Cipher-specific checks */ +#ifdef PCT_RC5_MODULE + if (version!=0x10) { + PyErr_Format(PyExc_ValueError, + "RC5: Bad RC5 algorithm version: %i", + version); + return NULL; + } + if (word_size!=16 && word_size!=32) { + PyErr_Format(PyExc_ValueError, + "RC5: Unsupported word size: %i", + word_size); + return NULL; + } + if (rounds<0 || 255segment_size = segment_size; + if ((counterstart != NULL) && PyString_Check(counterstart)) + { + assert (PyString_Size(counterstart) == BLOCK_SIZE); + memcpy(new->ctrval, PyString_AsString(counterstart), PyString_Size(counterstart)); + } +#ifdef PCT_RC5_MODULE + new->st.version = version; + new->st.word_size = word_size; + new->st.rounds = rounds; +#endif + + block_init(&(new->st), key, keylen); + if (PyErr_Occurred()) + { + Py_DECREF(new); + return NULL; + } + memset(new->IV, 0, BLOCK_SIZE); + memset(new->oldCipher, 0, BLOCK_SIZE); + memcpy(new->IV, IV, IVlen); + new->mode = mode; + new->count=8; + return new; +} + +static char ALG_Encrypt__doc__[] = +"Encrypt the provided string of binary data."; + +/* + * Treat the data in buf as an big-endian unsigned integer and increment it + * mod 2^(bytes*8). + */ +void +increment_unsigned(unsigned char*buf, size_t bytes) +{ + unsigned char* p = buf + bytes - 1; + while (*p == 255) + { + *p += 1; + /* carry */ + if (p == buf) + return; + p--; + } + *p += 1; +} + +static void +ctr_crypt(ALGobject *const self, const unsigned char*const str, unsigned char*const buffer, const int len) +{ + int i = 0; /* always points to the next byte of str which is to be crypted */ + unsigned char temp[BLOCK_SIZE]; + + while (i < len) + { + /* This loop is per block. */ + block_encrypt(&(self->st), self->ctrval, temp); + + while (self->ctroffset < BLOCK_SIZE) + { + if (i == len) + return; /* finished */ + /* This loop is per byte. */ + buffer[i] = str[i]^temp[self->ctroffset]; + i++; self->ctroffset++; + } + + increment_unsigned(self->ctrval, BLOCK_SIZE); + self->ctroffset = 0; + } +} + +static PyObject * +ALG_Encrypt(ALGobject *self, PyObject *args) +{ + unsigned char *buffer, *str; + unsigned char temp[BLOCK_SIZE]; + int i, j, len; + PyObject *result; + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len==0) /* Handle empty string */ + { + return PyString_FromStringAndSize(NULL, 0); + } + if ( (len % BLOCK_SIZE) !=0 && + (self->mode!=MODE_CFB) && (self->mode!=MODE_PGP) && self->mode!=MODE_CTR) + { + PyErr_Format(PyExc_ValueError, + "Input strings must be " + "a multiple of %i in length", + BLOCK_SIZE); + return NULL; + } + if (self->mode == MODE_CFB && + (len % (self->segment_size/8) !=0)) { + PyErr_Format(PyExc_ValueError, + "Input strings must be a multiple of " + "the segment size %i in length", + self->segment_size/8); + return NULL; + } + + buffer=malloc(len); + if (buffer==NULL) + { + PyErr_SetString(PyExc_MemoryError, + "No memory available in " + _MODULE_STRING " encrypt"); + return NULL; + } + switch(self->mode) + { + case(MODE_ECB): + for(i=0; ist), str+i, buffer+i); + } + break; + + case(MODE_CBC): + for(i=0; iIV[j]; + } + block_encrypt(&(self->st), temp, buffer+i); + memcpy(self->IV, buffer+i, BLOCK_SIZE); + } + break; + + case(MODE_CFB): + for(i=0; isegment_size/8) + { + block_encrypt(&(self->st), self->IV, temp); + for (j=0; jsegment_size/8; j++) { + buffer[i+j] = str[i+j] ^ temp[j]; + } + if (self->segment_size == BLOCK_SIZE * 8) { + /* s == b: segment size is identical to + the algorithm block size */ + memcpy(self->IV, buffer + i, BLOCK_SIZE); + } + else if ((self->segment_size % 8) == 0) { + int sz = self->segment_size/8; + memmove(self->IV, self->IV + sz, + BLOCK_SIZE-sz); + memcpy(self->IV + BLOCK_SIZE - sz, buffer + i, + sz); + } + else { + /* segment_size is not a multiple of 8; + currently this can't happen */ + } + } + break; + + case(MODE_PGP): + if (len<=BLOCK_SIZE-self->count) + { + /* If less than one block, XOR it in */ + for(i=0; iIV[self->count+i] ^= str[i]; + self->count += len; + } + else + { + int j; + for(i=0; icount; i++) + buffer[i] = self->IV[self->count+i] ^= str[i]; + self->count=0; + for(; ist), self->oldCipher, + self->IV); + for(j=0; jIV[j] ^= str[i+j]; + } + /* Do the remaining 1 to BLOCK_SIZE bytes */ + block_encrypt(&(self->st), self->oldCipher, self->IV); + self->count=len-i; + for(j=0; jIV[j] ^= str[i+j]; + } + } + break; + + case(MODE_OFB): + for(i=0; ist), self->IV, temp); + memcpy(self->IV, temp, BLOCK_SIZE); + for(j=0; jmode); + free(buffer); + return NULL; + } + result=PyString_FromStringAndSize(buffer, len); + free(buffer); + return(result); +} + +static char ALG_Decrypt__doc__[] = +"decrypt(string): Decrypt the provided string of binary data."; + + +static PyObject * +ALG_Decrypt(ALGobject *self, PyObject *args) +{ + unsigned char *buffer, *str; + unsigned char temp[BLOCK_SIZE]; + int i, j, len; + PyObject *result; + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len==0) /* Handle empty string */ + { + return PyString_FromStringAndSize(NULL, 0); + } + if ( (len % BLOCK_SIZE) !=0 && + (self->mode!=MODE_CFB && self->mode!=MODE_PGP && self->mode!=MODE_CTR)) + { + PyErr_Format(PyExc_ValueError, + "Input strings must be " + "a multiple of %i in length", + BLOCK_SIZE); + return NULL; + } + if (self->mode == MODE_CFB && + (len % (self->segment_size/8) !=0)) { + PyErr_Format(PyExc_ValueError, + "Input strings must be a multiple of " + "the segment size %i in length", + self->segment_size/8); + return NULL; + } + buffer=malloc(len); + if (buffer==NULL) + { + PyErr_SetString(PyExc_MemoryError, + "No memory available in " _MODULE_STRING + " decrypt"); + return NULL; + } + switch(self->mode) + { + case(MODE_ECB): + for(i=0; ist), str+i, buffer+i); + } + break; + + case(MODE_CBC): + for(i=0; ioldCipher, self->IV, BLOCK_SIZE); + block_decrypt(&(self->st), str+i, temp); + for(j=0; jIV[j]; + self->IV[j]=str[i+j]; + } + } + break; + + case(MODE_CFB): + for(i=0; isegment_size/8) + { + block_encrypt(&(self->st), self->IV, temp); + for (j=0; jsegment_size/8; j++) { + buffer[i+j] = str[i+j]^temp[j]; + } + if (self->segment_size == BLOCK_SIZE * 8) { + /* s == b: segment size is identical to + the algorithm block size */ + memcpy(self->IV, str + i, BLOCK_SIZE); + } + else if ((self->segment_size % 8) == 0) { + int sz = self->segment_size/8; + memmove(self->IV, self->IV + sz, + BLOCK_SIZE-sz); + memcpy(self->IV + BLOCK_SIZE - sz, str + i, + sz); + } + else { + /* segment_size is not a multiple of 8; + currently this can't happen */ + } + } + break; + + case(MODE_PGP): + if (len<=BLOCK_SIZE-self->count) + { + /* If less than one block, XOR it in */ + unsigned char t; + for(i=0; iIV[self->count+i]; + buffer[i] = t ^ (self->IV[self->count+i] = str[i]); + } + self->count += len; + } + else + { + int j; + unsigned char t; + for(i=0; icount; i++) + { + t=self->IV[self->count+i]; + buffer[i] = t ^ (self->IV[self->count+i] = str[i]); + } + self->count=0; + for(; ist), self->oldCipher, self->IV); + for(j=0; jIV[j]; + buffer[i+j] = t ^ (self->IV[j] = str[i+j]); + } + } + /* Do the remaining 1 to BLOCK_SIZE bytes */ + block_encrypt(&(self->st), self->oldCipher, self->IV); + self->count=len-i; + for(j=0; jIV[j]; + buffer[i+j] = t ^ (self->IV[j] = str[i+j]); + } + } + break; + + case (MODE_OFB): + for(i=0; ist), self->IV, temp); + memcpy(self->IV, temp, BLOCK_SIZE); + for(j=0; jIV[j]; + } + } + break; + + case (MODE_CTR): + ctr_crypt(self, str, buffer, len); + break; + + default: + PyErr_Format(PyExc_SystemError, + "Unknown ciphertext feedback mode %i; " + "this shouldn't happen", + self->mode); + free(buffer); + return NULL; + } + result=PyString_FromStringAndSize(buffer, len); + free(buffer); + return(result); +} + +static char ALG_Sync__doc__[] = +"sync(): For objects using the PGP feedback mode, this method modifies " +"the IV, synchronizing it with the preceding ciphertext."; + +static PyObject * +ALG_Sync(ALGobject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) { + return NULL; + } + + if (self->mode!=MODE_PGP) + { + PyErr_SetString(PyExc_SystemError, "sync() operation not defined for " + "this feedback mode"); + return NULL; + } + + if (self->count!=8) + { + memmove(self->IV+BLOCK_SIZE-self->count, self->IV, + self->count); + memcpy(self->IV, self->oldCipher+self->count, + BLOCK_SIZE-self->count); + self->count=8; + } + Py_INCREF(Py_None); + return Py_None; +} + +#if 0 +void PrintState(self, msg) + ALGobject *self; + char * msg; +{ + int count; + + printf("%sing: %i IV ", msg, (int)self->count); + for(count=0; count<8; count++) printf("%i ", self->IV[count]); + printf("\noldCipher:"); + for(count=0; count<8; count++) printf("%i ", self->oldCipher[count]); + printf("\n"); +} +#endif + + +/* ALG object methods */ + +static PyMethodDef ALGmethods[] = +{ + {"encrypt", (PyCFunction) ALG_Encrypt, 0, ALG_Encrypt__doc__}, + {"decrypt", (PyCFunction) ALG_Decrypt, 0, ALG_Decrypt__doc__}, + {"sync", (PyCFunction) ALG_Sync, METH_VARARGS, ALG_Sync__doc__}, + {NULL, NULL} /* sentinel */ +}; + + +static int +ALGsetattr(PyObject *ptr, char *name, PyObject *v) +{ + ALGobject *self=(ALGobject *)ptr; + if (strcmp(name, "IV") != 0) + { + PyErr_Format(PyExc_AttributeError, + "non-existent block cipher object attribute '%s'", + name); + return -1; + } + if (v==NULL) + { + PyErr_SetString(PyExc_AttributeError, + "Can't delete IV attribute of block cipher object"); + return -1; + } + if (!PyString_Check(v)) + { + PyErr_SetString(PyExc_TypeError, + "IV attribute of block cipher object must be string"); + return -1; + } + if (PyString_Size(v)!=BLOCK_SIZE) + { + PyErr_Format(PyExc_ValueError, + _MODULE_STRING " IV must be %i bytes long", + BLOCK_SIZE); + return -1; + } + memcpy(self->IV, PyString_AsString(v), BLOCK_SIZE); + return 0; +} + +static PyObject * +ALGgetattr(PyObject *s, char *name) +{ + ALGobject *self = (ALGobject*)s; + if (strcmp(name, "IV") == 0) + { + return(PyString_FromStringAndSize(self->IV, BLOCK_SIZE)); + } + if (strcmp(name, "mode") == 0) + { + return(PyInt_FromLong((long)(self->mode))); + } + if (strcmp(name, "block_size") == 0) + { + return PyInt_FromLong(BLOCK_SIZE); + } + if (strcmp(name, "key_size") == 0) + { + return PyInt_FromLong(KEY_SIZE); + } + return Py_FindMethod(ALGmethods, (PyObject *) self, name); +} + +/* List of functions defined in the module */ + +static struct PyMethodDef modulemethods[] = +{ + {"new", (PyCFunction) ALGnew, METH_VARARGS|METH_KEYWORDS, ALGnew__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject ALGtype = +{ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + _MODULE_STRING, /*tp_name*/ + sizeof(ALGobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + ALGdealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + ALGgetattr, /*tp_getattr*/ + ALGsetattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) 0, /*tp_repr*/ + 0, /*tp_as_number*/ +}; + +/* Initialization function for the module */ + +#if PYTHON_API_VERSION < 1011 +#define PyModule_AddIntConstant(m,n,v) {PyObject *o=PyInt_FromLong(v); \ + if (o!=NULL) \ + {PyDict_SetItemString(PyModule_GetDict(m),n,o); Py_DECREF(o);}} +#endif + +void +_MODULE_NAME (void) +{ + PyObject *m; + + ALGtype.ob_type = &PyType_Type; + + /* Create the module and add the functions */ + m = Py_InitModule("allmydata.Crypto.Cipher." _MODULE_STRING, modulemethods); + + PyModule_AddIntConstant(m, "MODE_ECB", MODE_ECB); + PyModule_AddIntConstant(m, "MODE_CBC", MODE_CBC); + PyModule_AddIntConstant(m, "MODE_CFB", MODE_CFB); + PyModule_AddIntConstant(m, "MODE_PGP", MODE_PGP); + PyModule_AddIntConstant(m, "MODE_OFB", MODE_OFB); + PyModule_AddIntConstant(m, "MODE_CTR", MODE_CTR); + PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); + PyModule_AddIntConstant(m, "key_size", KEY_SIZE); + + /* Check for errors */ + if (PyErr_Occurred()) + Py_FatalError("can't initialize module " _MODULE_STRING); +} + diff --git a/src/Crypto/src/cast5.c b/src/Crypto/src/cast5.c new file mode 100644 index 00000000..0843b98d --- /dev/null +++ b/src/Crypto/src/cast5.c @@ -0,0 +1,437 @@ +/* + These are the S-boxes for CAST5 as given in RFC 2144. +*/ + + +static const uint32 S1[256] = { +0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, +0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, +0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, +0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, +0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, +0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, +0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, +0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, +0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, +0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, +0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, +0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, +0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, +0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, +0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, +0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, +0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, +0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, +0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, +0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, +0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, +0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, +0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, +0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, +0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, +0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, +0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, +0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, +0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, +0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, +0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, +0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, +0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, +0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, +0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, +0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, +0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, +0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, +0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, +0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, +0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, +0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, +0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, +0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, +0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, +0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, +0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, +0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, +0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, +0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, +0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, +0x5c8165bf }; + +static const uint32 S2[256] = { +0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, +0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, +0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, +0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, +0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, +0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, +0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, +0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, +0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, +0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, +0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, +0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, +0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, +0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, +0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, +0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, +0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, +0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, +0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, +0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, +0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, +0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, +0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, +0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, +0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, +0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, +0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, +0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, +0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, +0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, +0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, +0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, +0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, +0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, +0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, +0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, +0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, +0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, +0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, +0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, +0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, +0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, +0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, +0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, +0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, +0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, +0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, +0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, +0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, +0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, +0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, +0x4523ecf1 }; + +static const uint32 S3[256] = { +0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, +0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, +0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, +0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, +0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, +0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, +0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, +0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, +0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, +0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, +0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, +0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, +0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, +0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, +0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, +0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, +0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, +0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, +0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, +0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, +0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, +0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, +0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, +0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, +0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, +0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, +0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, +0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, +0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, +0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, +0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, +0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, +0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, +0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, +0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, +0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, +0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, +0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, +0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, +0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, +0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, +0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, +0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, +0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, +0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, +0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, +0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, +0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, +0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, +0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, +0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, +0xee353783 }; + +static const uint32 S4[256] = { +0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, +0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, +0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, +0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, +0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, +0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, +0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, +0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, +0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, +0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, +0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, +0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, +0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, +0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, +0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, +0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, +0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, +0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, +0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, +0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, +0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, +0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, +0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, +0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, +0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, +0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, +0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, +0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, +0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, +0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, +0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, +0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, +0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, +0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, +0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, +0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, +0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, +0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, +0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, +0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, +0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, +0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, +0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, +0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, +0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, +0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, +0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, +0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, +0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, +0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, +0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, +0x0aef7ed2 }; + +static const uint32 S5[256] = { +0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, +0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, +0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, +0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, +0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, +0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, +0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, +0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, +0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, +0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, +0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, +0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, +0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, +0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, +0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, +0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, +0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, +0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, +0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, +0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, +0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, +0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, +0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, +0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, +0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, +0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, +0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, +0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, +0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, +0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, +0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, +0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, +0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, +0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, +0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, +0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, +0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, +0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, +0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, +0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, +0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, +0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, +0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, +0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, +0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, +0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, +0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, +0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, +0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, +0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, +0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, +0xefe9e7d4 }; + +static const uint32 S6[256] = { +0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, +0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, +0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, +0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, +0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, +0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, +0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, +0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, +0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, +0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, +0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, +0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, +0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, +0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, +0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, +0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, +0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, +0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, +0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, +0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, +0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, +0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, +0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, +0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, +0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, +0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, +0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, +0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, +0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, +0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, +0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, +0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, +0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, +0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, +0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, +0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, +0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, +0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, +0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, +0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, +0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, +0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, +0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, +0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, +0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, +0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, +0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, +0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, +0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, +0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, +0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, +0xd675cf2f }; + +static const uint32 S7[256] = { +0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, +0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, +0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, +0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, +0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, +0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, +0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, +0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, +0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, +0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, +0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, +0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, +0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, +0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, +0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, +0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, +0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, +0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, +0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, +0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, +0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, +0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, +0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, +0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, +0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, +0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, +0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, +0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, +0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, +0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, +0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, +0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, +0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, +0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, +0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, +0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, +0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, +0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, +0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, +0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, +0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, +0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, +0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, +0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, +0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, +0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, +0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, +0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, +0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, +0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, +0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, +0x954b8aa3 }; + +static const uint32 S8[256] = { +0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, +0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, +0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, +0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, +0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, +0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, +0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, +0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, +0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, +0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, +0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, +0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, +0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, +0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, +0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, +0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, +0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, +0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, +0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, +0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, +0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, +0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, +0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, +0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, +0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, +0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, +0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, +0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, +0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, +0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, +0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, +0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, +0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, +0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, +0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, +0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, +0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, +0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, +0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, +0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, +0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, +0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, +0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, +0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, +0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, +0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, +0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, +0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, +0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, +0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, +0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, +0xea8bf59e }; + diff --git a/src/Crypto/src/hash_template.c b/src/Crypto/src/hash_template.c new file mode 100644 index 00000000..2325b0fb --- /dev/null +++ b/src/Crypto/src/hash_template.c @@ -0,0 +1,248 @@ +/* + * hash_template.c : Generic framework for hash function extension modules + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. This software is provided "as is" without + * warranty of fitness for use or suitability for any purpose, express + * or implied. Use at your own risk or not at all. + * + */ + +/* Basic object type */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef _HAVE_STDC_HEADERS +#include +#endif + +#define _STR(x) #x +#define _XSTR(x) _STR(x) +#define _PASTE(x,y) x##y +#define _PASTE2(x,y) _PASTE(x,y) +#define _MODULE_NAME _PASTE2(init,MODULE_NAME) +#define _MODULE_STRING _XSTR(MODULE_NAME) + +typedef struct { + PyObject_HEAD + hash_state st; +} ALGobject; + +staticforward PyTypeObject ALGtype; + +#define is_ALGobject(v) ((v)->ob_type == &ALGtype) + +static ALGobject * +newALGobject(void) +{ + ALGobject *new; + + new = PyObject_New(ALGobject, &ALGtype); + return new; +} + +/* Internal methods for a hashing object */ + +static void +ALG_dealloc(PyObject *ptr) +{ + ALGobject *self = (ALGobject *)ptr; + + /* Overwrite the contents of the object */ + memset((char*)&(self->st), 0, sizeof(hash_state)); + PyObject_Del(ptr); +} + + +/* External methods for a hashing object */ + +static char ALG_copy__doc__[] = +"copy(): Return a copy of the hashing object."; + +static PyObject * +ALG_copy(ALGobject *self, PyObject *args) +{ + ALGobject *newobj; + + if (!PyArg_ParseTuple(args, "")) { + return NULL; + } + + if ( (newobj = newALGobject())==NULL) + return NULL; + + hash_copy(&(self->st), &(newobj->st)); + return((PyObject *)newobj); +} + +static char ALG_digest__doc__[] = +"digest(): Return the digest value as a string of binary data."; + +static PyObject * +ALG_digest(ALGobject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + return (PyObject *)hash_digest(&(self->st)); +} + +static char ALG_hexdigest__doc__[] = +"hexdigest(): Return the digest value as a string of hexadecimal digits."; + +static PyObject * +ALG_hexdigest(ALGobject *self, PyObject *args) +{ + PyObject *value, *retval; + unsigned char *raw_digest, *hex_digest; + int i, j, size; + + if (!PyArg_ParseTuple(args, "")) + return NULL; + + /* Get the raw (binary) digest value */ + value = (PyObject *)hash_digest(&(self->st)); + size = PyString_Size(value); + raw_digest = PyString_AsString(value); + + /* Create a new string */ + retval = PyString_FromStringAndSize(NULL, size * 2 ); + hex_digest = PyString_AsString(retval); + + /* Make hex version of the digest */ + for(i=j=0; i9) ? c+'a'-10 : c + '0'; + hex_digest[j++] = c; + c = raw_digest[i] % 16; c = (c>9) ? c+'a'-10 : c + '0'; + hex_digest[j++] = c; + } + Py_DECREF(value); + return retval; +} + +static char ALG_update__doc__[] = +"update(string): Update this hashing object's state with the provided string."; + +static PyObject * +ALG_update(ALGobject *self, PyObject *args) +{ + unsigned char *cp; + int len; + + if (!PyArg_ParseTuple(args, "s#", &cp, &len)) + return NULL; + + hash_update(&(self->st), cp, len); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef ALG_methods[] = { + {"copy", (PyCFunction)ALG_copy, METH_VARARGS, ALG_copy__doc__}, + {"digest", (PyCFunction)ALG_digest, METH_VARARGS, ALG_digest__doc__}, + {"hexdigest", (PyCFunction)ALG_hexdigest, METH_VARARGS, + ALG_hexdigest__doc__}, + {"update", (PyCFunction)ALG_update, METH_VARARGS, ALG_update__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static PyObject * +ALG_getattr(PyObject *self, char *name) +{ + if (strcmp(name, "digest_size")==0) + return PyInt_FromLong(DIGEST_SIZE); + + return Py_FindMethod(ALG_methods, self, name); +} + +static PyTypeObject ALGtype = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + _MODULE_STRING, /*tp_name*/ + sizeof(ALGobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + ALG_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + ALG_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ +}; + + +/* The single module-level function: new() */ + +static char ALG_new__doc__[] = +"new([string]): Return a new " _MODULE_STRING +" hashing object. An optional string " +"argument may be provided; if present, this string will be " +"automatically hashed into the initial state of the object."; + +static PyObject * +ALG_new(PyObject *self, PyObject *args) +{ + ALGobject *new; + unsigned char *cp = NULL; + int len; + + if ((new = newALGobject()) == NULL) + return NULL; + + if (!PyArg_ParseTuple(args, "|s#", + &cp, &len)) { + Py_DECREF(new); + return NULL; + } + + hash_init(&(new->st)); + + if (PyErr_Occurred()) { + Py_DECREF(new); + return NULL; + } + if (cp) + hash_update(&(new->st), cp, len); + + return (PyObject *)new; +} + + +/* List of functions exported by this module */ + +static struct PyMethodDef ALG_functions[] = { + {"new", (PyCFunction)ALG_new, METH_VARARGS, ALG_new__doc__}, + {NULL, NULL} /* Sentinel */ +}; + + +/* Initialize this module. */ + +#if PYTHON_API_VERSION < 1011 +#define PyModule_AddIntConstant(m,n,v) {PyObject *o=PyInt_FromLong(v); \ + if (o!=NULL) \ + {PyDict_SetItemString(PyModule_GetDict(m),n,o); Py_DECREF(o);}} +#endif + +void +_MODULE_NAME (void) +{ + PyObject *m; + + ALGtype.ob_type = &PyType_Type; + m = Py_InitModule("allmydata.Crypto.Hash." _MODULE_STRING, ALG_functions); + + /* Add some symbolic constants to the module */ + PyModule_AddIntConstant(m, "digest_size", DIGEST_SIZE); + + /* Check for errors */ + if (PyErr_Occurred()) + Py_FatalError("can't initialize module " + _MODULE_STRING); +} diff --git a/src/Crypto/src/stream_template.c b/src/Crypto/src/stream_template.c new file mode 100644 index 00000000..c3b32ecb --- /dev/null +++ b/src/Crypto/src/stream_template.c @@ -0,0 +1,248 @@ +/* -*- C -*- */ + +/* + * stream_template.c : Generic framework for stream ciphers + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. This software is provided "as is" without + * warranty of fitness for use or suitability for any purpose, express + * or implied. Use at your own risk or not at all. + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef _HAVE_STDC_HEADERS +#include +#endif + +#include "Python.h" +#include "modsupport.h" + +#define _STR(x) #x +#define _XSTR(x) _STR(x) +#define _PASTE(x,y) x##y +#define _PASTE2(x,y) _PASTE(x,y) +#define _MODULE_NAME _PASTE2(init,MODULE_NAME) +#define _MODULE_STRING _XSTR(MODULE_NAME) + + /* + * + * Python interface + * + */ + +typedef struct +{ + PyObject_HEAD + stream_state st; +} ALGobject; + +staticforward PyTypeObject ALGtype; + +#define is_ALGobject(v) ((v)->ob_type == &ALGtype) + +static ALGobject * +newALGobject(void) +{ + ALGobject * new; + new = PyObject_New(ALGobject, &ALGtype); + return new; +} + +static void +ALGdealloc(PyObject *ptr) +{ + ALGobject *self = (ALGobject *)ptr; + + /* Overwrite the contents of the object */ + memset((char*)&(self->st), 0, sizeof(stream_state)); + PyObject_Del(ptr); +} + +static char ALGnew__doc__[] = +"Return a new " _MODULE_STRING " encryption object."; + +static char *kwlist[] = {"key", NULL}; + +static ALGobject * +ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) +{ + unsigned char *key; + ALGobject * new; + int keylen; + + new = newALGobject(); + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#", kwlist, + &key, &keylen)) + { + Py_DECREF(new); + return NULL; + } + + if (KEY_SIZE!=0 && keylen != KEY_SIZE) + { + PyErr_SetString(PyExc_ValueError, + _MODULE_STRING " key must be " + "KEY_SIZE bytes long"); + return NULL; + } + if (KEY_SIZE== 0 && keylen == 0) + { + PyErr_SetString(PyExc_ValueError, + _MODULE_STRING " key cannot be " + "the null string (0 bytes long)"); + return NULL; + } + stream_init(&(new->st), key, keylen); + if (PyErr_Occurred()) + { + Py_DECREF(new); + return NULL; + } + return new; +} + +static char ALG_Encrypt__doc__[] = +"Decrypt the provided string of binary data."; + +static PyObject * +ALG_Encrypt(ALGobject *self, PyObject *args) +{ + unsigned char *buffer, *str; + int len; + PyObject *result; + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len == 0) /* Handle empty string */ + { + return PyString_FromStringAndSize(NULL, 0); + } + buffer = malloc(len); + if (buffer == NULL) + { + PyErr_SetString(PyExc_MemoryError, "No memory available in " + _MODULE_STRING " encrypt"); + return NULL; + } + memcpy(buffer, str, len); + stream_encrypt(&(self->st), buffer, len); + result = PyString_FromStringAndSize(buffer, len); + free(buffer); + return (result); +} + +static char ALG_Decrypt__doc__[] = +"decrypt(string): Decrypt the provided string of binary data."; + +static PyObject * +ALG_Decrypt(ALGobject *self, PyObject *args) +{ + char *buffer, *str; + int len; + PyObject *result; + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len == 0) /* Handle empty string */ + { + return PyString_FromStringAndSize(NULL, 0); + } + buffer = malloc(len); + if (buffer == NULL) + { + PyErr_SetString(PyExc_MemoryError, "No memory available in " + _MODULE_STRING " decrypt"); + return NULL; + } + memcpy(buffer, str, len); + stream_decrypt(&(self->st), buffer, len); + result = PyString_FromStringAndSize(buffer, len); + free(buffer); + return (result); +} + +/* ALGobject methods */ + +static PyMethodDef ALGmethods[] = +{ + {"encrypt", (PyCFunction) ALG_Encrypt, 0, ALG_Encrypt__doc__}, + {"decrypt", (PyCFunction) ALG_Decrypt, 0, ALG_Decrypt__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static PyObject * +ALGgetattr(PyObject *self, char *name) +{ + if (strcmp(name, "block_size") == 0) + { + return PyInt_FromLong(BLOCK_SIZE); + } + if (strcmp(name, "key_size") == 0) + { + return PyInt_FromLong(KEY_SIZE); + } + return Py_FindMethod(ALGmethods, self, name); +} + + +/* List of functions defined in the module */ + +static struct PyMethodDef modulemethods[] = +{ + {"new", (PyCFunction) ALGnew, + METH_VARARGS|METH_KEYWORDS, ALGnew__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject ALGtype = +{ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + _MODULE_STRING, /*tp_name*/ + sizeof(ALGobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + ALGdealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + ALGgetattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ +}; + +/* Initialization function for the module */ + +#if PYTHON_API_VERSION < 1011 +#define PyModule_AddIntConstant(m,n,v) {PyObject *o=PyInt_FromLong(v); \ + if (o!=NULL) \ + {PyDict_SetItemString(PyModule_GetDict(m),n,o); Py_DECREF(o);}} +#endif + +void +_MODULE_NAME (void) +{ + PyObject *m, *d, *x; + + ALGtype.ob_type = &PyType_Type; + /* Create the module and add the functions */ + m = Py_InitModule("allmydata.Crypto.Cipher." _MODULE_STRING, modulemethods); + + /* Add some symbolic constants to the module */ + d = PyModule_GetDict(m); + x = PyString_FromString(_MODULE_STRING ".error"); + PyDict_SetItemString(d, "error", x); + + PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); + PyModule_AddIntConstant(m, "key_size", KEY_SIZE); + + /* Check for errors */ + if (PyErr_Occurred()) + Py_FatalError("can't initialize module " _MODULE_STRING); +} diff --git a/src/Crypto/src/winrand.c b/src/Crypto/src/winrand.c new file mode 100644 index 00000000..8c82bd45 --- /dev/null +++ b/src/Crypto/src/winrand.c @@ -0,0 +1,366 @@ +/* -*- C -*- */ +/* + * Uses Windows CryptoAPI CryptGenRandom to get random bytes. + * The "new" method returns an object, whose "get_bytes" method + * can be called repeatedly to get random bytes, seeded by the + * OS. See the description in the comment at the end. + * + * If you have the Intel Security Driver header files (icsp4ms.h) + * for their hardware random number generator in the 810 and 820 chipsets, + * then define HAVE_INTEL_RNG. + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. This software is provided "as is" without + * warranty of fitness for use or suitability for any purpose, express + * or implied. Use at your own risk or not at all. + * + */ + +/* Author: Mark Moraes */ + +#include "Python.h" + +#ifdef MS_WIN32 + +#define _WIN32_WINNT 0x400 +#define WINSOCK + +#include +#include + +#ifdef HAVE_INTEL_RNG +# include "icsp4ms.h" +#else +# define PROV_INTEL_SEC 22 +# define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider" +#endif + +/* To-Do: store provider name and type for print/repr? */ +typedef struct +{ + PyObject_HEAD + HCRYPTPROV hcp; +} WRobject; + +staticforward PyTypeObject WRtype; + +#define is_WRobject(v) ((v)->ob_type == &WRtype) + +static void +WRdealloc(PyObject *ptr) +{ + WRobject *o = (WRobject *)ptr; + + if (! is_WRobject(ptr)) { + PyErr_Format(PyExc_TypeError, + "WinRandom trying to dealloc non-WinRandom object"); + return; + } + if (! CryptReleaseContext(o->hcp, 0)) { + PyErr_Format(PyExc_SystemError, + "CryptReleaseContext failed, error 0x%x", + GetLastError()); + return; + } + /* Overwrite the contents of the object */ + o->hcp = 0; + PyObject_Del(ptr); +} + +static char winrandom__doc__[] = +"new([provider], [provtype]): Returns an object handle to Windows\n\ +CryptoAPI that can be used to access a cryptographically strong\n\ +pseudo-random generator that uses OS-gathered entropy.\n\ +Provider is a string that specifies the Cryptographic Service Provider\n\ +to use, default is the default OS CSP.\n\ +provtype is an integer specifying the provider type to use, default\n\ +is 1 (PROV_RSA_FULL)"; + +static char WR_get_bytes__doc__[] = +"get_bytes(nbytes, [userdata]]): Returns nbytes of random data\n\ +from Windows CryptGenRandom.\n\ +userdata is a string with any additional entropic data that the\n\ +user wishes to provide."; + +static WRobject * +winrandom_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + HCRYPTPROV hcp = 0; + WRobject *res; + char *provname = NULL; + int provtype = PROV_RSA_FULL; + static char *kwlist[] = { "provider", "provtype", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|si", kwlist, + &provname, &provtype)) { + return NULL; + } + if (! CryptAcquireContext(&hcp, NULL, (LPCTSTR) provname, + (DWORD) provtype, 0)) { + PyErr_Format(PyExc_SystemError, + "CryptAcquireContext for provider \"%s\" type %i failed, error 0x%x", + provname? provname : "(null)", provtype, + GetLastError()); + return NULL; + } + res = PyObject_New(WRobject, &WRtype); + res->hcp = hcp; + return res; +} + +static PyObject * +WR_get_bytes(WRobject *self, PyObject *args) +{ + HCRYPTPROV hcp = 0; + int n, nbytes, len = 0; + PyObject *res; + char *buf, *str = NULL; + + if (! is_WRobject(self)) { + PyErr_Format(PyExc_TypeError, + "WinRandom trying to get_bytes with non-WinRandom object"); + return NULL; + } + if (!PyArg_ParseTuple(args, "i|s#", &n, &str, &len)) { + return NULL; + } + if (n <= 0) { + PyErr_SetString(PyExc_ValueError, "nbytes must be positive number"); + return NULL; + } + /* Just in case char != BYTE, or userdata > desired result */ + nbytes = (((n > len) ? n : len) * sizeof(char)) / sizeof(BYTE) + 1; + if ((buf = (char *) PyMem_Malloc(nbytes)) == NULL) + return PyErr_NoMemory(); + if (len > 0) + memcpy(buf, str, len); + /* + * if userdata > desired result, we end up getting + * more bytes than we really needed to return. No + * easy way to avoid that: we prefer that + * CryptGenRandom does the distillation of userdata + * down to entropy, rather than trying to do it + * ourselves. Since the extra bytes presumably come + * from an RC4 stream, they should be relatively + * cheap. + */ + if (! CryptGenRandom(self->hcp, (DWORD) nbytes, (BYTE *) buf)) { + PyErr_Format(PyExc_SystemError, + "CryptGenRandom failed, error 0x%x", + GetLastError()); + PyMem_Free(buf); + return NULL; + } + res = PyString_FromStringAndSize(buf, n); + PyMem_Free(buf); + return res; +} + +/* WinRandom object methods */ + +static PyMethodDef WRmethods[] = +{ + {"get_bytes", (PyCFunction) WR_get_bytes, METH_VARARGS, + WR_get_bytes__doc__}, + {NULL, NULL} /* sentinel */ +}; + +/* winrandom module methods */ + +static PyMethodDef WR_mod_methods[] = { + {"new", (PyCFunction) winrandom_new, METH_VARARGS|METH_KEYWORDS, + winrandom__doc__}, + {NULL, NULL} /* Sentinel */ +}; + + +static PyObject * +WRgetattr(PyObject *s, char *name) +{ + WRobject *self = (WRobject*)s; + if (! is_WRobject(self)) { + PyErr_Format(PyExc_TypeError, + "WinRandom trying to getattr with non-WinRandom object"); + return NULL; + } + if (strcmp(name, "hcp") == 0) + return PyInt_FromLong((long) self->hcp); + return Py_FindMethod(WRmethods, (PyObject *) self, name); +} + +static PyTypeObject WRtype = +{ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "winrandom.WinRandom", /*tp_name*/ + sizeof(WRobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + WRdealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + WRgetattr, /*tp_getattr*/ +}; + +void +initwinrandom() +{ + PyObject *m; + WRtype.ob_type = &PyType_Type; + m = Py_InitModule("winrandom", WR_mod_methods); + + /* define Windows CSP Provider Types */ +#ifdef PROV_RSA_FULL + PyModule_AddIntConstant(m, "PROV_RSA_FULL", PROV_RSA_FULL); +#endif +#ifdef PROV_RSA_SIG + PyModule_AddIntConstant(m, "PROV_RSA_SIG", PROV_RSA_SIG); +#endif +#ifdef PROV_DSS + PyModule_AddIntConstant(m, "PROV_DSS", PROV_DSS); +#endif +#ifdef PROV_FORTEZZA + PyModule_AddIntConstant(m, "PROV_FORTEZZA", PROV_FORTEZZA); +#endif +#ifdef PROV_MS_EXCHANGE + PyModule_AddIntConstant(m, "PROV_MS_EXCHANGE", PROV_MS_EXCHANGE); +#endif +#ifdef PROV_SSL + PyModule_AddIntConstant(m, "PROV_SSL", PROV_SSL); +#endif +#ifdef PROV_RSA_SCHANNEL + PyModule_AddIntConstant(m, "PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL); +#endif +#ifdef PROV_DSS_DH + PyModule_AddIntConstant(m, "PROV_DSS_DH", PROV_DSS_DH); +#endif +#ifdef PROV_EC_ECDSA_SIG + PyModule_AddIntConstant(m, "PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG); +#endif +#ifdef PROV_EC_ECNRA_SIG + PyModule_AddIntConstant(m, "PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG); +#endif +#ifdef PROV_EC_ECDSA_FULL + PyModule_AddIntConstant(m, "PROV_EC_ECDSA_FULL", PROV_EC_ECDSA_FULL); +#endif +#ifdef PROV_EC_ECNRA_FULL + PyModule_AddIntConstant(m, "PROV_EC_ECNRA_FULL", PROV_EC_ECNRA_FULL); +#endif +#ifdef PROV_SPYRUS_LYNKS + PyModule_AddIntConstant(m, "PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS); +#endif +#ifdef PROV_INTEL_SEC + PyModule_AddIntConstant(m, "PROV_INTEL_SEC", PROV_INTEL_SEC); +#endif + + /* Define Windows CSP Provider Names */ +#ifdef MS_DEF_PROV + PyModule_AddStringConstant(m, "MS_DEF_PROV", MS_DEF_PROV); +#endif +#ifdef MS_ENHANCED_PROV + PyModule_AddStringConstant(m, "MS_ENHANCED_PROV", MS_ENHANCED_PROV); +#endif +#ifdef MS_DEF_RSA_SIG_PROV + PyModule_AddStringConstant(m, "MS_DEF_RSA_SIG_PROV", + MS_DEF_RSA_SIG_PROV); +#endif +#ifdef MS_DEF_RSA_SCHANNEL_PROV + PyModule_AddStringConstant(m, "MS_DEF_RSA_SCHANNEL_PROV", + MS_DEF_RSA_SCHANNEL_PROV); +#endif +#ifdef MS_ENHANCED_RSA_SCHANNEL_PROV + PyModule_AddStringConstant(m, "MS_ENHANCED_RSA_SCHANNEL_PROV", + MS_ENHANCED_RSA_SCHANNEL_PROV); +#endif +#ifdef MS_DEF_DSS_PROV + PyModule_AddStringConstant(m, "MS_DEF_DSS_PROV", MS_DEF_DSS_PROV); +#endif +#ifdef MS_DEF_DSS_DH_PROV + PyModule_AddStringConstant(m, "MS_DEF_DSS_DH_PROV", + MS_DEF_DSS_DH_PROV); +#endif +#ifdef INTEL_DEF_PROV + PyModule_AddStringConstant(m, "INTEL_DEF_PROV", INTEL_DEF_PROV); +#endif + + if (PyErr_Occurred()) + Py_FatalError("can't initialize module winrandom"); +} + +/* + +CryptGenRandom usage is described in +http://msdn.microsoft.com/library/en-us/security/security/cryptgenrandom.asp +and many associated pages on Windows Cryptographic Service +Providers, which say: + + With Microsoft CSPs, CryptGenRandom uses the same + random number generator used by other security + components. This allows numerous processes to + contribute to a system-wide seed. CryptoAPI stores + an intermediate random seed with every user. To form + the seed for the random number generator, a calling + application supplies bits it might havefor instance, + mouse or keyboard timing inputthat are then added to + both the stored seed and various system data and + user data such as the process ID and thread ID, the + system clock, the system time, the system counter, + memory status, free disk clusters, the hashed user + environment block. This result is SHA-1 hashed, and + the output is used to seed an RC4 stream, which is + then used as the random stream and used to update + the stored seed. + +The only other detailed description I've found of the +sources of randomness for CryptGenRandom is this excerpt +from a posting +http://www.der-keiler.de/Newsgroups/comp.security.ssh/2002-06/0169.html + +From: Jon McClelland (dowot69@hotmail.com) +Date: 06/12/02 +... + +Windows, call a function such as CryptGenRandom, which has two of +the properties of a good random number generator, unpredictability and +even value distribution. This function, declared in Wincrypt.h, is +available on just about every Windows platform, including Windows 95 +with Internet Explorer 3.02 or later, Windows 98, Windows Me, Windows +CE v3, Windows NT 4, Windows 2000, and Windows XP. + +CryptGenRandom gets its randomness, also known as entropy, from many +sources in Windows 2000, including the following: +The current process ID (GetCurrentProcessID). +The current thread ID (GetCurrentThreadID). +The ticks since boot (GetTickCount). +The current time (GetLocalTime). +Various high-precision performance counters (QueryPerformanceCounter). +A Message Digest 4 (MD4) hash of the user's environment block, which +includes username, computer name, and search path. + +High-precision internal CPU counters, such as RDTSC, RDMSR, RDPMC (x86 +only-more information about these counters is at +developer.intel.com/software/idap/resources/technical_collateral/pentiumii/RDTSCPM1.HTM +). + +Low-level system information, such as idle time, kernel time, +interrupt times, commit limit, page read count, cache read count, +nonpaged pool allocations, alignment fixup count, operating system +lookaside information. + +Such information is added to a buffer, which is hashed using MD4 and +used as the key to modify a buffer, using RC4, provided by the user. +(Refer to the CryptGenRandom documentation in the Platform SDK for +more information about the user-provided buffer.) Hence, if the user +provides additional data in the buffer, this is used as an element in +the witches brew to generate the random data. The result is a +cryptographically random number generator. +Also, note that if you plan to sell your software to the United States +federal government, you'll need to use FIPS 140-1-approved algorithms. +The default versions of CryptGenRandom in Microsoft Windows CE v3, +Windows 95, Windows 98, Windows Me, Windows 2000, and Windows XP are +FIPS-approved. Obviously FIPS-140 compliance is necessary but not +sufficient to provide a properly secure source of random data. + +*/ + +#endif /* MS_WIN32 */ diff --git a/src/Crypto/test.py b/src/Crypto/test.py new file mode 100644 index 00000000..ff59b067 --- /dev/null +++ b/src/Crypto/test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +# +# Test script for the Python Cryptography Toolkit. +# + +__revision__ = "$Id: test.py,v 1.7 2002/07/11 14:31:19 akuchling Exp $" + +import os, sys + + +# Add the build directory to the front of sys.path +from distutils.util import get_platform +s = "build/lib.%s-%.3s" % (get_platform(), sys.version) +s = os.path.join(os.getcwd(), s) +sys.path.insert(0, s) +s = os.path.join(os.getcwd(), 'test') +sys.path.insert(0, s) + +from allmydata.Crypto.Util import test + +args = sys.argv[1:] +quiet = "--quiet" in args +if quiet: args.remove('--quiet') + +if not quiet: + print '\nStream Ciphers:' + print '===============' + +if args: test.TestStreamModules(args, verbose= not quiet) +else: test.TestStreamModules(verbose= not quiet) + +if not quiet: + print '\nBlock Ciphers:' + print '==============' + +if args: test.TestBlockModules(args, verbose= not quiet) +else: test.TestBlockModules(verbose= not quiet) + + diff --git a/src/Crypto/test/template b/src/Crypto/test/template new file mode 100644 index 00000000..dce6c9b4 --- /dev/null +++ b/src/Crypto/test/template @@ -0,0 +1,26 @@ +# +# Test script for Crypto.XXX +# + +__revision__ = "$Id: template,v 1.1 2002/05/17 13:31:48 akuchling Exp $" + +from sancho.unittest import TestScenario, parse_args, run_scenarios + +tested_modules = [ "Crypto.XXX" ] + +class XXXTest (TestScenario): + + def setup (self): + pass + + def shutdown (self): + pass + + def check_ (self): + "" + pass + + +if __name__ == "__main__": + (scenarios, options) = parse_args() + run_scenarios(scenarios, options) diff --git a/src/Crypto/test/test_chaffing.py b/src/Crypto/test/test_chaffing.py new file mode 100644 index 00000000..512b53bc --- /dev/null +++ b/src/Crypto/test/test_chaffing.py @@ -0,0 +1,58 @@ +# +# Test script for Crypto.XXX +# + +__revision__ = "$Id: test_chaffing.py,v 1.2 2003/02/28 15:23:59 akuchling Exp $" + +from sancho.unittest import TestScenario, parse_args, run_scenarios +from allmydata.Crypto.Protocol import Chaffing + +tested_modules = [ "Crypto.Protocol.Chaffing" ] + +text = """\ +When in the Course of human events, it becomes necessary for one people to +dissolve the political bands which have connected them with another, and to +assume among the powers of the earth, the separate and equal station to which +the Laws of Nature and of Nature's God entitle them, a decent respect to the +opinions of mankind requires that they should declare the causes which impel +them to the separation. + +We hold these truths to be self-evident, that all men are created equal, that +they are endowed by their Creator with certain unalienable Rights, that among +these are Life, Liberty, and the pursuit of Happiness. That to secure these +rights, Governments are instituted among Men, deriving their just powers from +the consent of the governed. That whenever any Form of Government becomes +destructive of these ends, it is the Right of the People to alter or to +abolish it, and to institute new Government, laying its foundation on such +principles and organizing its powers in such form, as to them shall seem most +likely to effect their Safety and Happiness. +""" + +class ChaffingTest (TestScenario): + + def setup (self): + pass + + def shutdown (self): + pass + + def check_chaffing (self): + "Simple tests of chaffing and winnowing" + self.test_stmt('Chaffing.Chaff()') + self.test_stmt('Chaffing.Chaff(0.5, 1)') + self.test_exc('Chaffing.Chaff(factor=-1)', ValueError) + self.test_exc('Chaffing.Chaff(blocksper=-1)', ValueError) + + data = [(1, 'data1', 'data1'), (2, 'data2', 'data2')] + c = Chaffing.Chaff(1.0, 1) + self.test_stmt('c.chaff(data)') + chaff = c.chaff(data) + self.test_val('len(chaff)', 4) + + c = Chaffing.Chaff(0.0, 1) + chaff = c.chaff(data) + self.test_val('len(chaff)', 2) + +if __name__ == "__main__": + (scenarios, options) = parse_args() + run_scenarios(scenarios, options) diff --git a/src/Crypto/test/test_hashes.py b/src/Crypto/test/test_hashes.py new file mode 100644 index 00000000..8e9e074e --- /dev/null +++ b/src/Crypto/test/test_hashes.py @@ -0,0 +1,94 @@ +# +# Test script for Crypto.Util.randpool. +# + +__revision__ = "$Id: test_hashes.py,v 1.4 2004/08/13 22:23:12 akuchling Exp $" + +import time, string, binascii +from sancho.unittest import TestScenario, parse_args, run_scenarios + +from allmydata.Crypto.Hash import * +import testdata + +tested_modules = [ "Crypto.Hash.MD2", "Crypto.Hash.MD4", "Crypto.Hash.MD5", + "Crypto.Hash.RIPEMD", "Crypto.Hash.SHA", "Crypto.Hash.SHA256"] + +class HashTest (TestScenario): + + def setup (self): + teststr='1' # Build 128K of test data + for i in xrange(0, 17): + teststr=teststr+teststr + self.str_128k = teststr + + def shutdown (self): + del self.str_128k + + def compare(self, hash_mod, strg, hex_result): + result = binascii.a2b_hex(hex_result) + obj = hash_mod.new(strg) + s1 = obj.digest() + + # Check that the right hash result is produced + self.test_val('s1', result) + + # Check that .hexdigest() produces the same output + self.test_val('obj.hexdigest()', hex_result) + + # Test second hashing, and copying of a hashing object + self.test_val('obj.digest()', result) + self.test_val('obj.copy().digest()', result) + + + def run_test_suite (self, hash_mod, test_vectors): + for text, digest in test_vectors: + self.compare(hash_mod, text, digest) + + def benchmark (self, hash_mod): + obj = hash_mod.new() + start=time.time() + s=obj.update(self.str_128k) + end=time.time() + delta = end-start + print hash_mod.__name__, ':', + if delta == 0: + print 'Unable to measure time -- elapsed time too small' + else: + print '%.2f K/sec' % (128/(end-start)) + + def check_md2 (self): + "MD2 module" + self.run_test_suite(MD2, testdata.md2) + self.benchmark(MD2) + + def check_md4 (self): + "MD4 module" + self.run_test_suite(MD4, testdata.md4) + self.benchmark(MD4) + + def check_md5 (self): + "MD5 module" + self.run_test_suite(MD5, testdata.md5) + self.benchmark(MD5) + + def check_ripemd (self): + "RIPEMD module" + self.run_test_suite(RIPEMD, testdata.ripemd) + self.benchmark(RIPEMD) + + def check_sha (self): + "SHA module" + self.run_test_suite(SHA, testdata.sha) + self.benchmark(SHA) + + def check_sha256 (self): + "SHA256 module" + self.run_test_suite(SHA256,testdata.sha256) + self.benchmark(SHA256) + +# class HashTest + + +if __name__ == "__main__": + (scenarios, options) = parse_args() + run_scenarios(scenarios, options) diff --git a/src/Crypto/test/test_number.py b/src/Crypto/test/test_number.py new file mode 100644 index 00000000..39a87fce --- /dev/null +++ b/src/Crypto/test/test_number.py @@ -0,0 +1,85 @@ +# +# Test script for Crypto.Util.number. +# + +__revision__ = "$Id: test_number.py,v 1.4 2003/04/04 18:21:35 akuchling Exp $" + +from sancho.unittest import TestScenario, parse_args, run_scenarios +from allmydata.Crypto.Util import number + +tested_modules = [ "Crypto.Util.number" ] + +class NumberTest (TestScenario): + + def setup (self): + pass + + def shutdown (self): + pass + + def check_getRandomNumber (self): + "Check generation of N-bit random numbers" + def f(N): + return '\xff' * N + + self.test_val('number.getRandomNumber(1, f)', 1) + self.test_val('number.getRandomNumber(4, f)', 15) + self.test_val('number.getRandomNumber(8, f)', 255) + self.test_val('number.getRandomNumber(12, f)', 4095) + self.test_val('number.getRandomNumber(16, f)', 65535) + + def check_GCD (self): + "Check GCD computation" + self.test_val('number.GCD(1, 5)', 1) + self.test_val('number.GCD(2, 6)', 2) + self.test_val('number.GCD(16, 12)', 4) + + def check_inverse (self): + "Check computation of inverses" + self.test_val('number.inverse(9, 10)', 9) + self.test_val('number.inverse(1, 2)', 1) + self.test_val('number.inverse(529, 10502)', 3097) + + def check_getPrime (self): + "Check generation of primes" + def f(n): + return '\xff' * n + self.test_val('number.getPrime(1, f)', 3) + self.test_val('number.getPrime(2, f)', 3) + self.test_val('number.getPrime(8, f)', 257) + self.test_val('number.getPrime(75, f)', 37778931862957161709601L) + + def check_isPrime (self): + "Check verification of primes" + self.test_bool('number.isPrime(1)', want_true=0) + self.test_bool('number.isPrime(2)') + self.test_bool('number.isPrime(3)') + self.test_bool('number.isPrime(4)', want_true=0) + self.test_bool('number.isPrime(37778931862957161709601L)') + self.test_bool('number.isPrime(37778931862957161709603L)', + want_true=0) + + def check_longbytes (self): + "Check conversion between bytes and integers" + self.test_val('number.long_to_bytes(1)', '\x01') + self.test_val('number.long_to_bytes(1, 2)', '\x00\x01') + self.test_val('number.long_to_bytes(511)', '\x01\xff') + + self.test_val('number.bytes_to_long("\x01")', 1) + self.test_val('number.bytes_to_long("\xff\x01")', 0xff01) + self.test_val('number.bytes_to_long("\x12\x34\x01")', 0x123401) + + def check_size (self): + "Check measurement of number sizes" + self.test_val('number.size(1)', 1) + self.test_val('number.size(15)', 4) + self.test_val('number.size(255)', 8) + self.test_val('number.size(256)', 9) + + +# class NumberTest + + +if __name__ == "__main__": + (scenarios, options) = parse_args() + run_scenarios(scenarios, options) diff --git a/src/Crypto/test/test_publickey.py b/src/Crypto/test/test_publickey.py new file mode 100644 index 00000000..d03fa91f --- /dev/null +++ b/src/Crypto/test/test_publickey.py @@ -0,0 +1,122 @@ +# +# Test script for Crypto.Util.PublicKey. +# + +__revision__ = "$Id: test_publickey.py,v 1.7 2003/04/04 19:38:28 akuchling Exp $" + +import sys, cPickle +from sancho.unittest import TestScenario, parse_args, run_scenarios +from allmydata.Crypto.PublicKey import * +from allmydata.Crypto.Util.randpool import RandomPool +from allmydata.Crypto.Util import number + +tested_modules = [ "Crypto.PublicKey.RSA", "Crypto.PublicKey.DSA", + "Crypto.PublicKey.ElGamal", "Crypto.PublicKey.qNEW"] + +class PublicKeyTest (TestScenario): + + def setup (self): + # Set up a random pool; we won't bother to actually fill it with + # entropy from the keyboard + self.pool = RandomPool(384) + self.pool.stir() + + def shutdown (self): + del self.pool + + def testkey (self, key, randfunc, verbose=0): + plaintext="Hello" + # Generate maximum-size plaintext + maxplain = (key.size() // 8) * '\377' + + if key.can_encrypt(): + if verbose: print ' Encryption/decryption test' + K=number.getPrime(10, randfunc) + ciphertext=key.encrypt(plaintext, K) + self.test_val('key.decrypt(ciphertext)', plaintext) + ciphertext=key.encrypt(maxplain, K) + self.test_val('key.decrypt(ciphertext)', maxplain) + + if key.can_sign(): + if verbose: print ' Signature test' + K=number.getPrime(30, randfunc) + signature=key.sign(plaintext, K) + self.test_bool('key.verify(plaintext, signature)') + self.test_bool('key.verify(plaintext[:-1], signature)', + want_true=0) + + # Change a single bit in the plaintext + badtext=plaintext[:-3]+chr( 1 ^ ord(plaintext[-3]) )+plaintext[-3:] + self.test_bool('key.verify(badtext, signature)', want_true=0) + + if verbose: print ' Removing private key data' + pubonly=key.publickey() + self.test_bool('pubonly.verify(plaintext, signature)') + + # Test blinding + if key.can_blind(): + if verbose: print ' Blinding test' + K=number.getPrime(30, randfunc) + B="garbage" + blindedtext=key.blind(plaintext, B) + signature=key.sign(blindedtext, K) + unblindedsignature=(key.unblind(signature[0], B),) + self.test_bool('key.verify(plaintext, unblindedsignature)') + self.test_val('key.sign(plaintext, K)', unblindedsignature) + + # Change a single bit in the blinding factor + badB=B[:-3]+chr( 1 ^ ord(B[-3]) )+B[-3:] + badunblindedsignature=(key.unblind(signature[0], badB),) + self.test_false('key.verify(badtext, badunblindedsignature)') + + badblindedtext=key.blind(plaintext, badB) + badsignature=key.sign(blindedtext, K) + badunblindedsignature2=(key.unblind(signature[0], B),) + self.test_false('key.verify(badtext, badunblindedsignature2)') + + + def exercise (self, randfunc, pk_mod, verbose=0): + N=256 # Key size, measured in bits + + key=pk_mod.generate(N, randfunc) + + if verbose: + print ' Key data:' + for field in key.keydata: + print " ", field, ':', hex(getattr(key,field)) + + if verbose: print " Testing newly generated key" + self.testkey(key, randfunc, verbose) + if verbose: print " Testing pickled/unpickled key" + import pickle + s = pickle.dumps(key) ; key2 = pickle.loads(s) + self.testkey(key2, randfunc, verbose) + + if verbose: print " Testing cPickled key" + s = cPickle.dumps(key) ; key2 = cPickle.loads(s) + self.testkey(key2, randfunc, verbose) + if verbose: print + + + def check_rsa(self): + "Check RSA algorithm" + self.exercise(self.pool.get_bytes, RSA) + + def check_dsa(self): + "Check DSA algorithm" + self.exercise(self.pool.get_bytes, DSA) + + def check_elgamal(self): + "Check ElGamal algorithm" + self.exercise(self.pool.get_bytes, ElGamal) + + def check_qnew(self): + "Check qNEW algorithm" + self.exercise(self.pool.get_bytes, qNEW) + +# class PublicKeyTest + + +if __name__ == "__main__": + (scenarios, options) = parse_args() + run_scenarios(scenarios, options) diff --git a/src/Crypto/test/test_randpool.py b/src/Crypto/test/test_randpool.py new file mode 100644 index 00000000..800af9ca --- /dev/null +++ b/src/Crypto/test/test_randpool.py @@ -0,0 +1,48 @@ +# +# Test script for Crypto.Util.randpool. +# + +__revision__ = "$Id: test_randpool.py,v 1.3 2003/02/28 15:24:01 akuchling Exp $" + +from sancho.unittest import TestScenario, parse_args, run_scenarios +from allmydata.Crypto.Hash import SHA +from allmydata.Crypto.Util import randpool + +tested_modules = [ "Crypto.Util.randpool" ] + +class RandomPoolTest (TestScenario): + + def setup (self): + self.pool = randpool.RandomPool(160, hash=SHA) + + def shutdown (self): + del self.pool + + def check_init (self): + "Check initial state" + self.test_val('self.pool.entropy', self.pool.bits) + + def check_get_bytes (self): + "Check retrieving of bytes from the pool" + start_entropy = self.pool.entropy + self.test_bool('self.pool.entropy > 0') + + # Draw out half of the pool's entropy + size = self.pool.entropy / 8 / 2 + self.test_stmt('self.pool.get_bytes(size)') + self.test_val('self.pool.entropy', start_entropy - size*8) + + # Draw out the rest of the pool's entropy + self.test_stmt('self.pool.get_bytes(size)') + self.test_val('self.pool.entropy', 0) + + # Remove yet more data; entropy stays at zero + self.test_stmt('self.pool.get_bytes(size)') + self.test_val('self.pool.entropy', 0) + +# class RandomPoolTest + + +if __name__ == "__main__": + (scenarios, options) = parse_args() + run_scenarios(scenarios, options) diff --git a/src/Crypto/test/test_rfc1751.py b/src/Crypto/test/test_rfc1751.py new file mode 100644 index 00000000..60ec4427 --- /dev/null +++ b/src/Crypto/test/test_rfc1751.py @@ -0,0 +1,45 @@ +# +# Test script for Crypto.Util.randpool. +# + +__revision__ = "$Id: test_rfc1751.py,v 1.3 2003/02/28 15:24:01 akuchling Exp $" + +import binascii +from sancho.unittest import TestScenario, parse_args, run_scenarios +from allmydata.Crypto.Util import RFC1751 + +tested_modules = [ "Crypto.Util.RFC1751" ] + +test_data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), + ('CCAC2AED591056BE4F90FD441C534766', + 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), + ('EFF81F9BFBC65350920CDD7416DE8009', + 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') + ] + +class RFC1751Test (TestScenario): + + def setup (self): + pass + + def shutdown (self): + pass + + def check_k2e (self): + "Check converting keys to English" + for key, words in test_data: + key=binascii.a2b_hex(key) + self.test_val('RFC1751.key_to_english(key)', words) + + def check_e2k (self): + "Check converting English strings to keys" + for key, words in test_data: + key=binascii.a2b_hex(key) + self.test_val('RFC1751.english_to_key(words)', key) + +# class RFC1751Test + + +if __name__ == "__main__": + (scenarios, options) = parse_args() + run_scenarios(scenarios, options) diff --git a/src/Crypto/test/testdata.py b/src/Crypto/test/testdata.py new file mode 100644 index 00000000..d6efdf28 --- /dev/null +++ b/src/Crypto/test/testdata.py @@ -0,0 +1,667 @@ +# +# testdata.py : Test data for the various algorithms +# +# Part of the Python Cryptography Toolkit +# +# Distribute and use freely; there are no restrictions on further +# dissemination and usage except those imposed by the laws of your +# country of residence. This software is provided "as is" without +# warranty of fitness for use or suitability for any purpose, express +# or implied. Use at your own risk or not at all. +# + +# Data for encryption algorithms is saved as (key, plaintext, +# ciphertext) tuples. Hashing algorithm test data is simply +# (text, hashvalue) pairs. + +# MD2 validation data + +md2= [ + ("", "8350e5a3e24c153df2275c9f80692773"), + ("a", "32ec01ec4a6dac72c0ab96fb34c0b5d1"), + ("abc", "da853b0d3f88d99b30283a69e6ded6bb"), + ("message digest", "ab4f496bfb2a530b219ff33031fe06b0"), + ("abcdefghijklmnopqrstuvwxyz", "4e8ddff3650292ab5a4108c3aa47940b"), + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "da33def2a42df13975352846c30338cd"), + ("12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "d5976f79d83d3a0dc9806c3c66f3efd8") + ] + +# MD4 validation data + +md4= [ + ('', "31d6cfe0d16ae931b73c59d7e0c089c0"), + ("a", "bde52cb31de33e46245e05fbdbd6fb24"), + ("abc", "a448017aaf21d8525fc10ae87aa6729d"), + ("message digest", "d9130a8164549fe818874806e1c7014b"), + ("abcdefghijklmnopqrstuvwxyz", "d79e1c308aa5bbcdeea8ed63df412da9"), + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "043f8582f241db351ce627e153e7f0e4"), + ("12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "e33b4ddc9c38f2199c3e7b164fcc0536"), + ] + +# MD5 validation data + +md5= [ + ('', "d41d8cd98f00b204e9800998ecf8427e"), + ('a', "0cc175b9c0f1b6a831c399e269772661"), + ('abc', "900150983cd24fb0d6963f7d28e17f72"), + ('message digest', "f96b697d7cb7938d525a2f31aaf161d0"), + ('abcdefghijklmnopqrstuvwxyz', "c3fcd3d76192e4007dfb496cca67e13b"), + ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + "d174ab98d277d9f5a5611c2c9f419d9f"), + ('12345678901234567890123456789012345678901234567890123456789' + '012345678901234567890', "57edf4a22be3c955ac49da2e2107b67a") + ] + +# Test data for SHA, the Secure Hash Algorithm. + +sha = [ + ('abc', "a9993e364706816aba3e25717850c26c9cd0d89d"), + ('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', + "84983e441c3bd26ebaae4aa1f95129e5e54670f1"), + (1000000 * 'a', '34aa973cd4c4daa4f61eeb2bdbad27316534016f'), + ] + +sha256 = [ + ('abc', "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), + ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"), + ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"), + ("Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battlefield of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate--we can not consecrate--we can not hallow--this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us--that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion--that we here highly resolve that these dead shall not have died in vain--that this nation, under God, shall have a new birth of freedom--and that government of the people, by the people, for the people, shall not perish from the earth. -- President Abraham Lincoln, November 19, 1863", + "4d25fccf8752ce470a58cd21d90939b7eb25f3fa418dd2da4c38288ea561e600"), + ("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), + ("This is exactly 64 bytes long, not counting the terminating byte", "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"), + ("For this sample, this 63-byte string will be used as input data", "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"), + ("And this textual data, astonishing as it may appear, is exactly 128 bytes in length, as are both SHA-384 and SHA-512 block sizes", + "0ab803344830f92089494fb635ad00d76164ad6e57012b237722df0d7ad26896"), + ("By hashing data that is one byte less than a multiple of a hash block length (like this 127-byte string), bugs may be revealed.", + "e4326d0459653d7d3514674d713e74dc3df11ed4d30b4013fd327fdb9e394c26"), + ("qwerty" * 65536, + "5e3dfe0cc98fd1c2de2a9d2fd893446da43d290f2512200c515416313cdf3192"), + ("Rijndael is AES" * 1024, + "80fced5a97176a5009207cd119551b42c5b51ceb445230d02ecc2663bbfb483a"), + (1000000 * 'a', 'cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0'), + ] + +ripemd = [ ("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"), + ("a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"), + ("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"), + ("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"), + ("abcdefghijklmnopqrstuvwxyz", + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"), + ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "12a053384a9c0c88e405a06c27dcf49ada62eb2b"), + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "b0e20b6e3116640286ed3a87a5713079b21f5189"), + (8 *"1234567890", "9b752e45573d4b39f4dbd3323cab82bf63326bfb"), + (1000000 * 'a', "52783243c1697bdbe16d37f97f68f08325dc1528"), +] + +#Test data for SHA256 +sha256 = [("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), + ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"), + ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"), + ("Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battlefield of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate--we can not consecrate--we can not hallow--this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us--that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion--that we here highly resolve that these dead shall not have died in vain--that this nation, under God, shall have a new birth of freedom--and that government of the people, by the people, for the people, shall not perish from the earth. -- President Abraham Lincoln, November 19, 1863", + "4d25fccf8752ce470a58cd21d90939b7eb25f3fa418dd2da4c38288ea561e600"), + ("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), + ("This is exactly 64 bytes long, not counting the terminating byte", "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"), + ("For this sample, this 63-byte string will be used as input data", "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"), + ("And this textual data, astonishing as it may appear, is exactly 128 bytes in length, as are both SHA-384 and SHA-512 block sizes", + "0ab803344830f92089494fb635ad00d76164ad6e57012b237722df0d7ad26896"), + ("By hashing data that is one byte less than a multiple of a hash block length (like this 127-byte string), bugs may be revealed.", + "e4326d0459653d7d3514674d713e74dc3df11ed4d30b4013fd327fdb9e394c26"), + ("qwerty" * 65536, + "5e3dfe0cc98fd1c2de2a9d2fd893446da43d290f2512200c515416313cdf3192"), + ("Rijndael is AES" * 1024, + "80fced5a97176a5009207cd119551b42c5b51ceb445230d02ecc2663bbfb483a"), +] +sha256 = sha256[:1] + +# DES validation data + +# Key, IV, plaintext, ciphertext +des_cbc= [('0123456789abcdef', 'fedcba9876543210', + "7654321 Now is the time for \000\000\000\000", 'ccd173ffab2039f4acd8aefddfd8a1eb468e91157888ba681d269397f7fe62b4')] + +des = [ ('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'), + ('0101010101010101', '95F8A5E5DD31D900', '8000000000000000'), + ('0101010101010101', 'DD7F121CA5015619', '4000000000000000'), + ('0101010101010101', '2E8653104F3834EA', '2000000000000000'), + ('0101010101010101', '4BD388FF6CD81D4F', '1000000000000000'), + ('0101010101010101', '20B9E767B2FB1456', '0800000000000000'), + ('0101010101010101', '55579380D77138EF', '0400000000000000'), + ('0101010101010101', '6CC5DEFAAF04512F', '0200000000000000'), + ('0101010101010101', '0D9F279BA5D87260', '0100000000000000'), + ('0101010101010101', 'D9031B0271BD5A0A', '0080000000000000'), + ('0101010101010101', '424250B37C3DD951', '0040000000000000'), + ('0101010101010101', 'B8061B7ECD9A21E5', '0020000000000000'), + ('0101010101010101', 'F15D0F286B65BD28', '0010000000000000'), + ('0101010101010101', 'ADD0CC8D6E5DEBA1', '0008000000000000'), + ('0101010101010101', 'E6D5F82752AD63D1', '0004000000000000'), + ('0101010101010101', 'ECBFE3BD3F591A5E', '0002000000000000'), + ('0101010101010101', 'F356834379D165CD', '0001000000000000'), + ('0101010101010101', '2B9F982F20037FA9', '0000800000000000'), + ('0101010101010101', '889DE068A16F0BE6', '0000400000000000'), + ('0101010101010101', 'E19E275D846A1298', '0000200000000000'), + ('0101010101010101', '329A8ED523D71AEC', '0000100000000000'), + ('0101010101010101', 'E7FCE22557D23C97', '0000080000000000'), + ('0101010101010101', '12A9F5817FF2D65D', '0000040000000000'), + ('0101010101010101', 'A484C3AD38DC9C19', '0000020000000000'), + ('0101010101010101', 'FBE00A8A1EF8AD72', '0000010000000000'), + ('0101010101010101', '750D079407521363', '0000008000000000'), + ('0101010101010101', '64FEED9C724C2FAF', '0000004000000000'), + ('0101010101010101', 'F02B263B328E2B60', '0000002000000000'), + ('0101010101010101', '9D64555A9A10B852', '0000001000000000'), + ('0101010101010101', 'D106FF0BED5255D7', '0000000800000000'), + ('0101010101010101', 'E1652C6B138C64A5', '0000000400000000'), + ('0101010101010101', 'E428581186EC8F46', '0000000200000000'), + ('0101010101010101', 'AEB5F5EDE22D1A36', '0000000100000000'), + ('0101010101010101', 'E943D7568AEC0C5C', '0000000080000000'), + ('0101010101010101', 'DF98C8276F54B04B', '0000000040000000'), + ('0101010101010101', 'B160E4680F6C696F', '0000000020000000'), + ('0101010101010101', 'FA0752B07D9C4AB8', '0000000010000000'), + ('0101010101010101', 'CA3A2B036DBC8502', '0000000008000000'), + ('0101010101010101', '5E0905517BB59BCF', '0000000004000000'), + ('0101010101010101', '814EEB3B91D90726', '0000000002000000'), + ('0101010101010101', '4D49DB1532919C9F', '0000000001000000'), + ('0101010101010101', '25EB5FC3F8CF0621', '0000000000800000'), + ('0101010101010101', 'AB6A20C0620D1C6F', '0000000000400000'), + ('0101010101010101', '79E90DBC98F92CCA', '0000000000200000'), + ('0101010101010101', '866ECEDD8072BB0E', '0000000000100000'), + ('0101010101010101', '8B54536F2F3E64A8', '0000000000080000'), + ('0101010101010101', 'EA51D3975595B86B', '0000000000040000'), + ('0101010101010101', 'CAFFC6AC4542DE31', '0000000000020000'), + ('0101010101010101', '8DD45A2DDF90796C', '0000000000010000'), + ('0101010101010101', '1029D55E880EC2D0', '0000000000008000'), + ('0101010101010101', '5D86CB23639DBEA9', '0000000000004000'), + ('0101010101010101', '1D1CA853AE7C0C5F', '0000000000002000'), + ('0101010101010101', 'CE332329248F3228', '0000000000001000'), + ('0101010101010101', '8405D1ABE24FB942', '0000000000000800'), + ('0101010101010101', 'E643D78090CA4207', '0000000000000400'), + ('0101010101010101', '48221B9937748A23', '0000000000000200'), + ('0101010101010101', 'DD7C0BBD61FAFD54', '0000000000000100'), + ('0101010101010101', '2FBC291A570DB5C4', '0000000000000080'), + ('0101010101010101', 'E07C30D7E4E26E12', '0000000000000040'), + ('0101010101010101', '0953E2258E8E90A1', '0000000000000020'), + ('0101010101010101', '5B711BC4CEEBF2EE', '0000000000000010'), + ('0101010101010101', 'CC083F1E6D9E85F6', '0000000000000008'), + ('0101010101010101', 'D2FD8867D50D2DFE', '0000000000000004'), + ('0101010101010101', '06E7EA22CE92708F', '0000000000000002'), + ('0101010101010101', '166B40B44ABA4BD6', '0000000000000001'), + ('8001010101010101', '0000000000000000', '95A8D72813DAA94D'), + ('4001010101010101', '0000000000000000', '0EEC1487DD8C26D5'), + ('2001010101010101', '0000000000000000', '7AD16FFB79C45926'), + ('1001010101010101', '0000000000000000', 'D3746294CA6A6CF3'), + ('0801010101010101', '0000000000000000', '809F5F873C1FD761'), + ('0401010101010101', '0000000000000000', 'C02FAFFEC989D1FC'), + ('0201010101010101', '0000000000000000', '4615AA1D33E72F10'), + ('0180010101010101', '0000000000000000', '2055123350C00858'), + ('0140010101010101', '0000000000000000', 'DF3B99D6577397C8'), + ('0120010101010101', '0000000000000000', '31FE17369B5288C9'), + ('0110010101010101', '0000000000000000', 'DFDD3CC64DAE1642'), + ('0108010101010101', '0000000000000000', '178C83CE2B399D94'), + ('0104010101010101', '0000000000000000', '50F636324A9B7F80'), + ('0102010101010101', '0000000000000000', 'A8468EE3BC18F06D'), + ('0101800101010101', '0000000000000000', 'A2DC9E92FD3CDE92'), + ('0101400101010101', '0000000000000000', 'CAC09F797D031287'), + ('0101200101010101', '0000000000000000', '90BA680B22AEB525'), + ('0101100101010101', '0000000000000000', 'CE7A24F350E280B6'), + ('0101080101010101', '0000000000000000', '882BFF0AA01A0B87'), + ('0101040101010101', '0000000000000000', '25610288924511C2'), + ('0101020101010101', '0000000000000000', 'C71516C29C75D170'), + ('0101018001010101', '0000000000000000', '5199C29A52C9F059'), + ('0101014001010101', '0000000000000000', 'C22F0A294A71F29F'), + ('0101012001010101', '0000000000000000', 'EE371483714C02EA'), + ('0101011001010101', '0000000000000000', 'A81FBD448F9E522F'), + ('0101010801010101', '0000000000000000', '4F644C92E192DFED'), + ('0101010401010101', '0000000000000000', '1AFA9A66A6DF92AE'), + ('0101010201010101', '0000000000000000', 'B3C1CC715CB879D8'), + ('0101010180010101', '0000000000000000', '19D032E64AB0BD8B'), + ('0101010140010101', '0000000000000000', '3CFAA7A7DC8720DC'), + ('0101010120010101', '0000000000000000', 'B7265F7F447AC6F3'), + ('0101010110010101', '0000000000000000', '9DB73B3C0D163F54'), + ('0101010108010101', '0000000000000000', '8181B65BABF4A975'), + ('0101010104010101', '0000000000000000', '93C9B64042EAA240'), + ('0101010102010101', '0000000000000000', '5570530829705592'), + ('0101010101800101', '0000000000000000', '8638809E878787A0'), + ('0101010101400101', '0000000000000000', '41B9A79AF79AC208'), + ('0101010101200101', '0000000000000000', '7A9BE42F2009A892'), + ('0101010101100101', '0000000000000000', '29038D56BA6D2745'), + ('0101010101080101', '0000000000000000', '5495C6ABF1E5DF51'), + ('0101010101040101', '0000000000000000', 'AE13DBD561488933'), + ('0101010101020101', '0000000000000000', '024D1FFA8904E389'), + ('0101010101018001', '0000000000000000', 'D1399712F99BF02E'), + ('0101010101014001', '0000000000000000', '14C1D7C1CFFEC79E'), + ('0101010101012001', '0000000000000000', '1DE5279DAE3BED6F'), + ('0101010101011001', '0000000000000000', 'E941A33F85501303'), + ('0101010101010801', '0000000000000000', 'DA99DBBC9A03F379'), + ('0101010101010401', '0000000000000000', 'B7FC92F91D8E92E9'), + ('0101010101010201', '0000000000000000', 'AE8E5CAA3CA04E85'), + ('0101010101010180', '0000000000000000', '9CC62DF43B6EED74'), + ('0101010101010140', '0000000000000000', 'D863DBB5C59A91A0'), + ('0101010101010120', '0000000000000000', 'A1AB2190545B91D7'), + ('0101010101010110', '0000000000000000', '0875041E64C570F7'), + ('0101010101010108', '0000000000000000', '5A594528BEBEF1CC'), + ('0101010101010104', '0000000000000000', 'FCDB3291DE21F0C0'), + ('0101010101010102', '0000000000000000', '869EFD7F9F265A09'), + ('1046913489980131', '0000000000000000', '88D55E54F54C97B4'), + ('1007103489988020', '0000000000000000', '0C0CC00C83EA48FD'), + ('10071034C8980120', '0000000000000000', '83BC8EF3A6570183'), + ('1046103489988020', '0000000000000000', 'DF725DCAD94EA2E9'), + ('1086911519190101', '0000000000000000', 'E652B53B550BE8B0'), + ('1086911519580101', '0000000000000000', 'AF527120C485CBB0'), + ('5107B01519580101', '0000000000000000', '0F04CE393DB926D5'), + ('1007B01519190101', '0000000000000000', 'C9F00FFC74079067'), + ('3107915498080101', '0000000000000000', '7CFD82A593252B4E'), + ('3107919498080101', '0000000000000000', 'CB49A2F9E91363E3'), + ('10079115B9080140', '0000000000000000', '00B588BE70D23F56'), + ('3107911598080140', '0000000000000000', '406A9A6AB43399AE'), + ('1007D01589980101', '0000000000000000', '6CB773611DCA9ADA'), + ('9107911589980101', '0000000000000000', '67FD21C17DBB5D70'), + ('9107D01589190101', '0000000000000000', '9592CB4110430787'), + ('1007D01598980120', '0000000000000000', 'A6B7FF68A318DDD3'), + ('1007940498190101', '0000000000000000', '4D102196C914CA16'), + ('0107910491190401', '0000000000000000', '2DFA9F4573594965'), + ('0107910491190101', '0000000000000000', 'B46604816C0E0774'), + ('0107940491190401', '0000000000000000', '6E7E6221A4F34E87'), + ('19079210981A0101', '0000000000000000', 'AA85E74643233199'), + ('1007911998190801', '0000000000000000', '2E5A19DB4D1962D6'), + ('10079119981A0801', '0000000000000000', '23A866A809D30894'), + ('1007921098190101', '0000000000000000', 'D812D961F017D320'), + ('100791159819010B', '0000000000000000', '055605816E58608F'), + ('1004801598190101', '0000000000000000', 'ABD88E8B1B7716F1'), + ('1004801598190102', '0000000000000000', '537AC95BE69DA1E1'), + ('1004801598190108', '0000000000000000', 'AED0F6AE3C25CDD8'), + ('1002911598100104', '0000000000000000', 'B3E35A5EE53E7B8D'), + ('1002911598190104', '0000000000000000', '61C79C71921A2EF8'), + ('1002911598100201', '0000000000000000', 'E2F5728F0995013C'), + ('1002911698100101', '0000000000000000', '1AEAC39A61F0A464'), + ('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') ] + + +# Test data for Alleged RC4 + +arc4 = [ ('0000000000000000', '0000000000000000', 'de188941a3375d3a'), + ('0123456789abcdef', '0123456789abcdef', '75b7878099e0c596'), + ('0123456789abcdef', '0000000000000000', '7494c2e7104b0879'), + ('ef012345', '00000000000000000000', 'd6a141a7ec3c38dfbd61') ] + +# Test data for IDEA + +idea = [('00010002000300040005000600070008', '0000000100020003', '11fbed2b01986de5'), + ('00010002000300040005000600070008', '0102030405060708', '540E5FEA18C2F8B1'), + ('00010002000300040005000600070008', '0019324B647D96AF', '9F0A0AB6E10CED78'), + ('00010002000300040005000600070008', 'F5202D5B9C671B08', 'CF18FD7355E2C5C5'), + ('00010002000300040005000600070008', 'FAE6D2BEAA96826E', '85DF52005608193D'), + ('00010002000300040005000600070008', '0A141E28323C4650', '2F7DE750212FB734'), + ('00010002000300040005000600070008', '050A0F14191E2328', '7B7314925DE59C09'), + ('0005000A000F00140019001E00230028', '0102030405060708', '3EC04780BEFF6E20'), + ('3A984E2000195DB32EE501C8C47CEA60', '0102030405060708', '97BCD8200780DA86'), + ('006400C8012C019001F4025802BC0320', '05320A6414C819FA', '65BE87E7A2538AED'), + ('9D4075C103BC322AFB03E7BE6AB30006', '0808080808080808', 'F5DB1AC45E5EF9F9') + ]; + +# Test data for RC5 + +rc5 = [('10200c1000000000000000000000000000000000', '0000000000000000', + '21A5DBEE154B8F6D'), + ('10200c10915F4619BE41B2516355A50110A9CE91', '21A5DBEE154B8F6D', + 'F7C013AC5B2B8952'), + ('10200c10783348E75AEB0F2FD7B169BB8DC16787', 'F7C013AC5B2B8952', + '2F42B3B70369FC92'), + ('10200c10DC49DB1375A5584F6485B413B5F12BAF', '2F42B3B70369FC92', + '65C178B284D197CC'), + ('10200c105269F149D41BA0152497574D7F153125', '65C178B284D197CC', + 'EB44E415DA319824') + ] + +# Test data for ARC2 +arc2 = [ +('5068696c6970476c617373', '0000000000000000', '624fb3e887419e48'), +('5068696c6970476c617373', 'ffffffffffffffff', '79cadef44c4a5a85'), +('5068696c6970476c617373', '0001020304050607', '90411525b34e4c2c'), +('5068696c6970476c617373', '0011223344556677', '078656aaba61cbfb'), +('ffffffffffffffff', '0000000000000000', 'd7bcc5dbb4d6e56a'), +('ffffffffffffffff', 'ffffffffffffffff', '7259018ec557b357'), +('ffffffffffffffff', '0001020304050607', '93d20a497f2ccb62'), +('ffffffffffffffff', '0011223344556677', 'cb15a7f819c0014d'), +('ffffffffffffffff5065746572477265656e6177617953e5ffe553', '0000000000000000', '63ac98cdf3843a7a'), +('ffffffffffffffff5065746572477265656e6177617953e5ffe553', 'ffffffffffffffff', '3fb49e2fa12371dd'), +('ffffffffffffffff5065746572477265656e6177617953e5ffe553', '0001020304050607', '46414781ab387d5f'), +('ffffffffffffffff5065746572477265656e6177617953e5ffe553', '0011223344556677', 'be09dc81feaca271'), +('53e5ffe553', '0000000000000000', 'e64221e608be30ab'), +('53e5ffe553', 'ffffffffffffffff', '862bc60fdcd4d9a9'), +('53e5ffe553', '0001020304050607', '6a34da50fa5e47de'), +('53e5ffe553', '0011223344556677', '584644c34503122c'), +] + +# Test data for Blowfish + +blowfish = [('6162636465666768696a6b6c6d6e6f707172737475767778797a', + '424c4f5746495348', '324ed0fef413a203'), + ('57686f206973204a6f686e2047616c743f', 'fedcba9876543210', + 'cc91732b8022f684') + ] + +# Test data for DES3 + +des3_cbc=[] + +des3= [('0123456789abcdeffedcba9876543210', '0123456789abcde7', + '7f1d0a77826b8aff'), + ] + +# The DES test data can also be used to construct DES3 test data. +for key, iv, plain, cipher in des_cbc: + des3_cbc.append((key*3, iv, plain, cipher)) +for key, plain, cipher in des: + des3.append((key*3, plain, cipher)) + +# Test data for CAST + +_castkey = '0123456712345678234567893456789A' +_castdata = '0123456789ABCDEF' + +cast = [(_castkey, _castdata, '238B4FE5847E44B2'), + (_castkey[:10*2], _castdata, 'EB6A711A2C02271B'), + (_castkey[: 5*2], _castdata, '7AC816D16E9B302E'), + ] + +# Test data for XOR + +xor = [] + +# Test data for AES + +aes = [# 128-bit key + ('000102030405060708090A0B0C0D0E0F', + '00112233445566778899AABBCCDDEEFF', + '69C4E0D86A7B0430D8CDB78070B4C55A'), + + # 192-bit key + ('000102030405060708090A0B0C0D0E0F1011121314151617', + '00112233445566778899AABBCCDDEEFF', + 'DDA97CA4864CDFE06EAF70A0EC0D7191'), + + # 256-bit key + ('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F', + '00112233445566778899AABBCCDDEEFF', + '8EA2B7CA516745BFEAFC49904B496089'), + ] + +# Test data for AES modes, from NIST SP800-38A +from allmydata.Crypto.Cipher import AES + +counterstart='\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' + +aes_modes = [ + (AES.MODE_CBC, + '2b7e151628aed2a6abf7158809cf4f3c', + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('7649abac8119b246cee98e9b12e9197d' + '5086cb9b507219ee95db113a917678b2' + '73bed6b8e3c1743b7116e69e22229516' + '3ff1caa1681fac09120eca307586e1a7' + ), + {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), + (AES.MODE_CBC, + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('4f021db243bc633d7178183a9fa071e8' + 'b4d9ada9ad7dedf4e5e738763f69145a' + '571b242012fb7ae07fa9baac3df102e0' + '08b0e27988598881d920a9e64f5615cd' + ), + {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), + (AES.MODE_CBC, + ('603deb1015ca71be2b73aef0857d7781' + '1f352c073b6108d72d9810a30914dff4' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('f58c4c04d6e5f1ba779eabfb5f7bfbd6' + '9cfc4e967edb808d679f777bc6702c7d' + '39f23369a9d9bacfa530e26304231461' + 'b2eb05e2c39be9fcda6c19078c6a9d1b' + ), + {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), + + (AES.MODE_OFB, + ('2b7e151628aed2a6abf7158809cf4f3c' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('3b3fd92eb72dad20333449f8e83cfb4a' + '7789508d16918f03f53c52dac54ed825' + '9740051e9c5fecf64344f7a82260edcc' + '304c6528f659c77866a510d9c1d6ae5e' + ), + {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), + (AES.MODE_OFB, + ('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('cdc80d6fddf18cab34c25909c99a4174' + 'fcc28b8d4c63837c09e81700c1100401' + '8d9a9aeac0f6596f559c6d4daf59a5f2' + '6d9f200857ca6c3e9cac524bd9acc92a' + ), + {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), + (AES.MODE_OFB, + ('603deb1015ca71be2b73aef0857d7781' + '1f352c073b6108d72d9810a30914dff4' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('dc7e84bfda79164b7ecd8486985d3860' + '4febdc6740d20b3ac88f6ad82a4fb08d' + '71ab47a086e86eedf39d1c5bba97c408' + '0126141d67f37be8538f5a8be740e484' + ), + {'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'} ), + + (AES.MODE_CTR, + ('2b7e151628aed2a6abf7158809cf4f3c' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('874d6191b620e3261bef6864990db6ce' + '9806f66b7970fdff8617187bb9fffdff' + '5ae4df3edbd5d35e5b4f09020db03eab' + '1e031dda2fbe03d1792170a0f3009cee' + ), + {'counterstart': counterstart}, ), + (AES.MODE_CTR, + ('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('1abc932417521ca24f2b0459fe7e6e0b' + '090339ec0aa6faefd5ccc2c6f4ce8e94' + '1e36b26bd1ebc670d1bd1d665620abf7' + '4f78a7f6d29809585a97daec58c6b050' + ), + {'counterstart': counterstart}, ), + (AES.MODE_CTR, + ('603deb1015ca71be2b73aef0857d7781' + '1f352c073b6108d72d9810a30914dff4' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ('601ec313775789a5b7a7f504bbf3d228' + 'f443e3ca4d62b59aca84e990cacaf5c5' + '2b0930daa23de94ce87017ba2d84988d' + 'dfc9c58db67aada613c2dd08457941a6' + ), + {'counterstart': counterstart}, ), + + (AES.MODE_CFB, + '2b7e151628aed2a6abf7158809cf4f3c', + '6bc1bee22e409f96e93d7e117393172aae2d', + '3b79424c9c0dd436bace9e0ed4586a4f32b9', + {'segment_size':8, + 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', + } + ), + (AES.MODE_CFB, + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + '6bc1bee22e409f96e93d7e117393172aae2d', + 'cda2521ef0a905ca44cd057cbf0d47a0678a', + {'segment_size':8, + 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', + } + ), + (AES.MODE_CFB, + ('603deb1015ca71be2b73aef0857d7781' + '1f352c073b6108d72d9810a30914dff4' + ), + '6bc1bee22e409f96e93d7e117393172aae2d', + 'dc1f1a8520a64db55fcc8ac554844e889700', + {'segment_size':8, + 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', + } + ), + + (AES.MODE_CFB, + ('2b7e151628aed2a6abf7158809cf4f3c' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ( + '3b3fd92eb72dad20333449f8e83cfb4a' + 'c8a64537a0b3a93fcde3cdad9f1ce58b' + '26751f67a3cbb140b1808cf187a4f4df' + 'c04b05357c5d1c0eeac4c66f9ff7f2e6' + ), + {'segment_size':128, + 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', + } + ), + (AES.MODE_CFB, + ('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ( + 'cdc80d6fddf18cab34c25909c99a4174' + '67ce7f7f81173621961a2b70171d3d7a' + '2e1e8a1dd59b88b1c8e60fed1efac4c9' + 'c05f9f9ca9834fa042ae8fba584b09ff' + ), + {'segment_size':128, + 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', + } + ), + (AES.MODE_CFB, + ('603deb1015ca71be2b73aef0857d7781' + '1f352c073b6108d72d9810a30914dff4' + ), + ('6bc1bee22e409f96e93d7e117393172a' + 'ae2d8a571e03ac9c9eb76fac45af8e51' + '30c81c46a35ce411e5fbc1191a0a52ef' + 'f69f2445df4f9b17ad2b417be66c3710' + ), + ( + 'dc7e84bfda79164b7ecd8486985d3860' + '39ffed143b28b1c832113c6331e5407b' + 'df10132415e54b92a13ed0a8267ae2f9' + '75a385741ab9cef82031623d55b1e471' + ), + {'segment_size':128, + 'IV':'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f', + } + ), + ] diff --git a/src/allmydata/__init__.py b/src/allmydata/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/allmydata/bucketstore.py b/src/allmydata/bucketstore.py new file mode 100644 index 00000000..e3e1b675 --- /dev/null +++ b/src/allmydata/bucketstore.py @@ -0,0 +1,134 @@ +import os + +from foolscap import Referenceable +from twisted.application import service +from twisted.python.failure import Failure +from allmydata.util import idlib +from zope.interface import implements +from allmydata.interfaces import RIBucketWriter, RIBucketReader + +from allmydata.util.assertutil import precondition, _assert + +class NoSuchBucketError(Failure): + pass + +class BucketStore(service.MultiService, Referenceable): + def __init__(self, store_dir): + precondition(os.path.isdir(store_dir)) + service.MultiService.__init__(self) + self._store_dir = store_dir + + self._leases = set() # should do weakref dances. + + def _get_bucket_dir(self, verifierid): + avid = idlib.b2a(verifierid) + return os.path.join(self._store_dir, avid) + + def has_bucket(self, verifierid): + return os.path.exists(self._get_bucket_dir(verifierid)) + + def allocate_bucket(self, verifierid, bucket_num, size, + leaser_credentials, canary): + bucket_dir = self._get_bucket_dir(verifierid) + precondition(not os.path.exists(bucket_dir)) + precondition(isinstance(bucket_num, int)) + bucket = WriteBucket(bucket_dir, verifierid, bucket_num, size) + bucket.set_leaser(leaser_credentials) + lease = Lease(verifierid, leaser_credentials, bucket, canary) + self._leases.add(lease) + return lease + + def get_buckets(self, verifierid): + # for now, only returns those created by this process, in this run + bucket_dir = self._get_bucket_dir(verifierid) + if os.path.exists(bucket_dir): + b = ReadBucket(bucket_dir, verifierid) + return [(b.get_bucket_num(), b)] + else: + return [] + +class Lease(Referenceable): + implements(RIBucketWriter) + + def __init__(self, verifierid, leaser, bucket, canary): + self._leaser = leaser + self._verifierid = verifierid + self._bucket = bucket + canary.notifyOnDisconnect(self._lost_canary) + + def get_bucket(self): + return self._bucket + + def remote_write(self, data): + self._bucket.write(data) + + def remote_close(self): + self._bucket.close() + + def _lost_canary(self): + pass + +class Bucket: + def __init__(self, bucket_dir, verifierid): + self._bucket_dir = bucket_dir + self._verifierid = verifierid + + def _write_attr(self, name, val): + f = file(os.path.join(self._bucket_dir, name), 'wb') + f.write(val) + f.close() + + def _read_attr(self, name): + f = file(os.path.join(self._bucket_dir, name), 'rb') + data = f.read() + f.close() + return data + + def is_complete(self): + return os.path.exists(os.path.join(self._bucket_dir, 'closed')) + +class WriteBucket(Bucket): + def __init__(self, bucket_dir, verifierid, bucket_num, size): + Bucket.__init__(self, bucket_dir, verifierid) + precondition(not os.path.exists(bucket_dir)) + os.mkdir(bucket_dir) + + self._size = size + self._data = file(os.path.join(self._bucket_dir, 'data'), 'wb') + self._bytes_written = 0 + + self._write_attr('bucket_num', str(bucket_num)) + + def set_leaser(self, leaser): + self._write_attr('leases', leaser) + + def write(self, data): + precondition(len(data) + self._bytes_written <= self._size) + self._data.write(data) + self._data.flush() + self._bytes_written += len(data) + + def close(self): + precondition(self._bytes_written == self._size) + self._data.close() + self._write_attr('closed', '') + + def is_complete(self): + complete = Bucket.is_complete(self) + if complete: + _assert(os.path.getsize(os.path.join(self._bucket_dir, 'data')) == self._size) + return complete + +class ReadBucket(Bucket, Referenceable): + implements(RIBucketReader) + + def __init__(self, bucket_dir, verifierid): + Bucket.__init__(self, bucket_dir, verifierid) + precondition(self.is_complete()) # implicitly asserts bucket_dir exists + + def get_bucket_num(self): + return int(self._read_attr('bucket_num')) + + def read(self): + return self._read_attr('data') + remote_read = read diff --git a/src/allmydata/chunk.py b/src/allmydata/chunk.py new file mode 100644 index 00000000..ec904191 --- /dev/null +++ b/src/allmydata/chunk.py @@ -0,0 +1,727 @@ + +""" +Read and write chunks from files. + +Version 1.0.0. + +A file is divided into blocks, each of which has size L{BLOCK_SIZE} +(except for the last block, which may be smaller). Blocks are encoded +into chunks. One publishes the hash of the entire file. Clients +who want to download the file first obtain the hash, then the clients +can receive chunks in any order. Cryptographic hashing is used to +verify each received chunk before writing to disk. Thus it is +impossible to download corrupt data if one has the correct file hash. + +One obtains the hash of a complete file via +L{CompleteChunkFile.file_hash}. One can read chunks from a complete +file by the sequence operations of C{len()} and subscripting on a +L{CompleteChunkFile} object. One can open an empty or partially +downloaded file with L{PartialChunkFile}, and read and write chunks +to this file. A chunk will fail to write if its contents and index +are not consistent with the overall file hash passed to +L{PartialChunkFile} when the partial chunk file was first created. + +The chunks have an overhead of less than 4% for files of size +less than C{10**20} bytes. + +Benchmarks: + + - On a 3 GHz Pentium 3, it took 3.4 minutes to first make a + L{CompleteChunkFile} object for a 4 GB file. Up to 10 MB of + memory was used as the constructor ran. A metafile filename + was passed to the constructor, and so the hash information was + written to the metafile. The object used a negligible amount + of memory after the constructor was finished. + - Creation of L{CompleteChunkFile} objects in future runs of the + program took negligible time, since the hash information was + already stored in the metafile. + +@var BLOCK_SIZE: Size of a block. See L{BlockFile}. +@var MAX_CHUNK_SIZE: Upper bound on the size of a chunk. + See L{CompleteChunkFile}. + +free (adj.): unencumbered; not under the control of others +Written by Connelly Barnes in 2005 and released into the +public domain with no warranty of any kind, either expressed +or implied. It probably won't make your computer catch on fire, +or eat your children, but it might. Use at your own risk. +""" + +import sha +import os +#import os.path + +from allmydata.util import bencode + +__all__ = ['CompleteChunkFile', 'PartialChunkFile'] + +__version__ = '1.0.0' + +BLOCK_SIZE = 65536 +MAX_CHUNK_SIZE = BLOCK_SIZE + 4096 + +def hash(s): + """ + Cryptographic hash function used by this module. + """ + return sha.new(s).digest() + + +def roundup_pow2(x): + """ + Round integer C{x} up to the nearest power of 2. + """ + ans = 1 + while ans < x: + ans *= 2 + return ans + + +class CompleteBinaryTreeMixin: + """ + Adds convenience methods to a complete binary tree. + + Assumes the total number of elements in the binary tree may be + accessed via C{__len__}, and that each element can be retrieved + using list subscripting. + + Tree is indexed like so:: + + + 0 + / \ + 1 2 + / \ / \ + 3 4 5 6 + / \ / \ / \ / \ + 7 8 9 10 11 12 13 14 + + """ + def parent(self, i): + """ + Index of the parent of C{i}. + """ + if i < 1 or (hasattr(self, '__len__') and i >= len(self)): + raise IndexError('index out of range: ' + repr(i)) + return (i - 1) // 2 + + def lchild(self, i): + """ + Index of the left child of C{i}. + """ + ans = 2 * i + 1 + if i < 0 or (hasattr(self, '__len__') and ans >= len(self)): + raise IndexError('index out of range: ' + repr(i)) + return ans + + def rchild(self, i): + """ + Index of right child of C{i}. + """ + ans = 2 * i + 2 + if i < 0 or (hasattr(self, '__len__') and ans >= len(self)): + raise IndexError('index out of range: ' + repr(i)) + return ans + + def sibling(self, i): + """ + Index of sibling of C{i}. + """ + parent = self.parent(i) + if self.lchild(parent) == i: + return self.rchild(parent) + else: + return self.lchild(parent) + + def needed(self, i): + """ + Return a list of nodes that are necessary for the hash chain. + """ + if i < 0 or i >= len(self): + raise IndexError('index out of range: ' + repr(i)) + needed = [] + here = i + while here != 0: + needed.append(self.sibling(here)) + here = self.parent(here) + return needed + + +class HashTree(CompleteBinaryTreeMixin, list): + """ + Compute Merkle hashes at any node in a complete binary tree. + + Tree is indexed like so:: + + + 0 + / \ + 1 2 + / \ / \ + 3 4 5 6 + / \ / \ / \ / \ + 7 8 9 10 11 12 13 14 <- List passed to constructor. + + """ + def __init__(self, L): + """ + Create complete binary tree from list of hash strings. + + The list is augmented by hashes so its length is a power of 2, and + then this is used as the bottom row of the hash tree. + + The augmenting is done so that if the augmented element is at + index C{i}, then its value is C{hash(bencode.bencode((i, '')))}. + """ + # Augment the list. + start = len(L) + end = roundup_pow2(len(L)) + L = L + [None] * (end - start) + for i in range(start, end): + L[i] = hash(bencode.bencode((i, ''))) + # Form each row of the tree. + rows = [L] + while len(rows[-1]) != 1: + last = rows[-1] + rows += [[hash(last[2*i] + last[2*i+1]) for i in xrange(len(last)//2)]] + # Flatten the list of rows into a single list. + rows.reverse() + self[:] = sum(rows, []) + + +class BlockFile: + """ + Reads and writes blocks of data to a binary file. + + It is assumed that the binary file does not change in size. + + @ivar file_name: Full path to file. + @ivar file_size: Size of file in bytes. + @ivar block_size: Size of each block. + """ + def __init__(self, file_name, mode, block_size, file_size=None): + """ + Initialize block reader or writer on given file name. + + If mode is 'r', the file must already exist and it is opened for + reading only. If mode is 'w', the file will be created with size + C{file_size} if it does not exist, and it is opened for reading + and writing. + + Note that C{file_size} is ignored if the file already exists. + """ + self.mode = mode + self.file_name = os.path.abspath(file_name) + assert self.mode in ['r', 'w'] + + if mode == 'r': + f = open(self.file_name, 'rb') + f.close() + + # Create file if it doesn't exist. + created = False + if mode == 'w' and not os.path.exists(self.file_name): + created = True + buf = ' ' * 1024 + f = open(self.file_name, 'wb') + for i in xrange(file_size // len(buf)): + f.write(buf) + f.write(' ' * (file_size % len(buf))) + f.close() + + self.file_size = os.stat(self.file_name).st_size + if created: + assert self.file_size == file_size + self.block_size = block_size + self.__block_count = self.file_size // self.block_size + if self.file_size % self.block_size == 0: + self.last_block_size = self.block_size + else: + self.last_block_size = self.file_size % self.block_size + self.__block_count += 1 + + def __getitem__(self, i): + """ + Get block i. + """ + if i < 0 or i >= len(self): + raise IndexError('block index out of range: ' + repr(i)) + f = open(self.file_name, 'rb') + try: + f.seek(i * self.block_size) + ans = f.read(self.block_size) + finally: + f.close() + return ans + + def __setitem__(self, i, s): + """ + Set block i. + """ + if self.mode != 'w': + raise ValueError('file opened for reading only') + if i < 0 or i >= len(self): + raise IndexError('block index out of range: ' + repr(i)) + if i < len(self) - 1: + if len(s) != self.block_size: + raise ValueError('length of value must equal block_size') + else: + if len(s) != self.last_block_size: + raise ValueError('length of value must equal last_block_size') + f = open(self.file_name, 'rb+') + try: + f.seek(i * self.block_size) + f.write(s) + finally: + f.close() + + def __len__(self): + """ + Get number of blocks. + """ + return int(self.__block_count) + + +class MetaFile(CompleteBinaryTreeMixin): + """ + A L{HashTree} stored on disk, with a timestamp. + + The list of hashes can be accessed using subscripting and + C{__len__}, in the same manner as for L{HashTree}. + + Note that the constructor takes the entire list associated with + the L{HashTree}, not just the bottom row of the tree. + + @ivar meta_name: Full path to metafile. + """ + def __init__(self, meta_name, mode, L=None): + """ + Open an existing meta-file for reading or writing. + + If C{mode} is 'r', the meta-file must already exist and it is + opened for reading only, and the list C{L} is ignored. If C{mode} + is 'w', the file will be created if it does not exist (from the + list of hashes given in C{L}), and it is opened for reading and + writing. + """ + self.meta_name = os.path.abspath(meta_name) + self.mode = mode + assert self.mode in ['r', 'w'] + + # A timestamp is stored at index 0. The MetaFile instance + # offsets all indices passed to __getitem__, __setitem__ by + # this offset, and pretends it has length equal to + # self.sublength. + self.offset = 1 + + if self.mode == 'w': + suggested_length = len(hash('')) * (len(L)+self.offset) + else: + suggested_length = None + + created = False + if self.mode == 'w' and not os.path.exists(self.meta_name): + created = True + + self.block_file = BlockFile(self.meta_name, self.mode, + len(hash('')), + suggested_length) + self.sublength = len(self.block_file) - self.offset + + if created: + for i in xrange(len(L)): + self.block_file[i + self.offset] = L[i] + + def __getitem__(self, i): + if i < 0 or i >= self.sublength: + raise IndexError('bad meta-file block index') + return self.block_file[i + self.offset] + + def __setitem__(self, i, value): + if i < 0 or i >= self.sublength: + raise IndexError('bad meta-file block index') + self.block_file[i + self.offset] = value + + def __len__(self): + return self.sublength + + def set_timestamp(self, file_name): + """ + Set meta file's timestamp equal to the timestamp for C{file_name}. + """ + st = os.stat(file_name) + timestamp = bencode.bencode((st.st_size, st.st_mtime)) + self.block_file[0] = sha.new(timestamp).digest() + + def check_timestamp(self, file_name): + """ + True if meta file's timestamp equals timestamp for C{file_name}. + """ + st = os.stat(file_name) + timestamp = bencode.bencode((st.st_size, st.st_mtime)) + return self.block_file[0] == sha.new(timestamp).digest() + + +class CompleteChunkFile(BlockFile): + """ + Reads chunks from a fully-downloaded file. + + A chunk C{i} is created from block C{i}. Block C{i} is unencoded + data read from the file by the L{BlockFile}. Chunk C{i} is + an encoded string created from block C{i}. + + Chunks can be read using list subscripting. The total number of + chunks (equals the total number of blocks) is given by L{__len__}. + + @ivar file_name: Full path to file. + @ivar file_size: Size of file in bytes. + @ivar file_hash: Hash of file. + @ivar meta_name: Full path to metafile, or C{None}. + @ivar tree: L{HashTree} or L{MetaFile} instance for the file. + One can extract a hash from any node in the hash + tree. + """ + + def __init__(self, file_name, meta_name=None, callback=None): + """ + Initialize reader on the given file name. + + The entire file will be read and the hash will be computed from + the file. This may take a long time, so C{callback()} is called + frequently during this process. This allows you to reduce CPU + usage if you wish. + + The C{meta_name} argument is optional. If it is specified, then the + hashes for C{file_name} will be stored under the file + C{meta_name}. If a C{CompleteChunkFile} is created on the same + file and metafile in the future, then the hashes will not need to + be recomputed and the constructor will return instantly. The + metafile contains a file and date stamp, so that if the file stored + in C{file_name} is modified, then the hashes will be recomputed. + """ + BlockFile.__init__(self, file_name, 'r', block_size=65536) + + # Whether we need to compute the hash tree + compute_tree = False + + self.meta_name = meta_name + if self.meta_name != None: + self.meta_name = os.path.abspath(self.meta_name) + self.meta = None + if self.meta_name == None: + compute_tree = True + else: + try: + meta = MetaFile(self.meta_name, 'r') + assert meta.check_timestamp(self.file_name) + except (IOError, AssertionError): + compute_tree = True + + # Compute the hash tree if needed. + if compute_tree: + chunk_hashes = [None] * len(self) + for i in xrange(len(self)): + triple = (self.file_size, i, BlockFile.__getitem__(self, i)) + chunk_hashes[i] = hash(bencode.bencode(triple)) + if callback: + callback() + self.tree = HashTree(chunk_hashes) + del chunk_hashes + + # If a meta-file was given, make self.tree be a MetaFile instance. + if self.meta_name != None: + if compute_tree: + # Did we compute the hash tree? Then store it to disk. + self.tree = MetaFile(self.meta_name, 'w', self.tree) + # Update its timestamp to be consistent with the file we + # just hashed. + self.tree.set_timestamp(self.file_name) + else: + # Read existing file from disk. + self.tree = MetaFile(self.meta_name, 'r') + + self.file_hash = self.tree[0] + + def __getitem__(self, i): + """ + Get chunk C{i}. + + Raises C{ValueError} if the file's contents changed since the + CompleteFileChunkReader was instantiated. + """ + return encode_chunk(BlockFile.__getitem__(self, i), i, + self.file_size, self.tree) + + +def encode_chunk(block, index, file_size, tree): + """ + Encode a chunk. + + Given a block at index C{index} in a file with size C{file_size}, + and a L{HashTree} or L{MetaFile} instance C{tree}, computes and + returns a chunk string for the given block. + + The C{tree} argument needs to have correct hashes only at certain + indices. Check out the code for details. In any case, if a hash + is wrong an exception will be raised. + """ + block_count = (len(tree) + 1) // 2 + if index < 0 or index >= block_count: + raise IndexError('block index out of range: ' + repr(index)) + + suffix = bencode.bencode((file_size, index, block)) + current = len(tree) - block_count + index + prefix = [] + while current > 0: + sibling = tree.sibling(current) + prefix += [tree[current], tree[sibling]] + current = tree.parent(current) + prefix = ''.join(prefix) + + # Encode the chunk + chunk = bencode.bencode((prefix, suffix)) + + # Check to make sure it decodes properly. + decode_chunk(chunk, file_size, tree) + return chunk + + +def decode_chunk(chunk, file_size, tree): + """ + Decode a chunk. + + Given file with size C{file_size} and a L{HashTree} or L{MetaFile} + instance C{tree}, return C{(index, block, tree_items)}. Here + C{index} is the block index where string C{block} should be placed + in the file. Also C{tree_items} is a dict mapping indices within + the L{HashTree} or L{MetaFile} tree object associated with the + given file to the corresponding hashes at those indices. These + have been verified against the file's hash, so it is known that + they are correct. + + Raises C{ValueError} if chunk verification fails. + """ + file_hash = tree[0] + block_count = (len(tree) + 1) // 2 + try: + # Decode the chunk + try: + (prefix, suffix) = bencode.bdecode(chunk) + except: + raise AssertionError() + + assert isinstance(prefix, str) + assert isinstance(suffix, str) + + # Verify the suffix against the hashes in the prefix. + hash_len = len(hash('')) + L = [prefix[hash_len*i:hash_len*(i+1)] for i in range(len(prefix)//hash_len)] + L += [file_hash] + assert L[0] == hash(suffix) + branches = [] + for i in range(0, len(L)-1, 2): + if hash(L[i] + L[i+1]) == L[i+2]: + branches += [0] + elif hash(L[i+1] + L[i]) == L[i+2]: + branches += [1] + else: + raise AssertionError() + + # Decode the suffix + try: + (claim_file_size, claim_index, block) = bencode.bdecode(suffix) + except: + raise AssertionError() + + assert isinstance(claim_file_size, int) or isinstance(claim_file_size, long) + assert isinstance(claim_index, int) or isinstance(claim_index, long) + assert isinstance(block, str) + + assert file_size == claim_file_size + + # Compute the index of the block, and check it. + found_index = sum([branches[i]*2**i for i in range(len(branches))]) + assert found_index == claim_index + + # Now fill in the tree_items dict. + tree_items = {} + current = (len(tree) - block_count) + found_index + i = 0 + while current > 0 and i + 1 < len(L): + tree_items[current] = L[i] + # Next item is our sibling. + tree_items[tree.sibling(current)] = L[i+1] + i += 2 + current = tree.parent(current) + + return (found_index, block, tree_items) + except AssertionError: + raise ValueError('corrupt chunk') + + +class PartialChunkFile(BlockFile): + """ + Reads and writes chunks to a partially downloaded file. + + @ivar file_name: Full path to file. + @ivar file_size: Size of file in bytes. + @ivar file_hash: Hash of file. + @ivar meta_name: Full path to metafile. + @ivar tree: L{MetaFile} instance for the file. + The hashes in this hash tree are valid only for + nodes that we have been sent hashes for. + """ + def __init__(self, file_name, meta_name, file_hash=None, file_size=None): + """ + Initialize reader/writer for the given file name and metafile name. + + If neither C{file_name} nor C{meta_file} exist, then both are + created. The C{file_hash} and C{file_size} arguments are used to + initialize the two files. + + If both C{file_name} and C{meta_file} exist, then the hash and + file size arguments are ignored, and those values are instead read + from the files. + + If one file exists and the other does not, an C{IOError} is raised. + """ + self.meta_name = os.path.abspath(meta_name) + meta_exists = os.path.exists(self.meta_name) + file_exists = os.path.exists(os.path.abspath(file_name)) + + BlockFile.__init__(self, os.path.abspath(file_name), 'w', + BLOCK_SIZE, file_size) + + if file_exists and not meta_exists: + raise IOError('metafile ' + repr(self.meta_name) + + ' missing for file ' + repr(self.file_name)) + if meta_exists and not file_exists: + raise IOError('file ' + repr(self.file_name) + + ' missing for metafile ' + repr(self.meta_name)) + tree_count = 2 * roundup_pow2(len(self)) - 1 + self.tree = MetaFile(self.meta_name, 'w', [hash('')] * tree_count) + + if not meta_exists and not file_exists: + self.tree[0] = file_hash + + self.file_hash = self.tree[0] + + def __getitem__(self, i): + """ + Get chunk C{i}. + + Raises C{ValueError} if chunk has not yet been downloaded or is + corrupted. + """ + return encode_chunk(BlockFile.__getitem__(self, i), i, + self.file_size, self.tree) + + def __setitem__(self, i, chunk): + """ + Set chunk C{i}. + + Raises C{ValueError} if the chunk is invalid. + """ + (index, block, tree_items) = decode_chunk(chunk, + self.file_size, self.tree) + if index != i: + raise ValueError('incorrect index for chunk') + BlockFile.__setitem__(self, index, block) + for (tree_index, tree_value) in tree_items.items(): + self.tree[tree_index] = tree_value + + +def test(filename1='temp-out', metaname1='temp-out.meta', + filename2='temp-out2', metaname2='temp-out2.meta'): + """ + Unit tests. + """ + print 'Testing:' + + import random + ntests = 100 + max_file_size = 200000 + + # Test CompleteChunkFile. + + if os.path.exists(metaname1): + os.remove(metaname1) + + for i in range(ntests): + fsize = random.randrange(max_file_size) + # Make some random string of size 'fsize' to go in the file. + s = ''.join([sha.new(str(j)).digest() for j in range(fsize//20+1)]) + assert len(s) >= fsize + s = s[:fsize] + f = open(filename1, 'wb') + f.write(s) + f.close() + C = CompleteChunkFile(filename1) + for j in range(len(C)): + C[j] + C = CompleteChunkFile(filename1, metaname1) + for j in range(len(C)): + C[j] + C = CompleteChunkFile(filename1, metaname1) + for j in range(len(C)): + C[j] + os.remove(metaname1) + + os.remove(filename1) + + print ' CompleteChunkFile: OK' + + # Test PartialChunkFile + + for i in range(ntests): + fsize = random.randrange(max_file_size) + # Make some random string of size 'fsize' to go in the file. + s = ''.join([sha.new(str(j)).digest() for j in range(fsize//20+1)]) + assert len(s) >= fsize + s = s[:fsize] + f = open(filename1, 'wb') + f.write(s) + f.close() + C1 = CompleteChunkFile(filename1) + if os.path.exists(filename2): + os.remove(filename2) + + if os.path.exists(metaname2): + os.remove(metaname2) + C2 = PartialChunkFile(filename2, metaname2, C1.file_hash, C1.file_size) + assert len(C1) == len(C2) + assert C2.tree[0] == C1.tree[0] + for j in range(len(C2)): + try: + C2[j] + ok = False + except ValueError: + ok = True + if not ok: + raise AssertionError() + for j in range(len(C2)//2): + k = random.randrange(len(C2)) + if len(C1) > 1: + assert C1[k] != C1[(k+1)%len(C1)] + try: + C2[k] = C1[(k+1)%len(C1)] + ok = False + except ValueError: + ok = True + if not ok: + raise AssertionError() + C2[k] = C1[k] + assert C2[k] == C1[k] + for j in range(len(C2)): + C2[j] = C1[j] + assert C2[j] == C1[j] + + os.remove(filename1) + os.remove(filename2) + os.remove(metaname2) + + print ' PartialChunkFile: OK' + + +if __name__ == '__main__': + test() diff --git a/src/allmydata/client.py b/src/allmydata/client.py new file mode 100644 index 00000000..360cdc93 --- /dev/null +++ b/src/allmydata/client.py @@ -0,0 +1,149 @@ + +import os, sha +from foolscap import Referenceable +from twisted.application import service +from twisted.python import log +from zope.interface import implements +from allmydata.interfaces import RIClient +from allmydata import node + +from twisted.internet import defer + +from allmydata.util import idlib +from allmydata.storageserver import StorageServer +from allmydata.upload import Uploader +from allmydata.download import Downloader +from allmydata.vdrive import VDrive +from allmydata.webish import WebishServer + +class Client(node.Node, Referenceable): + implements(RIClient) + CERTFILE = "client.pem" + PORTNUMFILE = "client.port" + STOREDIR = 'storage' + NODETYPE = "client" + WEBPORTFILE = "webport" + QUEEN_PBURL_FILE = "roster_pburl" + + def __init__(self, basedir="."): + node.Node.__init__(self, basedir) + self.queen = None # self.queen is either None or a RemoteReference + self.all_peers = set() + self.connections = {} + self.add_service(StorageServer(os.path.join(basedir, self.STOREDIR))) + self.add_service(Uploader()) + self.add_service(Downloader()) + self.add_service(VDrive()) + WEBPORTFILE = os.path.join(self.basedir, self.WEBPORTFILE) + if os.path.exists(WEBPORTFILE): + f = open(WEBPORTFILE, "r") + webport = f.read() # strports string + f.close() + self.add_service(WebishServer(webport)) + self.queen_pburl = None + QUEEN_PBURL_FILE = os.path.join(self.basedir, self.QUEEN_PBURL_FILE) + if os.path.exists(QUEEN_PBURL_FILE): + f = open(QUEEN_PBURL_FILE, "r") + self.queen_pburl = f.read().strip() + f.close() + self.queen_connector = None + + def tub_ready(self): + self.my_pburl = self.tub.registerReference(self) + self.maybe_connect_to_queen() + + def set_queen_pburl(self, queen_pburl): + self.queen_pburl = queen_pburl + self.maybe_connect_to_queen() + + def maybe_connect_to_queen(self): + if not self.running: + return + if not self.my_pburl: + return + if self.queen_connector: + return + if not self.queen_pburl: + self.log("no queen_pburl, cannot connect") + return + self.queen_connector = self.tub.connectTo(self.queen_pburl, + self._got_queen) + + def stopService(self): + if self.queen_connector: + self.queen_connector.stopConnecting() + self.queen_connector = None + return service.MultiService.stopService(self) + + def _got_queen(self, queen): + self.log("connected to queen") + self.queen = queen + queen.notifyOnDisconnect(self._lost_queen) + d = queen.callRemote("hello", + nodeid=self.nodeid, + node=self, + pburl=self.my_pburl) + d.addCallback(self._got_vdrive_root) + + def _got_vdrive_root(self, root): + self.getServiceNamed("vdrive").set_root(root) + if "webish" in self.namedServices: + self.getServiceNamed("webish").set_root_dirnode(root) + + def _lost_queen(self): + self.log("lost connection to queen") + self.queen = None + + def remote_get_service(self, name): + # TODO: 'vdrive' should not be public in the medium term + return self.getServiceNamed(name) + + def remote_add_peers(self, new_peers): + for nodeid, pburl in new_peers: + if nodeid == self.nodeid: + continue + self.log("adding peer %s" % idlib.b2a(nodeid)) + if nodeid in self.all_peers: + self.log("weird, I already had an entry for them") + return + self.all_peers.add(nodeid) + if nodeid not in self.connections: + d = self.tub.getReference(pburl) + def _got_reference(ref, which_nodeid): + self.log("connected to %s" % idlib.b2a(which_nodeid)) + if which_nodeid in self.all_peers: + self.connections[which_nodeid] = ref + else: + log.msg(" ignoring it because we no longer want to talk to them") + d.addCallback(_got_reference, nodeid) + + def remote_lost_peers(self, lost_peers): + for nodeid in lost_peers: + self.log("lost peer %s" % idlib.b2a(nodeid)) + if nodeid in self.all_peers: + self.all_peers.remove(nodeid) + else: + self.log("weird, I didn't have an entry for them") + if nodeid in self.connections: + del self.connections[nodeid] + + def get_remote_service(self, nodeid, servicename): + if nodeid not in self.connections: + return defer.fail(IndexError("no connection to that peer")) + peer = self.connections[nodeid] + d = peer.callRemote("get_service", name=servicename) + return d + + + def permute_peerids(self, key, max_count=None): + # TODO: eventually reduce memory consumption by doing an insertion + # sort of at most max_count elements + results = [] + for nodeid in self.all_peers: + permuted = sha.new(key + nodeid).digest() + results.append((permuted, nodeid)) + results.sort() + results = [r[1] for r in results] + if max_count is None: + return results + return results[:max_count] diff --git a/src/allmydata/debugshell.py b/src/allmydata/debugshell.py new file mode 100644 index 00000000..130c9099 --- /dev/null +++ b/src/allmydata/debugshell.py @@ -0,0 +1,17 @@ +import os + +def get_random_bucket_on(nodeid, size=200): + d = app.get_remote_service(nodeid, 'storageserver') + def get_bucket(rss): + return rss.callRemote('allocate_bucket', + verifierid=os.urandom(20), + bucket_num=26, + size=size, + leaser=app.tub.tubID, + ) + d.addCallback(get_bucket) + return d + +def write_to_bucket(bucket, bytes=100): + return bucket.callRemote('write', data=os.urandom(bytes)) + diff --git a/src/allmydata/download.py b/src/allmydata/download.py new file mode 100644 index 00000000..a344d039 --- /dev/null +++ b/src/allmydata/download.py @@ -0,0 +1,229 @@ + +import os +from zope.interface import Interface, implements +from twisted.python import failure, log +from twisted.internet import defer +from twisted.application import service + +from allmydata.util import idlib +from allmydata import encode + +class NotEnoughPeersError(Exception): + pass + +class HaveAllPeersError(Exception): + # we use this to jump out of the loop + pass + +class FileDownloader: + debug = False + + def __init__(self, peer, verifierid): + self._peer = peer + assert isinstance(verifierid, str) + self._verifierid = verifierid + + def set_download_target(self, target): + self._target = target + self._target.register_canceller(self._cancel) + + def _cancel(self): + pass + + def make_decoder(self): + n = self._shares = 4 + k = self._desired_shares = 2 + self._target.open() + self._decoder = encode.Decoder(self._target, k, n, + self._verifierid) + + def start(self): + log.msg("starting download") + if self.debug: + print "starting download" + # first step: who should we download from? + + # maybe limit max_peers to 2*len(self.shares), to reduce memory + # footprint + max_peers = None + + self.permuted = self._peer.permute_peerids(self._verifierid, max_peers) + for p in self.permuted: + assert isinstance(p, str) + self.landlords = [] # list of (peerid, bucket_num, remotebucket) + + d = defer.maybeDeferred(self._check_next_peer) + d.addCallback(self._got_all_peers) + return d + + def _check_next_peer(self): + if len(self.permuted) == 0: + # there are no more to check + raise NotEnoughPeersError + peerid = self.permuted.pop(0) + + d = self._peer.get_remote_service(peerid, "storageserver") + def _got_peer(service): + bucket_num = len(self.landlords) + if self.debug: print "asking %s" % idlib.b2a(peerid) + d2 = service.callRemote("get_buckets", verifierid=self._verifierid) + def _got_response(buckets): + if buckets: + bucket_nums = [num for (num,bucket) in buckets] + if self.debug: + print " peerid %s has buckets %s" % (idlib.b2a(peerid), + bucket_nums) + + self.landlords.append( (peerid, buckets) ) + if len(self.landlords) >= self._desired_shares: + if self.debug: print " we're done!" + raise HaveAllPeersError + # otherwise we fall through to search more peers + d2.addCallback(_got_response) + return d2 + d.addCallback(_got_peer) + + def _done_with_peer(res): + if self.debug: print "done with peer %s:" % idlib.b2a(peerid) + if isinstance(res, failure.Failure): + if res.check(HaveAllPeersError): + if self.debug: print " all done" + # we're done! + return + if res.check(IndexError): + if self.debug: print " no connection" + else: + if self.debug: print " other error:", res + else: + if self.debug: print " they had data for us" + # we get here for either good peers (when we still need more), or + # after checking a bad peer (and thus still need more). So now we + # need to grab a new peer. + return self._check_next_peer() + d.addBoth(_done_with_peer) + return d + + def _got_all_peers(self, res): + all_buckets = [] + for peerid, buckets in self.landlords: + all_buckets.extend(buckets) + d = self._decoder.start(all_buckets) + def _done(res): + self._target.close() + return self._target.finish() + def _fail(res): + self._target.fail() + return res + d.addCallbacks(_done, _fail) + return d + +def netstring(s): + return "%d:%s," % (len(s), s) + +class IDownloadTarget(Interface): + def open(): + """Called before any calls to write() or close().""" + def write(data): + pass + def close(): + pass + def fail(): + """fail() is called to indicate that the download has failed. No + further methods will be invoked on the IDownloadTarget after fail().""" + def register_canceller(cb): + """The FileDownloader uses this to register a no-argument function + that the target can call to cancel the download. Once this canceller + is invoked, no further calls to write() or close() will be made.""" + def finish(self): + """When the FileDownloader is done, this finish() function will be + called. Whatever it returns will be returned to the invoker of + Downloader.download. + """ + +class FileName: + implements(IDownloadTarget) + def __init__(self, filename): + self._filename = filename + def open(self): + self.f = open(self._filename, "wb") + return self.f + def write(self, data): + self.f.write(data) + def close(self): + self.f.close() + def fail(self): + self.f.close() + os.unlink(self._filename) + def register_canceller(self, cb): + pass # we won't use it + def finish(self): + pass + +class Data: + implements(IDownloadTarget) + def __init__(self): + self._data = [] + def open(self): + pass + def write(self, data): + self._data.append(data) + def close(self): + self.data = "".join(self._data) + del self._data + def fail(self): + del self._data + def register_canceller(self, cb): + pass # we won't use it + def finish(self): + return self.data + +class FileHandle: + implements(IDownloadTarget) + def __init__(self, filehandle): + self._filehandle = filehandle + def open(self): + pass + def write(self, data): + self._filehandle.write(data) + def close(self): + # the originator of the filehandle reserves the right to close it + pass + def fail(self): + pass + def register_canceller(self, cb): + pass + def finish(self): + pass + +class IDownloader(Interface): + def download(verifierid, target): + pass + +class Downloader(service.MultiService): + """I am a service that allows file downloading. + """ + implements(IDownloader) + name = "downloader" + + def download(self, verifierid, t): + assert self.parent + assert self.running + assert isinstance(verifierid, str) + t = IDownloadTarget(t) + assert t.write + assert t.close + dl = FileDownloader(self.parent, verifierid) + dl.set_download_target(t) + dl.make_decoder() + d = dl.start() + return d + + # utility functions + def download_to_data(self, verifierid): + return self.download(verifierid, Data()) + def download_to_filename(self, verifierid, filename): + return self.download(verifierid, FileName(filename)) + def download_to_filehandle(self, verifierid, filehandle): + return self.download(verifierid, FileHandle(filehandle)) + + diff --git a/src/allmydata/encode.py b/src/allmydata/encode.py new file mode 100644 index 00000000..ea54fbd2 --- /dev/null +++ b/src/allmydata/encode.py @@ -0,0 +1,50 @@ +from twisted.internet import defer +import sha +from allmydata.util import idlib + +def netstring(s): + return "%d:%s," % (len(s), s) + +class Encoder(object): + def __init__(self, infile, m): + self.infile = infile + self.k = 2 + self.m = m + + def do_upload(self, landlords): + dl = [] + data = self.infile.read() + for (peerid, bucket_num, remotebucket) in landlords: + dl.append(remotebucket.callRemote('write', data)) + dl.append(remotebucket.callRemote('close')) + + return defer.DeferredList(dl) + +class Decoder(object): + def __init__(self, outfile, k, m, verifierid): + self.outfile = outfile + self.k = 2 + self.m = m + self._verifierid = verifierid + + def start(self, buckets): + assert len(buckets) >= self.k + dl = [] + for bucketnum, bucket in buckets[:self.k]: + d = bucket.callRemote("read") + dl.append(d) + d2 = defer.DeferredList(dl) + d2.addCallback(self._got_all_data) + return d2 + + def _got_all_data(self, resultslist): + shares = [results for success,results in resultslist if success] + assert len(shares) >= self.k + # here's where the Reed-Solomon magic takes place + self.outfile.write(shares[0]) + hasher = sha.new(netstring("allmydata_v1_verifierid")) + hasher.update(shares[0]) + vid = hasher.digest() + if self._verifierid: + assert self._verifierid == vid, "%s != %s" % (idlib.b2a(self._verifierid), idlib.b2a(vid)) + diff --git a/src/allmydata/encode_new.py b/src/allmydata/encode_new.py new file mode 100644 index 00000000..f2ff0ad1 --- /dev/null +++ b/src/allmydata/encode_new.py @@ -0,0 +1,206 @@ +#! /usr/bin/python + +import math +from twisted.internet import defer +from allmydata.chunk import HashTree +from Crypto.Cipher import AES +import sha + +def hash(data): + return sha.new(data).digest() + +""" + +The goal of the encoder is to turn the original file into a series of +'shares'. Each share is going to a 'shareholder' (nominally each shareholder +is a different host, but for small meshes there may be overlap). The number +of shares is chosen to hit our reliability goals (more shares on more +machines means more reliability), and is limited by overhead (proportional to +numshares or log(numshares)) and the encoding technology in use (Reed-Solomon +only permits 256 shares total). It is also constrained by the amount of data +we want to send to each host. For estimating purposes, think of 100 shares +out of which we need 25 to reconstruct the file. + +The encoder starts by cutting the original file into segments. All segments +except the last are of equal size. The segment size is chosen to constrain +the memory footprint (which will probably vary between 1x and 4x segment +size) and to constrain the overhead (which will be proportional to either the +number of segments or log(number of segments)). + + +Each segment (A,B,C) is read into memory, encrypted, and encoded into +subshares. The 'share' (say, share #1) that makes it out to a host is a +collection of these subshares (subshare A1, B1, C1), plus some hash-tree +information necessary to validate the data upon retrieval. Only one segment +is handled at a time: all subshares for segment A are delivered before any +work is begun on segment B. + +As subshares are created, we retain the hash of each one. The list of +subshare hashes for a single share (say, hash(A1), hash(B1), hash(C1)) is +used to form the base of a Merkle hash tree for that share (hashtrees[1]). +This hash tree has one terminal leaf per subshare. The complete subshare hash +tree is sent to the shareholder after all the data has been sent. At +retrieval time, the decoder will ask for specific pieces of this tree before +asking for subshares, whichever it needs to validate those subshares. + +[TODO: we don't really need to generate this whole subshare hash tree +ourselves. It would be sufficient to have the shareholder generate it and +just tell us the root. This gives us an extra level of validation on the +transfer, though, and it is relatively cheap to compute.] + +Each of these subshare hash trees has a root hash. The collection of these +root hashes for all shares are collected into the 'share hash tree', which +has one terminal leaf per share. After sending the subshares and the complete +subshare hash tree to each shareholder, we send them the portion of the share +hash tree that is necessary to validate their share. The root of the share +hash tree is put into the URI. + +""" + + + + +class Encoder(object): + + def setup(self, infile): + self.infile = infile + infile.seek(0, 2) + self.file_size = infile.tell() + infile.seek(0, 0) + fsize = 1.0 * self.file_size + self.segment_size = 1024 + self.num_segments = int(math.ceil(fsize / self.segment_size)) + + self.num_shares = 100 + self.share_size = self.file_size / 25 + + def get_reservation_size(self): + self.num_shares = 100 + self.share_size = self.file_size / 25 + overhead = self.compute_overhead() + return self.share_size + overhead + + def setup_encryption(self): + self.key = "\x00"*16 + self.cryptor = AES.new(key=self.key, mode=AES.MODE_CTR, + counterstart="\x00"*16) + self.segment_num = 0 + self.subshare_hashes = [[]] * self.num_shares + # subshare_hashes[i] is a list that will be accumulated and then send + # to landlord[i]. This list contains a hash of each segment_share + # that we sent to that landlord. + self.share_root_hashes = [None] * self.num_shares + + def start(self): + self.setup_encryption() + d = defer.succeed(None) + for i in range(self.num_segments): + d.addCallback(lambda res: self.do_segment(i)) + d.addCallback(lambda res: self.send_all_subshare_hash_trees()) + d.addCallback(lambda res: self.send_all_share_hash_trees()) + d.addCallback(lambda res: self.close_all_shareholders()) + d.addCallback(lambda res: self.done()) + return d + + def encode_segment(self, crypttext): + shares = [crypttext] * self.num_shares + return shares + + def do_segment(self, segnum): + segment_plaintext = self.infile.read(self.segment_size) + segment_crypttext = self.cryptor.encrypt(segment_plaintext) + del segment_plaintext + subshares_for_this_segment = self.encode_segment(segment_crypttext) + del segment_crypttext + dl = [] + for share_num,subshare in enumerate(subshares_for_this_segment): + d = self.send_subshare(share_num, self.segment_num, subshare) + dl.append(d) + self.subshare_hashes[share_num].append(hash(subshare)) + self.segment_num += 1 + return defer.DeferredList(dl) + + def send_subshare(self, share_num, segment_num, subshare): + #if False: + # offset = hash_size + segment_num * segment_size + # return self.send(share_num, "write", subshare, offset) + return self.send(share_num, "put_subshare", segment_num, subshare) + + def send(self, share_num, methname, *args, **kwargs): + ll = self.landlords[share_num] + return ll.callRemote(methname, *args, **kwargs) + + def send_all_subshare_hash_trees(self): + dl = [] + for share_num,hashes in enumerate(self.subshare_hashes): + # hashes is a list of the hashes of all subshares that were sent + # to shareholder[share_num]. + dl.append(self.send_one_subshare_hash_tree(share_num, hashes)) + return defer.DeferredList(dl) + + def send_one_subshare_hash_tree(self, share_num, subshare_hashes): + t = HashTree(subshare_hashes) + all_hashes = list(t) + # all_hashes[0] is the root hash, == hash(ah[1]+ah[2]) + # all_hashes[1] is the left child, == hash(ah[3]+ah[4]) + # all_hashes[n] == hash(all_hashes[2*n+1] + all_hashes[2*n+2]) + self.share_root_hashes[share_num] = t[0] + ll = self.landlords[share_num] + if False: + block = "".join(all_hashes) + return ll.callRemote("write", block, offset=0) + return ll.callRemote("put_subshare_hashes", all_hashes) + + def send_all_share_hash_trees(self): + dl = [] + for h in self.share_root_hashes: + assert h + # create the share hash tree + t = HashTree(self.share_root_hashes) + # the root of this hash tree goes into our URI + self.root_hash = t[0] + # now send just the necessary pieces out to each shareholder + for i in range(self.num_shares): + needed_hash_indices = t.needed_for(i) + dl.append(self.send_one_share_hash_tree(i, needed_hash_indices)) + return defer.DeferredList(dl) + + def send_one_share_hash_tree(self, share_num, needed_hashes): + ll = self.landlords[share_num] + return ll.callRemote("put_share_hashes", needed_hashes) + + def close_all_shareholders(self): + dl = [] + for ll in self.landlords: + dl.append(ll.callRemote("close")) + return defer.DeferredList(dl) + + def done(self): + return self.root_hash + + +from foolscap import RemoteInterface +from foolscap.schema import ListOf, TupleOf, Nothing +_None = Nothing() + + +class RIStorageBucketWriter(RemoteInterface): + def put_subshare(segment_number=int, subshare=str): + return _None + def put_segment_hashes(all_hashes=ListOf(str)): + return _None + def put_share_hashes(needed_hashes=ListOf(TupleOf(int,str))): + return _None + #def write(data=str, offset=int): + # return _None +class RIStorageBucketReader(RemoteInterface): + def get_share_hashes(): + return ListOf(TupleOf(int,str)) + def get_segment_hashes(which=ListOf(int)): + return ListOf(str) + def get_subshare(segment_number=int): + return str + #def read(size=int, offset=int): + # return str + +"figleaf doesn't like the last line of the file to be a comment" diff --git a/src/allmydata/filetable.py b/src/allmydata/filetable.py new file mode 100644 index 00000000..b52c367d --- /dev/null +++ b/src/allmydata/filetable.py @@ -0,0 +1,138 @@ + +import os, shutil +from zope.interface import implements +from foolscap import Referenceable +from allmydata.interfaces import RIMutableDirectoryNode +from twisted.application import service +from twisted.python import log + +class DeadDirectoryNodeError(Exception): + """The directory referenced by this node has been deleted.""" + +class BadDirectoryError(Exception): + """There was a problem with the directory being referenced.""" +class BadFileError(Exception): + """The file being referenced does not exist.""" + +class MutableDirectoryNode(Referenceable): + implements(RIMutableDirectoryNode) + + def __init__(self, basedir): + self._basedir = basedir + + def make_subnode(self, basedir): + return self.__class__(basedir) + + def validate_name(self, name): + if name == "." or name == ".." or "/" in name: + raise DeadDirectoryNodeError("bad filename component") + + # these are the public methods, available to anyone who holds a reference + + def list(self): + log.msg("Dir(%s).list" % self._basedir) + results = [] + if not os.path.isdir(self._basedir): + raise DeadDirectoryNodeError("This directory has been deleted") + for name in os.listdir(self._basedir): + absname = os.path.join(self._basedir, name) + if os.path.isdir(absname): + results.append( (name, self.make_subnode(absname)) ) + elif os.path.isfile(absname): + f = open(absname, "rb") + data = f.read() + f.close() + results.append( (name, data) ) + # anything else is ignored + return results + remote_list = list + + def get(self, name): + self.validate_name(name) + absname = os.path.join(self._basedir, name) + if os.path.isdir(absname): + return self.make_subnode(absname) + elif os.path.isfile(absname): + f = open(absname, "rb") + data = f.read() + f.close() + return data + else: + raise BadFileError("there is nothing named '%s' in this directory" + % name) + remote_get = get + + def add_directory(self, name): + self.validate_name(name) + absname = os.path.join(self._basedir, name) + if os.path.isdir(absname): + raise BadDirectoryError("the directory '%s' already exists" % name) + if os.path.exists(absname): + raise BadDirectoryError("the directory '%s' already exists " + "(but isn't a directory)" % name) + os.mkdir(absname) + return self.make_subnode(absname) + remote_add_directory = add_directory + + def add_file(self, name, data): + self.validate_name(name) + f = open(os.path.join(self._basedir, name), "wb") + f.write(data) + f.close() + remote_add_file = add_file + + def remove(self, name): + self.validate_name(name) + absname = os.path.join(self._basedir, name) + if os.path.isdir(absname): + shutil.rmtree(absname) + elif os.path.isfile(absname): + os.unlink(absname) + else: + raise BadFileError("Cannot delete non-existent file '%s'" % name) + remote_remove = remove + + +class GlobalVirtualDrive(service.MultiService): + name = "filetable" + VDRIVEDIR = "vdrive" + + def __init__(self, basedir="."): + service.MultiService.__init__(self) + vdrive_dir = os.path.join(basedir, self.VDRIVEDIR) + if not os.path.exists(vdrive_dir): + os.mkdir(vdrive_dir) + self._root = MutableDirectoryNode(vdrive_dir) + + def get_root(self): + return self._root + + +class Node: + pass + +class MutableFileNode(Node): + """I hold an SSK identifier for a mutable file. My 'contents' are + defined to be the most recent version of the SSK's payload that can + be found. This SSK identifier must be dereferenced to get the + contents.""" + pass +class ImmutableFileNode(Node): + """I hold a CHK identifier for an immutable file. I may have some + metadata as well: ctime, mtime, content-type, and filesize.""" + pass +class ImmutableDirectoryNode(Node): + """I hold a list of child nodes.""" + pass +class MutableDirectoryNode2(Node): + """I hold an SSK identifier for a mutable directory. When + dereferenced, I will have a list of child nodes.""" + pass + +# interesting feature ideas: +# pubsub for MutableDirectoryNode: get rapid notification of changes +# caused by someone else +# +# bind a local physical directory to the MutableDirectoryNode contents: +# each time the vdrive changes, update the local drive to match, and +# vice versa. diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py new file mode 100644 index 00000000..14d081e3 --- /dev/null +++ b/src/allmydata/interfaces.py @@ -0,0 +1,75 @@ + +from foolscap.schema import StringConstraint, ListOf, TupleOf, Any, Nothing +from foolscap import RemoteInterface + +Nodeid = StringConstraint(20) # binary format 20-byte SHA1 hash +PBURL = StringConstraint(150) +Verifierid = StringConstraint(20) +ShareData = StringConstraint(100000) +# these four are here because Foolscap does not yet support the kind of +# restriction I really want to apply to these. +RIClient_ = Any() +Referenceable_ = Any() +RIBucketWriter_ = Any() +RIBucketReader_ = Any() +RIMutableDirectoryNode_ = Any() +RIMutableFileNode_ = Any() + +class RIQueenRoster(RemoteInterface): + def hello(nodeid=Nodeid, node=RIClient_, pburl=PBURL): + return RIMutableDirectoryNode_ # the virtual drive root + +class RIClient(RemoteInterface): + def get_service(name=str): + return Referenceable_ + def add_peers(new_peers=ListOf(TupleOf(Nodeid, PBURL), maxLength=100)): + return Nothing() + def lost_peers(lost_peers=ListOf(Nodeid)): + return Nothing() + +class RIStorageServer(RemoteInterface): + def allocate_bucket(verifierid=Verifierid, bucket_num=int, size=int, + leaser=Nodeid, canary=Referenceable_): + # if the canary is lost before close(), the bucket is deleted + return RIBucketWriter_ + def get_buckets(verifierid=Verifierid): + return ListOf(TupleOf(int, RIBucketReader_)) + +class RIBucketWriter(RemoteInterface): + def write(data=ShareData): + return Nothing() + + def close(): + return Nothing() + + +class RIBucketReader(RemoteInterface): + def read(): + return ShareData + + +class RIMutableDirectoryNode(RemoteInterface): + def list(): + return ListOf( TupleOf(str, # name, relative to directory + (RIMutableDirectoryNode_, Verifierid)), + maxLength=100, + ) + + def get(name=str): + return (RIMutableDirectoryNode_, Verifierid) + + def add_directory(name=str): + return RIMutableDirectoryNode_ + + def add_file(name=str, data=Verifierid): + return Nothing() + + def remove(name=str): + return Nothing() + + # need more to move directories + +# TODO: figleaf gets confused when the last line of a file is a comment. I +# suspect an off-by-one error in the code that decides which lines are code +# and which are not. +pass diff --git a/src/allmydata/manhole.py b/src/allmydata/manhole.py new file mode 100644 index 00000000..c0858dc9 --- /dev/null +++ b/src/allmydata/manhole.py @@ -0,0 +1,278 @@ + +# this is adapted from my code in Buildbot -warner + +import os.path +import binascii, base64 +from twisted.python import log +from twisted.application import service, strports +from twisted.cred import checkers, portal +from twisted.conch import manhole, telnet, manhole_ssh, checkers as conchc +from twisted.conch.insults import insults +from twisted.internet import protocol + +from zope.interface import implements + +# makeTelnetProtocol and _TelnetRealm are for the TelnetManhole + +class makeTelnetProtocol: + # this curries the 'portal' argument into a later call to + # TelnetTransport() + def __init__(self, portal): + self.portal = portal + + def __call__(self): + auth = telnet.AuthenticatingTelnetProtocol + return telnet.TelnetTransport(auth, self.portal) + +class _TelnetRealm: + implements(portal.IRealm) + + def __init__(self, namespace_maker): + self.namespace_maker = namespace_maker + + def requestAvatar(self, avatarId, *interfaces): + if telnet.ITelnetProtocol in interfaces: + namespace = self.namespace_maker() + p = telnet.TelnetBootstrapProtocol(insults.ServerProtocol, + manhole.ColoredManhole, + namespace) + return (telnet.ITelnetProtocol, p, lambda: None) + raise NotImplementedError() + + +class chainedProtocolFactory: + # this curries the 'namespace' argument into a later call to + # chainedProtocolFactory() + def __init__(self, namespace): + self.namespace = namespace + + def __call__(self): + return insults.ServerProtocol(manhole.ColoredManhole, self.namespace) + +class AuthorizedKeysChecker(conchc.SSHPublicKeyDatabase): + """Accept connections using SSH keys from a given file. + + SSHPublicKeyDatabase takes the username that the prospective client has + requested and attempts to get a ~/.ssh/authorized_keys file for that + username. This requires root access, so it isn't as useful as you'd + like. + + Instead, this subclass looks for keys in a single file, given as an + argument. This file is typically kept in the buildmaster's basedir. The + file should have 'ssh-dss ....' lines in it, just like authorized_keys. + """ + + def __init__(self, authorized_keys_file): + self.authorized_keys_file = os.path.expanduser(authorized_keys_file) + + def checkKey(self, credentials): + f = open(self.authorized_keys_file) + for l in f.readlines(): + l2 = l.split() + if len(l2) < 2: + continue + try: + if base64.decodestring(l2[1]) == credentials.blob: + return 1 + except binascii.Error: + continue + return 0 + +class ModifiedColoredManhole(manhole.ColoredManhole): + def connectionMade(self): + manhole.ColoredManhole.connectionMade(self) + # look in twisted.conch.recvline.RecvLine for hints + self.keyHandlers["\x08"] = self.handle_BACKSPACE + self.keyHandlers["\x15"] = self.handle_KILLLINE + self.keyHandlers["\x01"] = self.handle_HOME + self.keyHandlers["\x04"] = self.handle_DELETE + self.keyHandlers["\x05"] = self.handle_END + self.keyHandlers["\x0b"] = self.handle_KILLLINE # really kill-to-end + #self.keyHandlers["\xe2"] = self.handle_BACKWARDS_WORD # M-b + #self.keyHandlers["\xe6"] = self.handle_FORWARDS_WORD # M-f + + def handle_KILLLINE(self): + self.handle_END() + for i in range(len(self.lineBuffer)): + self.handle_BACKSPACE() + +class _BaseManhole(service.MultiService): + """This provides remote access to a python interpreter (a read/exec/print + loop) embedded in the buildmaster via an internal SSH server. This allows + detailed inspection of the buildmaster state. It is of most use to + buildbot developers. Connect to this by running an ssh client. + """ + + def __init__(self, port, checker, using_ssh=True): + """ + @type port: string or int + @param port: what port should the Manhole listen on? This is a + strports specification string, like 'tcp:12345' or + 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a + simple tcp port. + + @type checker: an object providing the + L{twisted.cred.checkers.ICredentialsChecker} interface + @param checker: if provided, this checker is used to authenticate the + client instead of using the username/password scheme. You must either + provide a username/password or a Checker. Some useful values are:: + import twisted.cred.checkers as credc + import twisted.conch.checkers as conchc + c = credc.AllowAnonymousAccess # completely open + c = credc.FilePasswordDB(passwd_filename) # file of name:passwd + c = conchc.UNIXPasswordDatabase # getpwnam() (probably /etc/passwd) + + @type using_ssh: bool + @param using_ssh: If True, accept SSH connections. If False, accept + regular unencrypted telnet connections. + """ + + # unfortunately, these don't work unless we're running as root + #c = credc.PluggableAuthenticationModulesChecker: PAM + #c = conchc.SSHPublicKeyDatabase() # ~/.ssh/authorized_keys + # and I can't get UNIXPasswordDatabase to work + + service.MultiService.__init__(self) + if type(port) is int: + port = "tcp:%d" % port + self.port = port # for comparison later + self.checker = checker # to maybe compare later + + def makeNamespace(): + # close over 'self' so we can get access to .parent later + from allmydata import debugshell + debugshell.app = self.parent # make client/queen accesible via 'app' + namespace = {} + for sym in dir(debugshell): + if sym.startswith('__') and sym.endswith('__'): + continue + namespace[sym] = getattr(debugshell, sym) + return namespace + + def makeProtocol(): + namespace = makeNamespace() + p = insults.ServerProtocol(ModifiedColoredManhole, namespace) + return p + + self.using_ssh = using_ssh + if using_ssh: + r = manhole_ssh.TerminalRealm() + r.chainedProtocolFactory = makeProtocol + p = portal.Portal(r, [self.checker]) + f = manhole_ssh.ConchFactory(p) + else: + r = _TelnetRealm(makeNamespace) + p = portal.Portal(r, [self.checker]) + f = protocol.ServerFactory() + f.protocol = makeTelnetProtocol(p) + s = strports.service(self.port, f) + s.setServiceParent(self) + + + def startService(self): + service.MultiService.startService(self) + if self.using_ssh: + via = "via SSH" + else: + via = "via telnet" + log.msg("Manhole listening %s on port %s" % (via, self.port)) + + +class TelnetManhole(_BaseManhole): + """This Manhole accepts unencrypted (telnet) connections, and requires a + username and password authorize access. You are encouraged to use the + encrypted ssh-based manhole classes instead.""" + + def __init__(self, port, username, password): + """ + @type port: string or int + @param port: what port should the Manhole listen on? This is a + strports specification string, like 'tcp:12345' or + 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a + simple tcp port. + + @param username: + @param password: username= and password= form a pair of strings to + use when authenticating the remote user. + """ + + self.username = username + self.password = password + + c = checkers.InMemoryUsernamePasswordDatabaseDontUse() + c.addUser(username, password) + + _BaseManhole.__init__(self, port, c, using_ssh=False) + +class PasswordManhole(_BaseManhole): + """This Manhole accepts encrypted (ssh) connections, and requires a + username and password to authorize access. + """ + + def __init__(self, port, username, password): + """ + @type port: string or int + @param port: what port should the Manhole listen on? This is a + strports specification string, like 'tcp:12345' or + 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a + simple tcp port. + + @param username: + @param password: username= and password= form a pair of strings to + use when authenticating the remote user. + """ + + self.username = username + self.password = password + + c = checkers.InMemoryUsernamePasswordDatabaseDontUse() + c.addUser(username, password) + + _BaseManhole.__init__(self, port, c) + +class AuthorizedKeysManhole(_BaseManhole): + """This Manhole accepts ssh connections, and requires that the + prospective client have an ssh private key that matches one of the public + keys in our authorized_keys file. It is created with the name of a file + that contains the public keys that we will accept.""" + + def __init__(self, port, keyfile): + """ + @type port: string or int + @param port: what port should the Manhole listen on? This is a + strports specification string, like 'tcp:12345' or + 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a + simple tcp port. + + @param keyfile: the name of a file (relative to the buildmaster's + basedir) that contains SSH public keys of authorized + users, one per line. This is the exact same format + as used by sshd in ~/.ssh/authorized_keys . + """ + + # TODO: expanduser this, and make it relative to the buildmaster's + # basedir + self.keyfile = keyfile + c = AuthorizedKeysChecker(keyfile) + _BaseManhole.__init__(self, port, c) + +class ArbitraryCheckerManhole(_BaseManhole): + """This Manhole accepts ssh connections, but uses an arbitrary + user-supplied 'checker' object to perform authentication.""" + + def __init__(self, port, checker): + """ + @type port: string or int + @param port: what port should the Manhole listen on? This is a + strports specification string, like 'tcp:12345' or + 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a + simple tcp port. + + @param checker: an instance of a twisted.cred 'checker' which will + perform authentication + """ + + _BaseManhole.__init__(self, port, checker) + + + diff --git a/src/allmydata/node.py b/src/allmydata/node.py new file mode 100644 index 00000000..bbb03e33 --- /dev/null +++ b/src/allmydata/node.py @@ -0,0 +1,95 @@ + +from twisted.application import service +import os.path +from foolscap import Tub +from allmydata.util.iputil import get_local_ip_for +from allmydata.util import idlib +from twisted.python import log + +class Node(service.MultiService): + # this implements common functionality of both Client nodes and the Queen + # node. + NODETYPE = "unknown NODETYPE" + PORTNUMFILE = None + CERTFILE = None + LOCAL_IP_FILE = "local_ip" + NODEIDFILE = "my_nodeid" + + def __init__(self, basedir="."): + service.MultiService.__init__(self) + self.basedir = os.path.abspath(basedir) + assert self.CERTFILE, "Your node.Node subclass must provide CERTFILE" + certfile = os.path.join(self.basedir, self.CERTFILE) + if os.path.exists(certfile): + f = open(certfile, "rb") + self.tub = Tub(certData=f.read()) + f.close() + else: + self.tub = Tub() + f = open(certfile, "wb") + f.write(self.tub.getCertData()) + f.close() + self.nodeid = idlib.a2b(self.tub.tubID) + f = open(os.path.join(self.basedir, self.NODEIDFILE), "w") + f.write(idlib.b2a(self.nodeid) + "\n") + f.close() + self.short_nodeid = self.tub.tubID[:4] # ready for printing + portnum = 0 + assert self.PORTNUMFILE, "Your node.Node subclass must provide PORTNUMFILE" + self._portnumfile = os.path.join(self.basedir, self.PORTNUMFILE) + if os.path.exists(self._portnumfile): + portnum = int(open(self._portnumfile, "r").read()) + self.tub.listenOn("tcp:%d" % portnum) + # we must wait until our service has started before we can find out + # our IP address and thus do tub.setLocation, and we can't register + # any services with the Tub until after that point + self.tub.setServiceParent(self) + + AUTHKEYSFILEBASE = "authorized_keys." + for f in os.listdir(self.basedir): + if f.startswith(AUTHKEYSFILEBASE): + keyfile = os.path.join(self.basedir, f) + portnum = int(f[len(AUTHKEYSFILEBASE):]) + from allmydata import manhole + m = manhole.AuthorizedKeysManhole(portnum, keyfile) + m.setServiceParent(self) + self.log("AuthorizedKeysManhole listening on %d" % portnum) + + def log(self, msg): + log.msg(self.short_nodeid + ": " + msg) + + def _setup_tub(self, local_ip): + # we can't get a dynamically-assigned portnum until our Tub is + # running, which means after startService. + l = self.tub.getListeners()[0] + portnum = l.getPortnum() + local_ip_filename = os.path.join(self.basedir, self.LOCAL_IP_FILE) + if os.path.exists(local_ip_filename): + f = open(local_ip_filename, "r") + local_ip = f.read() + f.close() + self.tub.setLocation("%s:%d" % (local_ip, portnum)) + if not os.path.exists(self._portnumfile): + # record which port we're listening on, so we can grab the same + # one next time + f = open(self._portnumfile, "w") + f.write("%d\n" % portnum) + f.close() + self.tub.setLocation("%s:%d" % (local_ip, l.getPortnum())) + return self.tub + + def tub_ready(self): + # called when the Tub is available for registerReference + pass + + def add_service(self, s): + s.setServiceParent(self) + return s + + def startService(self): + # note: this class can only be started and stopped once. + service.MultiService.startService(self) + local_ip = get_local_ip_for() + self._setup_tub(local_ip) + self.tub_ready() + self.log("%s running" % self.NODETYPE) diff --git a/src/allmydata/queen.py b/src/allmydata/queen.py new file mode 100644 index 00000000..011d57b5 --- /dev/null +++ b/src/allmydata/queen.py @@ -0,0 +1,76 @@ + +import os.path +from foolscap import Referenceable +from foolscap.eventual import eventually +from twisted.application import service +from twisted.python import log +from allmydata.util import idlib +from zope.interface import implements +from allmydata.interfaces import RIQueenRoster +from allmydata import node +from allmydata.filetable import GlobalVirtualDrive + +class Roster(service.MultiService, Referenceable): + implements(RIQueenRoster) + + def __init__(self): + service.MultiService.__init__(self) + self.phonebook = {} + self.connections = {} + self.gvd_root = None + + def set_gvd_root(self, root): + self.gvd_root = root + + def remote_hello(self, nodeid, node, pburl): + log.msg("roster: contact from %s" % idlib.b2a(nodeid)) + eventually(self._educate_the_new_peer, + nodeid, node, list(self.phonebook.items())) + eventually(self._announce_new_peer, + nodeid, pburl, list(self.connections.values())) + self.phonebook[nodeid] = pburl + self.connections[nodeid] = node + node.notifyOnDisconnect(self._lost_node, nodeid) + return self.gvd_root + + def _educate_the_new_peer(self, nodeid, node, new_peers): + log.msg("roster: educating %s (%d)" % (idlib.b2a(nodeid)[:4], len(new_peers))) + node.callRemote("add_peers", new_peers=new_peers) + + def _announce_new_peer(self, new_nodeid, new_node_pburl, peers): + log.msg("roster: announcing %s to everybody (%d)" % (idlib.b2a(new_nodeid)[:4], len(peers))) + for targetnode in peers: + targetnode.callRemote("add_peers", + new_peers=[(new_nodeid, new_node_pburl)]) + + def _lost_node(self, nodeid): + log.msg("roster: lost contact with %s" % idlib.b2a(nodeid)) + del self.phonebook[nodeid] + del self.connections[nodeid] + eventually(self._announce_lost_peer, nodeid) + + def _announce_lost_peer(self, lost_nodeid): + for targetnode in self.connections.values(): + targetnode.callRemote("lost_peers", lost_peers=[lost_nodeid]) + + + +class Queen(node.Node): + CERTFILE = "queen.pem" + PORTNUMFILE = "queen.port" + NODETYPE = "queen" + + def __init__(self, basedir="."): + node.Node.__init__(self, basedir) + self.gvd = self.add_service(GlobalVirtualDrive(basedir)) + self.urls = {} + + def tub_ready(self): + r = self.add_service(Roster()) + self.urls["roster"] = self.tub.registerReference(r, "roster") + self.log(" roster is at %s" % self.urls["roster"]) + f = open(os.path.join(self.basedir, "roster_pburl"), "w") + f.write(self.urls["roster"] + "\n") + f.close() + r.set_gvd_root(self.gvd.get_root()) + diff --git a/src/allmydata/scripts/__init__.py b/src/allmydata/scripts/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/allmydata/scripts/runner.py b/src/allmydata/scripts/runner.py new file mode 100644 index 00000000..ecff3201 --- /dev/null +++ b/src/allmydata/scripts/runner.py @@ -0,0 +1,184 @@ +#! /usr/bin/python + +import os, sys, signal, time +from twisted.python import usage + +class StartOptions(usage.Options): + optParameters = [ + ["basedir", "C", ".", "which directory to start the node in"], + ] + +class StopOptions(usage.Options): + optParameters = [ + ["basedir", "C", ".", "which directory to stop the node in"], + ] + +class RestartOptions(usage.Options): + optParameters = [ + ["basedir", "C", ".", "which directory to restart the node in"], + ] + +class CreateClientOptions(usage.Options): + optParameters = [ + ["basedir", "C", None, "which directory to create the client in"], + ] + + def parseArgs(self, *args): + if len(args) > 0: + self['basedir'] = args[0] + if len(args) > 1: + raise usage.UsageError("I wasn't expecting so many arguments") + + def postOptions(self): + if self['basedir'] is None: + raise usage.UsageError(" parameter is required") + self['basedir'] = os.path.abspath(self['basedir']) + +class CreateQueenOptions(usage.Options): + optParameters = [ + ["basedir", "C", None, "which directory to create the queen in"], + ] + + def parseArgs(self, *args): + if len(args) > 0: + self['basedir'] = args[0] + if len(args) > 1: + raise usage.UsageError("I wasn't expecting so many arguments") + + def postOptions(self): + if self['basedir'] is None: + raise usage.UsageError(" parameter is required") + self['basedir'] = os.path.abspath(self['basedir']) + +client_tac = """ +# -*- python -*- + +from allmydata import client +from twisted.application import service + +c = client.Client() + +application = service.Application("allmydata_client") +c.setServiceParent(application) +""" + +queen_tac = """ +# -*- python -*- + +from allmydata import queen +from twisted.application import service + +c = queen.Queen() + +application = service.Application("allmydata_queen") +c.setServiceParent(application) +""" + +class Options(usage.Options): + synopsis = "Usage: allmydata [command options]" + + subCommands = [ + ["create-client", None, CreateClientOptions, "Create a client node."], + ["create-queen", None, CreateQueenOptions, "Create a queen node."], + ["start", None, StartOptions, "Start a node (of any type)."], + ["stop", None, StopOptions, "Stop a node."], + ["restart", None, RestartOptions, "Restart a node."], + ] + + def postOptions(self): + if not hasattr(self, 'subOptions'): + raise usage.UsageError("must specify a command") + +def run(): + config = Options() + try: + config.parseOptions() + except usage.error, e: + print "%s: %s" % (sys.argv[0], e) + print + c = getattr(config, 'subOptions', config) + print str(c) + sys.exit(1) + + command = config.subCommand + so = config.subOptions + + if command == "create-client": + rc = create_client(so) + elif command == "create-queen": + rc = create_queen(so) + elif command == "start": + rc = start(so) + elif command == "stop": + rc = stop(so) + elif command == "restart": + rc = restart(so) + rc = rc or 0 + sys.exit(rc) + +def create_client(config): + basedir = config['basedir'] + os.mkdir(basedir) + f = open(os.path.join(basedir, "client.tac"), "w") + f.write(client_tac) + f.close() + print "client created in %s, please copy roster_pburl into the directory" % basedir + +def create_queen(config): + basedir = config['basedir'] + os.mkdir(basedir) + f = open(os.path.join(basedir, "queen.tac"), "w") + f.write(queen_tac) + f.close() + print "queen created in %s" % basedir + +def start(config): + basedir = config['basedir'] + if os.path.exists(os.path.join(basedir, "client.tac")): + tac = "client.tac" + type = "client" + elif os.path.exists(os.path.join(basedir, "queen.tac")): + tac = "queen.tac" + type = "queen" + else: + print "%s does not look like a node directory" % basedir + sys.exit(1) + os.chdir(basedir) + rc = os.system("twistd -y %s" % tac) + if rc == 0: + print "node probably started" + return 0 + else: + print "node probably not started" + return 1 + +def stop(config): + basedir = config['basedir'] + pidfile = os.path.join(basedir, "twistd.pid") + if not os.path.exists(pidfile): + print "%s does not look like a running node directory (no twistd.pid)" % basedir + return 1 + pid = open(pidfile, "r").read() + pid = int(pid) + + timer = 0 + os.kill(pid, signal.SIGTERM) + time.sleep(0.1) + while timer < 5: + # poll once per second until twistd.pid goes away, up to 5 seconds + try: + os.kill(pid, 0) + except OSError: + print "process %d is dead" % pid + return + timer += 1 + time.sleep(1) + print "never saw process go away" + return 1 + +def restart(config): + rc = stop(config) + if rc: + print "not restarting" + return rc + return start(config) diff --git a/src/allmydata/storageserver.py b/src/allmydata/storageserver.py new file mode 100644 index 00000000..868dc99a --- /dev/null +++ b/src/allmydata/storageserver.py @@ -0,0 +1,34 @@ +import os + +from foolscap import Referenceable +from twisted.application import service + +from allmydata.bucketstore import BucketStore +from zope.interface import implements +from allmydata.interfaces import RIStorageServer +from allmydata.util import idlib + +class BucketAlreadyExistsError(Exception): + pass + +class StorageServer(service.MultiService, Referenceable): + implements(RIStorageServer) + name = 'storageserver' + + def __init__(self, store_dir): + if not os.path.isdir(store_dir): + os.mkdir(store_dir) + service.MultiService.__init__(self) + self._bucketstore = BucketStore(store_dir) + self._bucketstore.setServiceParent(self) + + def remote_allocate_bucket(self, verifierid, bucket_num, size, leaser, + canary): + if self._bucketstore.has_bucket(verifierid): + raise BucketAlreadyExistsError() + lease = self._bucketstore.allocate_bucket(verifierid, bucket_num, size, + idlib.b2a(leaser), canary) + return lease + + def remote_get_buckets(self, verifierid): + return self._bucketstore.get_buckets(verifierid) diff --git a/src/allmydata/test/__init__.py b/src/allmydata/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/allmydata/test/figleaf.excludes b/src/allmydata/test/figleaf.excludes new file mode 100644 index 00000000..0b779a91 --- /dev/null +++ b/src/allmydata/test/figleaf.excludes @@ -0,0 +1,2 @@ +^/home/warner/stuff/python/twisted/Twisted/ +^/var/lib diff --git a/src/allmydata/test/test_client.py b/src/allmydata/test/test_client.py new file mode 100644 index 00000000..c067c303 --- /dev/null +++ b/src/allmydata/test/test_client.py @@ -0,0 +1,19 @@ + +from twisted.trial import unittest + +from allmydata import client + +class Basic(unittest.TestCase): + def test_loadable(self): + c = client.Client("") + c.startService() + return c.stopService() + + def test_permute(self): + c = client.Client("") + c.all_peers = ["%d" % i for i in range(5)] + self.failUnlessEqual(c.permute_peerids("one"), ['3','1','0','4','2']) + self.failUnlessEqual(c.permute_peerids("one", 3), ['3','1','0']) + self.failUnlessEqual(c.permute_peerids("two"), ['0','4','2','1','3']) + c.all_peers = [] + self.failUnlessEqual(c.permute_peerids("one"), []) diff --git a/src/allmydata/test/test_encode.py b/src/allmydata/test/test_encode.py new file mode 100644 index 00000000..9e8b42c3 --- /dev/null +++ b/src/allmydata/test/test_encode.py @@ -0,0 +1,19 @@ +#! /usr/bin/python + +from twisted.trial import unittest +from twisted.internet import defer +from allmydata import encode_new +from cStringIO import StringIO + +class MyEncoder(encode_new.Encoder): + def send(self, share_num, methname, *args, **kwargs): + return defer.succeed(None) + +class Encode(unittest.TestCase): + def OFFtest_1(self): + e = MyEncoder() + data = StringIO("some data to encode\n") + e.setup(data) + d = e.start() + return d + diff --git a/src/allmydata/test/test_filetable.py b/src/allmydata/test/test_filetable.py new file mode 100644 index 00000000..f72a9d31 --- /dev/null +++ b/src/allmydata/test/test_filetable.py @@ -0,0 +1,57 @@ + +import os +from twisted.trial import unittest +from allmydata.filetable import MutableDirectoryNode, \ + DeadDirectoryNodeError, BadDirectoryError, BadFileError + + +class FileTable(unittest.TestCase): + def test_files(self): + os.mkdir("filetable") + root = MutableDirectoryNode(os.path.abspath("filetable")) + self.failUnlessEqual(root.list(), []) + root.add_file("one", "vid-one") + root.add_file("two", "vid-two") + self.failUnlessEqual(root.list(), [("one", "vid-one"), + ("two", "vid-two")]) + root.remove("two") + self.failUnlessEqual(root.list(), [("one", "vid-one")]) + self.failUnlessRaises(BadFileError, root.remove, "two") + self.failUnlessRaises(BadFileError, root.remove, "three") + + self.failUnlessEqual(root.get("one"), "vid-one") + self.failUnlessRaises(BadFileError, root.get, "missing") + + # now play with directories + subdir1 = root.add_directory("subdir1") + self.failUnless(isinstance(subdir1, MutableDirectoryNode)) + subdir1a = root.get("subdir1") + self.failUnless(isinstance(subdir1a, MutableDirectoryNode)) + self.failUnlessEqual(subdir1a._basedir, subdir1._basedir) + entries = root.list() + self.failUnlessEqual(len(entries), 2) + one_index = entries.index( ("one", "vid-one") ) + subdir_index = 1 - one_index + self.failUnlessEqual(entries[subdir_index][0], "subdir1") + subdir2 = entries[subdir_index][1] + self.failUnless(isinstance(subdir2, MutableDirectoryNode)) + + self.failUnlessEqual(subdir1.list(), []) + self.failUnlessEqual(subdir2.list(), []) + + subdir1.add_file("subone", "vid-subone") + self.failUnlessEqual(subdir1.list(), [("subone", "vid-subone")]) + self.failUnlessEqual(subdir2.list(), [("subone", "vid-subone")]) + + self.failUnlessEqual(len(root.list()), 2) + + self.failUnlessRaises(BadDirectoryError, root.add_directory, "subdir1") + self.failUnlessRaises(BadDirectoryError, root.add_directory, "one") + + root.remove("subdir1") + self.failUnlessEqual(root.list(), [("one", "vid-one")]) + + # should our (orphaned) subdir1/subdir2 node still be able to do + # anything? + self.failUnlessRaises(DeadDirectoryNodeError, subdir1.list) + diff --git a/src/allmydata/test/test_queen.py b/src/allmydata/test/test_queen.py new file mode 100644 index 00000000..7e12917a --- /dev/null +++ b/src/allmydata/test/test_queen.py @@ -0,0 +1,10 @@ + +from twisted.trial import unittest + +from allmydata import queen + +class Basic(unittest.TestCase): + def test_loadable(self): + q = queen.Queen() + q.startService() + return q.stopService() diff --git a/src/allmydata/test/test_storage.py b/src/allmydata/test/test_storage.py new file mode 100644 index 00000000..6e7b57d1 --- /dev/null +++ b/src/allmydata/test/test_storage.py @@ -0,0 +1,147 @@ + +import os +import random + +from twisted.trial import unittest +from twisted.application import service +from twisted.internet import defer +from foolscap import Tub, Referenceable +from foolscap.eventual import flushEventualQueue + +from allmydata import client + +class Canary(Referenceable): + pass + +class StorageTest(unittest.TestCase): + + def setUp(self): + self.svc = service.MultiService() + self.node = client.Client('') + self.node.setServiceParent(self.svc) + self.tub = Tub() + self.tub.setServiceParent(self.svc) + return self.svc.startService() + + def test_create_bucket(self): + """ + Check that the storage server can return bucket data accurately. + """ + vid = os.urandom(20) + bnum = random.randrange(0, 256) + data = os.urandom(random.randint(1024, 16384)) + + rssd = self.tub.getReference(self.node.my_pburl) + def get_storageserver(node): + return node.callRemote('get_service', name='storageserver') + rssd.addCallback(get_storageserver) + + def create_bucket(storageserver): + return storageserver.callRemote('allocate_bucket', + verifierid=vid, + bucket_num=bnum, + size=len(data), + leaser=self.node.nodeid, + canary=Canary(), + ) + rssd.addCallback(create_bucket) + + def write_to_bucket(bucket): + def write_some(junk, bytes): + return bucket.callRemote('write', data=bytes) + def finalise(junk): + return bucket.callRemote('close') + off1 = len(data) / 2 + off2 = 3 * len(data) / 4 + d = defer.succeed(None) + d.addCallback(write_some, data[:off1]) + d.addCallback(write_some, data[off1:off2]) + d.addCallback(write_some, data[off2:]) + d.addCallback(finalise) + return d + rssd.addCallback(write_to_bucket) + + def get_node_again(junk): + return self.tub.getReference(self.node.my_pburl) + rssd.addCallback(get_node_again) + rssd.addCallback(get_storageserver) + + def get_buckets(storageserver): + return storageserver.callRemote('get_buckets', verifierid=vid) + rssd.addCallback(get_buckets) + + def read_buckets(buckets): + self.failUnlessEqual(len(buckets), 1) + bucket_num, bucket = buckets[0] + self.failUnlessEqual(bucket_num, bnum) + + def check_data(bytes_read): + self.failUnlessEqual(bytes_read, data) + d = bucket.callRemote('read') + d.addCallback(check_data) + return d + rssd.addCallback(read_buckets) + + return rssd + + def test_overwrite(self): + """ + Check that the storage server rejects an attempt to write too much data. + """ + vid = os.urandom(20) + bnum = random.randrange(0, 256) + data = os.urandom(random.randint(1024, 16384)) + + rssd = self.tub.getReference(self.node.my_pburl) + def get_storageserver(node): + return node.callRemote('get_service', name='storageserver') + rssd.addCallback(get_storageserver) + + def create_bucket(storageserver): + return storageserver.callRemote('allocate_bucket', + verifierid=vid, + bucket_num=bnum, + size=len(data), + leaser=self.node.nodeid, + canary=Canary(), + ) + rssd.addCallback(create_bucket) + + def write_to_bucket(bucket): + def write_some(junk, bytes): + return bucket.callRemote('write', data=bytes) + def finalise(junk): + return bucket.callRemote('close') + off1 = len(data) / 2 + off2 = 3 * len(data) / 4 + d = defer.succeed(None) + d.addCallback(write_some, data[:off1]) + d.addCallback(write_some, data[off1:off2]) + d.addCallback(write_some, data[off2:]) + # and then overwrite + d.addCallback(write_some, data[off1:off2]) + d.addCallback(finalise) + return d + rssd.addCallback(write_to_bucket) + + self.deferredShouldFail(rssd, ftype=AssertionError) + return rssd + + def deferredShouldFail(self, d, ftype=None, checker=None): + + def _worked(res): + self.fail("hey, this was supposed to fail, not return %s" % res) + if not ftype and not checker: + d.addCallbacks(_worked, + lambda f: None) + elif ftype and not checker: + d.addCallbacks(_worked, + lambda f: f.trap(ftype) or None) + else: + d.addCallbacks(_worked, + checker) + + def tearDown(self): + d = self.svc.stopService() + d.addCallback(lambda res: flushEventualQueue()) + return d diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py new file mode 100644 index 00000000..165e42d8 --- /dev/null +++ b/src/allmydata/test/test_system.py @@ -0,0 +1,143 @@ + +from twisted.trial import unittest +from twisted.internet import defer, reactor +from twisted.application import service +from allmydata import client, queen +import os +from foolscap.eventual import flushEventualQueue +from twisted.python import log +from allmydata.util import idlib +from twisted.web.client import getPage + +class SystemTest(unittest.TestCase): + def setUp(self): + self.sparent = service.MultiService() + self.sparent.startService() + def tearDown(self): + d = self.sparent.stopService() + d.addCallback(lambda res: flushEventualQueue()) + def _done(res): + d1 = defer.Deferred() + reactor.callLater(0.1, d1.callback, None) + return d1 + d.addCallback(_done) + return d + + def add_service(self, s): + s.setServiceParent(self.sparent) + return s + + def set_up_nodes(self, NUMCLIENTS=5): + self.numclients = NUMCLIENTS + if not os.path.isdir("queen"): + os.mkdir("queen") + q = self.queen = self.add_service(queen.Queen(basedir="queen")) + self.queen_pburl = q.urls["roster"] + self.clients = [] + for i in range(NUMCLIENTS): + basedir = "client%d" % i + if not os.path.isdir(basedir): + os.mkdir(basedir) + if i == 0: + f = open(os.path.join(basedir, "webport"), "w") + f.write("tcp:0:interface=127.0.0.1") + f.close() + c = self.add_service(client.Client(basedir=basedir)) + c.set_queen_pburl(self.queen_pburl) + self.clients.append(c) + log.msg("STARTING") + d = self.wait_for_connections() + def _connected(res): + # now find out where the web port was + l = self.clients[0].getServiceNamed("webish").listener + port = l._port.getHost().port + self.webish_url = "http://localhost:%d/" % port + d.addCallback(_connected) + return d + + def wait_for_connections(self, ignored=None): + for c in self.clients: + if len(c.connections) != self.numclients - 1: + d = defer.Deferred() + d.addCallback(self.wait_for_connections) + reactor.callLater(0.05, d.callback, None) + return d + return defer.succeed(None) + + def test_connections(self): + d = self.set_up_nodes() + def _check(res): + for c in self.clients: + self.failUnlessEqual(len(c.connections), 4) + d.addCallback(_check) + return d + test_connections.timeout = 20 + + def test_upload_and_download(self): + DATA = "Some data to upload\n" + d = self.set_up_nodes() + def _do_upload(res): + log.msg("UPLOADING") + u = self.clients[0].getServiceNamed("uploader") + d1 = u.upload_data(DATA) + return d1 + d.addCallback(_do_upload) + def _upload_done(verifierid): + log.msg("upload finished: verifierid=%s" % idlib.b2a(verifierid)) + dl = self.clients[1].getServiceNamed("downloader") + d1 = dl.download_to_data(verifierid) + return d1 + d.addCallback(_upload_done) + def _download_done(data): + log.msg("download finished") + self.failUnlessEqual(data, DATA) + d.addCallback(_download_done) + return d + test_upload_and_download.timeout = 20 + + def test_vdrive(self): + self.data = DATA = "Some data to publish to the virtual drive\n" + d = self.set_up_nodes() + def _do_publish(res): + log.msg("PUBLISHING") + v0 = self.clients[0].getServiceNamed("vdrive") + d1 = v0.make_directory("/", "subdir1") + d1.addCallback(lambda subdir1: + v0.put_file_by_data(subdir1, "mydata567", DATA)) + return d1 + d.addCallback(_do_publish) + def _publish_done(res): + log.msg("publish finished") + v1 = self.clients[1].getServiceNamed("vdrive") + d1 = v1.get_file_to_data("/subdir1/mydata567") + return d1 + d.addCallback(_publish_done) + def _get_done(data): + log.msg("get finished") + self.failUnlessEqual(data, DATA) + d.addCallback(_get_done) + d.addCallback(self._test_web) + return d + test_vdrive.timeout = 20 + + def _test_web(self, res): + base = self.webish_url + d = getPage(base) + def _got_welcome(page): + expected = "Connected Peers: %d" % (self.numclients-1) + self.failUnless(expected in page, + "I didn't see the right 'connected peers' message " + "in: %s" % page + ) + d.addCallback(_got_welcome) + d.addCallback(lambda res: getPage(base + "vdrive/subdir1")) + def _got_subdir1(page): + # there ought to be an href for our file + self.failUnless(">mydata567" in page) + d.addCallback(_got_subdir1) + d.addCallback(lambda res: getPage(base + "vdrive/subdir1/mydata567")) + def _got_data(page): + self.failUnlessEqual(page, self.data) + d.addCallback(_got_data) + return d + diff --git a/src/allmydata/test/test_upload.py b/src/allmydata/test/test_upload.py new file mode 100644 index 00000000..9d3e44c8 --- /dev/null +++ b/src/allmydata/test/test_upload.py @@ -0,0 +1,173 @@ + +from twisted.trial import unittest +from twisted.internet import defer +from cStringIO import StringIO + +from allmydata import upload + +class StringBucketProxy: + # This is for unit tests: make a StringIO look like a RIBucketWriter. + + def __init__(self): + self.data = StringIO() + self.size = None + self.done = False + + def callRemote(self, methname, **kwargs): + if methname == "write": + return defer.maybeDeferred(self.write, **kwargs) + elif methname == "close": + return defer.maybeDeferred(self.close, **kwargs) + else: + return defer.fail(NameError("no such method named %s" % methname)) + + def write(self, data): + self.data.write(data) + def close(self): + self.done = True + + +class FakePeer: + def __init__(self, peerid, response): + self.peerid = peerid + self.response = response + + def callRemote(self, methname, *args, **kwargs): + assert not args + return defer.maybeDeferred(self._callRemote, methname, **kwargs) + + def _callRemote(self, methname, **kwargs): + assert methname == "allocate_bucket" + assert kwargs["size"] == 100 + assert kwargs["leaser"] == "fakeclient" + if self.response == "good": + return self + raise upload.TooFullError() + +class FakeClient: + nodeid = "fakeclient" + def __init__(self, responses): + self.peers = [] + for peerid,r in enumerate(responses): + if r == "disconnected": + self.peers.append(None) + else: + self.peers.append(FakePeer(str(peerid), r)) + + def permute_peerids(self, key, max_peers): + assert max_peers == None + return [str(i) for i in range(len(self.peers))] + + def get_remote_service(self, peerid, name): + peer = self.peers[int(peerid)] + if not peer: + return defer.fail(IndexError("no connection to that peer")) + return defer.succeed(peer) + +class NextPeerUploader(upload.FileUploader): + def _got_all_peers(self, res): + return res + +class NextPeer(unittest.TestCase): + responses = ["good", # 0 + "full", # 1 + "full", # 2 + "disconnected", # 3 + "good", # 4 + ] + + def compare_landlords(self, u, c, expected): + exp = [(str(peerid), bucketnum, c.peers[peerid]) + for peerid, bucketnum in expected] + self.failUnlessEqual(u.landlords, exp) + + def test_0(self): + c = FakeClient([]) + u = NextPeerUploader(c) + u._verifierid = "verifierid" + u._shares = 2 + u._share_size = 100 + d = u.start() + def _check(f): + f.trap(upload.NotEnoughPeersError) + d.addCallbacks(lambda res: self.fail("this was supposed to fail"), + _check) + return d + + def test_1(self): + c = FakeClient(self.responses) + u = NextPeerUploader(c) + u._verifierid = "verifierid" + u._shares = 2 + u._share_size = 100 + d = u.start() + def _check(res): + self.failUnlessEqual(u.goodness_points, 2) + self.compare_landlords(u, c, [(0, 0), + (4, 1), + ]) + d.addCallback(_check) + return d + + def test_2(self): + c = FakeClient(self.responses) + u = NextPeerUploader(c) + u._verifierid = "verifierid" + u._shares = 3 + u._share_size = 100 + d = u.start() + def _check(res): + self.failUnlessEqual(u.goodness_points, 3) + self.compare_landlords(u, c, [(0, 0), + (4, 1), + (0, 2), + ]) + d.addCallback(_check) + return d + + responses2 = ["good", # 0 + "full", # 1 + "full", # 2 + "good", # 3 + "full", # 4 + ] + + def test_3(self): + c = FakeClient(self.responses2) + u = NextPeerUploader(c) + u._verifierid = "verifierid" + u._shares = 3 + u._share_size = 100 + d = u.start() + def _check(res): + self.failUnlessEqual(u.goodness_points, 3) + self.compare_landlords(u, c, [(0, 0), + (3, 1), + (0, 2), + ]) + d.addCallback(_check) + return d + + responses3 = ["good", # 0 + "good", # 1 + "good", # 2 + "good", # 3 + "good", # 4 + ] + + def test_4(self): + c = FakeClient(self.responses3) + u = NextPeerUploader(c) + u._verifierid = "verifierid" + u._shares = 4 + u._share_size = 100 + d = u.start() + def _check(res): + self.failUnlessEqual(u.goodness_points, 4) + self.compare_landlords(u, c, [(0, 0), + (1, 1), + (2, 2), + (3, 3), + ]) + d.addCallback(_check) + return d diff --git a/src/allmydata/test/test_vdrive.py b/src/allmydata/test/test_vdrive.py new file mode 100644 index 00000000..3610a66b --- /dev/null +++ b/src/allmydata/test/test_vdrive.py @@ -0,0 +1,68 @@ + +import os +from twisted.trial import unittest +from twisted.internet import defer +from allmydata import vdrive, filetable + +class LocalDirNode(filetable.MutableDirectoryNode): + def callRemote(self, methname, *args, **kwargs): + def _call(): + meth = getattr(self, methname) + return meth(*args, **kwargs) + return defer.maybeDeferred(_call) + + +class Traverse(unittest.TestCase): + def make_tree(self, basedir): + os.makedirs(basedir) + root = LocalDirNode(basedir) + self.d1 = d1 = root.add_directory("d1") + self.d2 = d2 = root.add_directory("d2") + root.add_file("a", "a") + root.add_file("b", "b") + d1.add_file("1.a", "1.a") + d1.add_file("1.b", "1.b") + d2.add_file("2.a", "2.a") + d2.add_file("2.b", "2.b") + return root + + def test_one(self): + basedir = "test_vdrive/one" + root = self.make_tree(basedir) + v = vdrive.VDrive() + v.set_root(root) + + d = v.get_dir("") + d.addCallback(lambda dir: self.failUnlessEqual(dir, root)) + d.addCallback(lambda res: v.get_dir("/d1")) + def _check(dir): + self.failUnless(isinstance(dir, LocalDirNode)) + self.failUnlessEqual(dir._basedir, self.d1._basedir) + d.addCallback(_check) + + + d.addCallback(lambda res: v.listdir("")) + d.addCallback(lambda files: + self.failUnlessEqual(sorted(files), + ["a", "b", "d1", "d2"])) + d.addCallback(lambda res: v.listdir("/")) + d.addCallback(lambda files: + self.failUnlessEqual(sorted(files), + ["a", "b", "d1", "d2"])) + d.addCallback(lambda res: v.listdir("d1")) + d.addCallback(lambda files: + self.failUnlessEqual(sorted(files), + ["1.a", "1.b"])) + + d.addCallback(lambda res: v.make_directory("", "d3")) + d.addCallback(lambda res: v.listdir("")) + d.addCallback(lambda files: + self.failUnlessEqual(sorted(files), + ["a", "b", "d1", "d2", "d3"])) + + d.addCallback(lambda res: v.make_directory("d2", "d2.1")) + d.addCallback(lambda res: v.listdir("/d2")) + d.addCallback(lambda files: + self.failUnlessEqual(sorted(files), + ["2.a", "2.b", "d2.1"])) + return d diff --git a/src/allmydata/test/trial_figleaf.py b/src/allmydata/test/trial_figleaf.py new file mode 100644 index 00000000..05780476 --- /dev/null +++ b/src/allmydata/test/trial_figleaf.py @@ -0,0 +1,127 @@ + +"""A Trial IReporter plugin that gathers figleaf code-coverage information. + +Once this plugin is installed, trial can be invoked with one of two new +--reporter options: + + trial --reporter=verbose-figleaf ARGS + trial --reporter-bwverbose-figleaf ARGS + +Once such a test run has finished, there will be a .figleaf file in the +top-level directory. This file can be turned into a directory of .html files +(with index.html as the starting point) by running: + + figleaf2html -d OUTPUTDIR [-x EXCLUDEFILE] + +Figleaf thinks of everyting in terms of absolute filenames rather than +modules. The EXCLUDEFILE may be necessary to keep it from providing reports +on non-Code-Under-Test files that live in unusual locations. In particular, +if you use extra PYTHONPATH arguments to point at some alternate version of +an upstream library (like Twisted), or if something like debian's +python-support puts symlinks to .py files in sys.path but not the .py files +themselves, figleaf will present coverage information on both of these. The +EXCLUDEFILE option might help to inhibit these. + +Other figleaf problems: + + the annotated code files are written to BASENAME(file).html, which results + in collisions between similarly-named source files. + + The line-wise coverage information isn't quite right. Blank lines are + counted as unreached code, lambdas aren't quite right, and some multiline + comments (docstrings?) aren't quite right. + +""" + +# TODO: pull some of figleaf into our tree so we can customize it more +# easily. + +from twisted.trial.reporter import TreeReporter, VerboseTextReporter + +# These plugins are registered via twisted/plugins/allmydata_trial.py . See +# the notes there for an explanation of how that works. + + + +# Reporters don't really get told about the suite starting and stopping. + +# The Reporter class is imported before the test classes are. + +# The test classes are imported before the Reporter is created. To get +# control earlier than that requires modifying twisted/scripts/trial.py . + +# Then Reporter.__init__ is called. + +# Then tests run, calling things like write() and addSuccess(). Each test is +# framed by a startTest/stopTest call. + +# Then the results are emitted, calling things like printErrors, +# printSummary, and wasSuccessful. + +# So for code-coverage (not including import), start in __init__ and finish +# in printSummary. To include import, we have to start in our own import and +# finish in printSummary. + +import figleaf +figleaf.start() + +class FigleafReporter(TreeReporter): + def __init__(self, *args, **kwargs): + TreeReporter.__init__(self, *args, **kwargs) + + def printSummary(self): + figleaf.stop() + figleaf.write_coverage(".figleaf") + print "Figleaf results written to .figleaf" + return TreeReporter.printSummary(self) + +class FigleafTextReporter(VerboseTextReporter): + def __init__(self, *args, **kwargs): + VerboseTextReporter.__init__(self, *args, **kwargs) + + def printSummary(self): + figleaf.stop() + figleaf.write_coverage(".figleaf") + print "Figleaf results written to .figleaf" + return VerboseTextReporter.printSummary(self) + +class not_FigleafReporter(object): + # this class, used as a reporter on a fully-passing test suite, doesn't + # trigger exceptions. So it is a guide to what methods are invoked on a + # Reporter. + def __init__(self, *args, **kwargs): + print "FIGLEAF HERE" + self.r = TreeReporter(*args, **kwargs) + self.shouldStop = self.r.shouldStop + self.separator = self.r.separator + self.testsRun = self.r.testsRun + self._starting2 = False + + def write(self, *args): + if not self._starting2: + self._starting2 = True + print "FIRST WRITE" + return self.r.write(*args) + + def startTest(self, *args, **kwargs): + return self.r.startTest(*args, **kwargs) + + def stopTest(self, *args, **kwargs): + return self.r.stopTest(*args, **kwargs) + + def addSuccess(self, *args, **kwargs): + return self.r.addSuccess(*args, **kwargs) + + def printErrors(self, *args, **kwargs): + return self.r.printErrors(*args, **kwargs) + + def writeln(self, *args, **kwargs): + return self.r.writeln(*args, **kwargs) + + def printSummary(self, *args, **kwargs): + print "PRINT SUMMARY" + return self.r.printSummary(*args, **kwargs) + + def wasSuccessful(self, *args, **kwargs): + return self.r.wasSuccessful(*args, **kwargs) + diff --git a/src/allmydata/upload.py b/src/allmydata/upload.py new file mode 100644 index 00000000..5b8588ab --- /dev/null +++ b/src/allmydata/upload.py @@ -0,0 +1,209 @@ + +from zope.interface import Interface, implements +from twisted.python import failure, log +from twisted.internet import defer +from twisted.application import service +from foolscap import Referenceable + +from allmydata.util import idlib +from allmydata import encode + +from cStringIO import StringIO +import sha + +class NotEnoughPeersError(Exception): + pass + +class HaveAllPeersError(Exception): + # we use this to jump out of the loop + pass + +# this wants to live in storage, not here +class TooFullError(Exception): + pass + +class FileUploader: + debug = False + + def __init__(self, peer): + self._peer = peer + + def set_filehandle(self, filehandle): + self._filehandle = filehandle + filehandle.seek(0, 2) + self._size = filehandle.tell() + filehandle.seek(0) + + def make_encoder(self): + self._needed_shares = 4 + self._shares = 4 + self._encoder = encode.Encoder(self._filehandle, self._shares) + self._share_size = self._size + + def set_verifierid(self, vid): + assert isinstance(vid, str) + self._verifierid = vid + + + def start(self): + log.msg("starting upload") + if self.debug: + print "starting upload" + # first step: who should we upload to? + + # maybe limit max_peers to 2*len(self.shares), to reduce memory + # footprint + max_peers = None + + self.permuted = self._peer.permute_peerids(self._verifierid, max_peers) + self._total_peers = len(self.permuted) + for p in self.permuted: + assert isinstance(p, str) + # we will shrink self.permuted as we give up on peers + self.peer_index = 0 + self.goodness_points = 0 + self.target_goodness = self._shares + self.landlords = [] # list of (peerid, bucket_num, remotebucket) + + d = defer.maybeDeferred(self._check_next_peer) + d.addCallback(self._got_all_peers) + return d + + def _check_next_peer(self): + if len(self.permuted) == 0: + # there are no more to check + raise NotEnoughPeersError("%s goodness, want %s, have %d " + "landlords, %d total peers" % + (self.goodness_points, + self.target_goodness, + len(self.landlords), + self._total_peers)) + if self.peer_index >= len(self.permuted): + self.peer_index = 0 + + peerid = self.permuted[self.peer_index] + + d = self._peer.get_remote_service(peerid, "storageserver") + def _got_peer(service): + bucket_num = len(self.landlords) + if self.debug: print "asking %s" % idlib.b2a(peerid) + d2 = service.callRemote("allocate_bucket", + verifierid=self._verifierid, + bucket_num=bucket_num, + size=self._share_size, + leaser=self._peer.nodeid, + canary=Referenceable()) + def _allocate_response(bucket): + if self.debug: + print " peerid %s will grant us a lease" % idlib.b2a(peerid) + self.landlords.append( (peerid, bucket_num, bucket) ) + self.goodness_points += 1 + if self.goodness_points >= self.target_goodness: + if self.debug: print " we're done!" + raise HaveAllPeersError() + # otherwise we fall through to allocate more peers + d2.addCallback(_allocate_response) + return d2 + d.addCallback(_got_peer) + def _done_with_peer(res): + if self.debug: print "done with peer %s:" % idlib.b2a(peerid) + if isinstance(res, failure.Failure): + if res.check(HaveAllPeersError): + if self.debug: print " all done" + # we're done! + return + if res.check(TooFullError): + if self.debug: print " too full" + elif res.check(IndexError): + if self.debug: print " no connection" + else: + if self.debug: print " other error:", res + self.permuted.remove(peerid) # this peer was unusable + else: + if self.debug: print " they gave us a lease" + # we get here for either good peers (when we still need + # more), or after checking a bad peer (and thus still need + # more). So now we need to grab a new peer. + self.peer_index += 1 + return self._check_next_peer() + d.addBoth(_done_with_peer) + return d + + def _got_all_peers(self, res): + d = self._encoder.do_upload(self.landlords) + d.addCallback(lambda res: self._verifierid) + return d + +def netstring(s): + return "%d:%s," % (len(s), s) + +class IUploadable(Interface): + def get_filehandle(): + pass + def close_filehandle(f): + pass + +class FileName: + implements(IUploadable) + def __init__(self, filename): + self._filename = filename + def get_filehandle(self): + return open(self._filename, "rb") + def close_filehandle(self, f): + f.close() + +class Data: + implements(IUploadable) + def __init__(self, data): + self._data = data + def get_filehandle(self): + return StringIO(self._data) + def close_filehandle(self, f): + pass + +class FileHandle: + implements(IUploadable) + def __init__(self, filehandle): + self._filehandle = filehandle + def get_filehandle(self): + return self._filehandle + def close_filehandle(self, f): + # the originator of the filehandle reserves the right to close it + pass + +class Uploader(service.MultiService): + """I am a service that allows file uploading. + """ + name = "uploader" + + def _compute_verifierid(self, f): + hasher = sha.new(netstring("allmydata_v1_verifierid")) + f.seek(0) + hasher.update(f.read()) + f.seek(0) + # note: this is only of the plaintext data, no encryption yet + return hasher.digest() + + def upload(self, f): + assert self.parent + assert self.running + f = IUploadable(f) + fh = f.get_filehandle() + u = FileUploader(self.parent) + u.set_filehandle(fh) + u.set_verifierid(self._compute_verifierid(fh)) + u.make_encoder() + d = u.start() + def _done(res): + f.close_filehandle(fh) + return res + d.addBoth(_done) + return d + + # utility functions + def upload_data(self, data): + return self.upload(Data(data)) + def upload_filename(self, filename): + return self.upload(FileName(filename)) + def upload_filehandle(self, filehandle): + return self.upload(FileHandle(filehandle)) diff --git a/src/allmydata/util/__init__.py b/src/allmydata/util/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/allmydata/util/assertutil.py b/src/allmydata/util/assertutil.py new file mode 100644 index 00000000..2adae8d6 --- /dev/null +++ b/src/allmydata/util/assertutil.py @@ -0,0 +1,82 @@ +# Copyright (c) 2003-2006 Bryce "Zooko" Wilcox-O'Hearn +# mailto:zooko@zooko.com +# http://zooko.com/ +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this work to deal in this work without restriction (including the +# rights to use, modify, distribute, sublicense, and/or sell copies) + +""" +Tests useful in assertion checking, prints out nicely formated messages too. +""" + +from humanreadable import hr + +from twisted.python import log + +def _assert(___cond=False, *___args, **___kwargs): + if ___cond: + return True + msgbuf=[] + if ___args: + msgbuf.append("%s %s" % tuple(map(hr, (___args[0], type(___args[0]),)))) + msgbuf.extend([", %s %s" % tuple(map(hr, (arg, type(arg),))) for arg in ___args[1:]]) + if ___kwargs: + msgbuf.append(", %s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) + else: + if ___kwargs: + msgbuf.append("%s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) + msgbuf.extend([", %s: %s %s" % tuple(map(hr, (k, v, type(v),))) for k, v in ___kwargs.items()[1:]]) + + raise AssertionError, "".join(msgbuf) + + return False + +def precondition(___cond=False, *___args, **___kwargs): + try: + if ___cond: + return True + msgbuf=["precondition", ] + if ___args or ___kwargs: + msgbuf.append(": ") + if ___args: + msgbuf.append("%s %s" % tuple(map(hr, (___args[0], type(___args[0]),)))) + msgbuf.extend([", %s %s" % tuple(map(hr, (arg, type(arg),))) for arg in ___args[1:]]) + if ___kwargs: + msgbuf.append(", %s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) + else: + if ___kwargs: + msgbuf.append("%s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) + msgbuf.extend([", %s: %s %s" % tuple(map(hr, (k, v, type(v),))) for k, v in ___kwargs.items()[1:]]) + except Exception, le: + log.msg("assertutil.precondition(): INTERNAL ERROR IN pyutil.assertutil. %s %s %s" % (type(le), repr(le), le.args,)) + log.err() + raise le + except: + log.msg("assertutil.precondition(): INTERNAL ERROR IN pyutil.assertutil.") + log.err() + raise + + raise AssertionError, "".join(msgbuf) + + return False + +def postcondition(___cond=False, *___args, **___kwargs): + if ___cond: + return True + msgbuf=["postcondition", ] + if ___args or ___kwargs: + msgbuf.append(": ") + if ___args: + msgbuf.append("%s %s" % tuple(map(hr, (___args[0], type(___args[0]),)))) + msgbuf.extend([", %s %s" % tuple(map(hr, (arg, type(arg),))) for arg in ___args[1:]]) + if ___kwargs: + msgbuf.append(", %s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) + else: + if ___kwargs: + msgbuf.append("%s: %s %s" % ((___kwargs.items()[0][0],) + tuple(map(hr, (___kwargs.items()[0][1], type(___kwargs.items()[0][1]),))))) + msgbuf.extend([", %s: %s %s" % tuple(map(hr, (k, v, type(v),))) for k, v in ___kwargs.items()[1:]]) + + raise AssertionError, "".join(msgbuf) + + return False + diff --git a/src/allmydata/util/bencode.py b/src/allmydata/util/bencode.py new file mode 100644 index 00000000..d507a6ce --- /dev/null +++ b/src/allmydata/util/bencode.py @@ -0,0 +1,433 @@ +#!/usr/bin/env python +# -*- coding: MacRoman -*- +""" +A library for streaming and unstreaming of simple objects, designed +for speed, compactness, and ease of implementation. + +The basic functions are bencode and bdecode. bencode takes an object +and returns a string, bdecode takes a string and returns an object. +bdecode raises a ValueError if you give it an invalid string. + +The objects passed in may be nested dicts, lists, ints, floats, strings, +and Python boolean and None types. For example, all of the following +may be bencoded - + +{'a': [0, 1], 'b': None} + +[None, ['a', 2, ['c', None]]] + +{'spam': (2,3,4)} + +{'name': 'Cronus', 'spouse': 'Rhea', 'children': ['Hades', 'Poseidon']} + +In general bdecode(bencode(spam)) == spam, but tuples and lists are +encoded the same, so bdecode(bencode((0, 1))) is [0, 1] rather +than (0, 1). Longs and ints are also encoded the same way, so +bdecode(bencode(4)) is a long. + +Dict keys are required to be basestrings (byte strings or unicode objects), +to avoid a mess of potential implementation incompatibilities. bencode is +intended to be used for protocols which are going to be re-implemented many +times, so it's very conservative in that regard. + +Which type is encoded is determined by the first character, 'i', 'n', 'f', +'d', 'l', 'b', 'u', and any digit. They indicate integer, null, float, +dict, list, boolean, unicode string, and string, respectively. + +Strings are length-prefixed in base 10, followed by a colon. + +bencode('spam') == '4:spam' + +Unicode string objects are indicated with an initial u, a base 10 +length-prefix, and the remaining bytes in utf-8 encoding. + +bencode(u'\u00bfHabla espa\u00f1ol?') == 'ËHabla espaÐol?' + +Nulls are indicated by a single 'n'. + +bencode(None) == 'n' + +Integers are encoded base 10 and terminated with an 'e' - + +bencode(3) == 'i3e' +bencode(-20) == 'i-20e' + +Floats are encoded in base 10 and terminated with an 'e' - + +bencode(3.2) == 'f3.2e' +bencode(-23.4532) == 'f-23.4532e' + +Lists are encoded in list order, terminated by an 'e' - + +bencode(['abc', 'd']) == 'l3:abc1:de' +bencode([2, 'f']) == 'li2e1:fe' + +Dicts are encoded by containing alternating keys and values. +The keys are encoded in sorted order, but sort order is not +enforced on the decode. Dicts are terminated by an 'e'. Dict +keys can be either bytestrings or unicode strings. For example - + +bencode({'spam': 'eggs'}) == 'd4:spam4:eggse' +bencode({'ab': 2, 'a': None}) == 'd1:an2:abi2ee' +bencode({'a' : 1, u'\xab': 2}) == 'd1:ai1eu4:\xfe\xff\x00\xa8i2ee' + +Truncated strings come first, so in sort order 'a' comes before 'abc'. +""" + +# This file is licensed under the GNU Lesser General Public License v2.1. +# +# Originally written by Mojo Nation. +# Rewritten by Bram Cohen. +# Further enhanced by Allmydata to support additional Python types (Boolean +# None, Float, and Unicode strings.) + +from types import IntType, LongType, FloatType, ListType, TupleType, DictType, StringType, UnicodeType, BooleanType, NoneType +from cStringIO import StringIO +import string + +def bencode(data): + """ + encodes objects as strings, see module documentation for more info + """ + result = StringIO() + bwrite(data, result) + return result.getvalue() + +def bwrite(data, result): + # a generic using pje's type dispatch will be faster here + try: + encoder = encoders[type(data)] + except KeyError: + encoder = None + # Catch subclasses of built-in types + for t,coder in encoders.items(): + if isinstance(data, t): + encoder = coder + break + if not encoder: + raise ValueError("unsupported data type: %s" % type(data)) + encoder(data, result) + +encoders = {} + +def encode_int(data, result): + result.write('i' + str(data) + 'e') + +encoders[IntType] = encode_int +encoders[LongType] = encode_int + +def encode_float(data, result): + result.write('f' + str(data) + 'e') + +encoders[FloatType] = encode_float + +def encode_bool(data, result): + if data: + result.write('b1') + else: + result.write('b0') + +encoders[BooleanType] = encode_bool + +def encode_list(data, result): + result.write('l') + _bwrite = bwrite + for item in data: + _bwrite(item, result) + result.write('e') + +encoders[TupleType] = encode_list +encoders[ListType] = encode_list +encoders[set] = encode_list + +def encode_string(data, result): + result.write(str(len(data)) + ':' + data) + +encoders[StringType] = encode_string + +def encode_unicode(data, result): + payload = data.encode('utf-8') + result.write('u' + str(len(payload)) + ':' + payload) + +encoders[UnicodeType] = encode_unicode + +def encode_dict(data, result): + result.write('d') + _bwrite = bwrite + keylist = data.keys() + keylist.sort() + for key in keylist: + _bwrite(key, result) + _bwrite(data[key], result) + result.write('e') + +encoders[DictType] = encode_dict + +encoders[NoneType] = lambda data, result: result.write('n') + +def bdecode(s): + """ + Does the opposite of bencode. Raises a ValueError if there's a problem. + """ + try: + result, index = bread(s, 0) + if index != len(s): + raise ValueError('left over stuff at end: %s' % s[index:]) + return result + except IndexError, e: + raise ValueError(str(e)) + except KeyError, e: + raise ValueError(str(e)) + +def bread(s, index): + return decoders[s[index]](s, index) + +decoders = {} + +def decode_raw_string(s, index): + ci = s.index(":", index) + ei = ci + int(s[index:ci]) + 1 + if ei > len(s): + raise ValueError('length encoding indicates premature end of string') + return (s[ci+1:ei], ei) + +for c in string.digits: + decoders[c] = decode_raw_string + +def decode_unicode_string(s, index): + ci = s.index(":", index) + ei = ci + int(s[index+1:ci]) + 1 + if ei > len(s): + raise ValueError('length encoding indicates premature end of string') + return (unicode(s[ci+1:ei], 'utf-8'), ei) + +decoders['u'] = decode_unicode_string + +def decode_int(s, index): + ei = s.index('e', index) + return (long(s[index+1:ei]), ei+1) + +decoders['i'] = decode_int + +def decode_float(s, index): + ei = s.index('e', index) + return (float(s[index+1:ei]), ei+1) + +decoders['f'] = decode_float + +def decode_bool(s, index): + val = s[index+1] + if val == '1': + return True, index+2 + elif val == '0': + return False, index+2 + else: + raise ValueError('invalid boolean encoding: %s' % s[index:index+2]) + +decoders['b'] = decode_bool + +# decoders['n'] = lambda s, index: decoders_n.inc('n') or (None, index + 1) +decoders['n'] = lambda s, index: (None, index + 1) + +def decode_list(s, index): + # decoders_n.inc('l') + result = [] + index += 1 + _bread = bread + while s[index] != 'e': + next, index = _bread(s, index) + result.append(next) + return result, index + 1 + +decoders['l'] = decode_list + +def decode_dict(s, index): + # decoders_n.inc('d') + result = {} + index += 1 + _decode_string = decode_raw_string + _decode_unicode = decode_unicode_string + _bread = bread + while s[index] != 'e': + if s[index] in string.digits: + key, index = _decode_string(s, index) + elif s[index] == "u": + key, index = _decode_unicode(s, index) + else: + raise ValueError("dict key must be basestring") + if key in result: + raise ValueError("dict key was repeated") + value, index = _bread(s, index) + result[key] = value + return result, index + 1 + +decoders['d'] = decode_dict + +def test_decode_raw_string(): + assert decode_raw_string('1:a', 0) == ('a', 3) + assert decode_raw_string('0:', 0) == ('', 2) + assert decode_raw_string('10:aaaaaaaaaaaaaaaaaaaaaaaaa', 0) == ('aaaaaaaaaa', 13) + assert decode_raw_string('10:', 1) == ('', 3) +# non-reexp version does not check for this case +# try: +# decode_raw_string('01:a', 0) +# assert 0, 'failed' +# except ValueError: +# pass + try: + decode_raw_string('--1:a', 0) + assert 0, 'failed' + except ValueError: + pass + try: + decode_raw_string('h', 0) + assert 0, 'failed' + except ValueError: + pass + try: + decode_raw_string('h:', 0) + assert 0, 'failed' + except ValueError: + pass + try: + decode_raw_string('1', 0) + assert 0, 'failed' + except ValueError: + pass + try: + decode_raw_string('', 0) + assert 0, 'failed' + except ValueError: + pass + try: + decode_raw_string('5:a', 0) + assert 0, 'failed' + except ValueError: + pass + +def test_encode_and_decode_unicode_results_in_unicode_type(): + assert bdecode(bencode(u'\u00bfHabla espa\u00f1ol?')) == u'\u00bfHabla espa\u00f1ol?' + +def test_encode_and_decode_unicode_at_least_preserves_the_content_even_if_it_flattens_the_type(): + test_string = bdecode(bencode(u'\u00bfHabla espa\u00f1ol?')) + if isinstance(test_string, unicode): + assert test_string == u'\u00bfHabla espa\u00f1ol?' + elif isinstance(test_string, str): + assert test_string.decode('utf-8') == u'\u00bfHabla espa\u00f1ol?' + else: + assert 0, 'flunked' + +def test_dict_forbids_non_string_key(): + try: + bdecode('di3ene') + assert 0, 'failed' + except ValueError: + pass + +def test_dict_forbids_key_repeat(): + try: + bdecode('d1:an1:ane') + assert 0, 'failed' + except ValueError: + pass + +def test_empty_dict(): + assert bdecode('de') == {} + +def test_dict_allows_unicode_keys(): + assert bdecode(bencode({'a': 1, u'\xa8': 2})) == {'a': 1L, u'\xa8': 2L} + +def test_ValueError_in_decode_unknown(): + try: + bdecode('x') + assert 0, 'flunked' + except ValueError: + pass + +def test_encode_and_decode_none(): + assert bdecode(bencode(None)) == None + +def test_encode_and_decode_long(): + assert bdecode(bencode(-23452422452342L)) == -23452422452342L + +def test_encode_and_decode_int(): + assert bdecode(bencode(2)) == 2 + +def test_encode_and_decode_float(): + assert bdecode(bencode(3.4)) == 3.4 + assert bdecode(bencode(0.0)) == 0.0 + assert bdecode(bencode(-4.56)) == -4.56 + assert bdecode(bencode(-0.0)) == -0.0 + +def test_encode_and_decode_bool(): + assert bdecode(bencode(True)) == True + assert bdecode(bencode(False)) == False + +# the non-regexp methods no longer check for canonical ints, but we +# don't parse input we did not generate using bencode, so I will leave +# these commented out for now +#def test_decode_noncanonical_int(): +# try: +# bdecode('i03e') +# assert 0 +# except ValueError: +# pass +# try: +# bdecode('i3 e') +# assert 0 +# except ValueError: +# pass +# try: +# bdecode('i 3e') +# assert 0 +# except ValueError: +# pass +# try: +# bdecode('i-0e') +# assert 0 +# except ValueError: +# pass + +def test_encode_and_decode_dict(): + x = {'42': 3} + assert bdecode(bencode(x)) == x + +def test_encode_and_decode_list(): + assert bdecode(bencode([])) == [] + +def test_encode_and_decode_tuple(): + assert bdecode(bencode(())) == [] + +def test_encode_and_decode_empty_dict(): + assert bdecode(bencode({})) == {} + +def test_encode_and_decode_complex_object(): + spam = [[], 0, -3, -345234523543245234523L, {}, 'spam', None, {'a': [3]}, {}, {'a': 1L, u'\xa8': 2L}] + assert bencode(bdecode(bencode(spam))) == bencode(spam) + assert bdecode(bencode(spam)) == spam + +def test_unfinished_list(): + try: + bdecode('ln') + assert 0 + except ValueError: + pass + +def test_unfinished_dict(): + try: + bdecode('d') + assert 0 + except ValueError: + pass + try: + bdecode('d1:a') + assert 0 + except ValueError: + pass + +def test_unsupported_type(): + try: + bencode(lambda: None) + assert 0 + except ValueError: + pass \ No newline at end of file diff --git a/src/allmydata/util/humanreadable.py b/src/allmydata/util/humanreadable.py new file mode 100644 index 00000000..bae826c5 --- /dev/null +++ b/src/allmydata/util/humanreadable.py @@ -0,0 +1,128 @@ +# Copyright (c) 2001 Autonomous Zone Industries +# Copyright (c) 2002-2005 Bryce "Zooko" Wilcox-O'Hearn +# This file is licensed under the +# GNU Lesser General Public License v2.1. +# See the file COPYING or visit http://www.gnu.org/ for details. + +import exceptions, os +from repr import Repr + +class BetterRepr(Repr): + def __init__(self): + Repr.__init__(self) + + # Note: These levels can get adjusted dynamically! My goal is to get + # more info when printing important debug stuff like exceptions and + # stack traces and less info when logging normal events. + # --Zooko 2000-10-14 + if 0: # DEBUG MODE + self.maxlevel = 24 + self.maxdict = 24 + self.maxlist = 24 + self.maxtuple = 24 + self.maxstring = 800 + self.maxother = 800 + else: + self.maxlevel = 6 + self.maxdict = 6 + self.maxlist = 6 + self.maxtuple = 6 + self.maxstring = 300 + self.maxother = 300 + + def repr_function(self, obj, level): + if hasattr(obj, 'func_code'): + return '<' + obj.func_name + '() at ' + os.path.basename(obj.func_code.co_filename) + ':' + str(obj.func_code.co_firstlineno) + '>' + else: + return '<' + obj.func_name + '() at (builtin)' + + def repr_instance_method(self, obj, level): + if hasattr(obj, 'func_code'): + return '<' + obj.im_class.__name__ + '.' + obj.im_func.__name__ + '() at ' + os.path.basename(obj.im_func.func_code.co_filename) + ':' + str(obj.im_func.func_code.co_firstlineno) + '>' + else: + return '<' + obj.im_class.__name__ + '.' + obj.im_func.__name__ + '() at (builtin)' + + def repr_long(self, obj, level): + s = `obj` # XXX Hope this isn't too slow... + if len(s) > self.maxlong: + i = max(0, (self.maxlong-3)/2) + j = max(0, self.maxlong-3-i) + s = s[:i] + '...' + s[len(s)-j:] + if s[-1] == 'L': + return s[:-1] + return s + + def repr_instance(self, obj, level): + """ + If it is an instance of Exception, format it nicely (trying to emulate + the format that you see when an exception is actually raised, plus + bracketing '<''s). If it is an instance of dict call self.repr_dict() + on it. If it is an instance of list call self.repr_list() on it. Else + call Repr.repr_instance(). + """ + if isinstance(obj, exceptions.Exception): + # Don't cut down exception strings so much. + tms = self.maxstring + self.maxstring = max(512, tms * 4) + tml = self.maxlist + self.maxlist = max(12, tml * 4) + try: + if hasattr(obj, 'args'): + if len(obj.args) == 1: + return '<' + obj.__class__.__name__ + ': ' + self.repr1(obj.args[0], level-1) + '>' + else: + return '<' + obj.__class__.__name__ + ': ' + self.repr1(obj.args, level-1) + '>' + else: + return '<' + obj.__class__.__name__ + '>' + finally: + self.maxstring = tms + self.maxlist = tml + + if isinstance(obj, dict): + return self.repr_dict(obj, level) + + if isinstance(obj, list): + return self.repr_list(obj, level) + + return Repr.repr_instance(self, obj, level) + + def repr_list(self, obj, level): + """ + copied from standard repr.py and fixed to work on multithreadedly mutating lists. + """ + if level <= 0: return '[...]' + n = len(obj) + myl = obj[:min(n, self.maxlist)] + s = '' + for item in myl: + entry = self.repr1(item, level-1) + if s: s = s + ', ' + s = s + entry + if n > self.maxlist: s = s + ', ...' + return '[' + s + ']' + + def repr_dict(self, obj, level): + """ + copied from standard repr.py and fixed to work on multithreadedly mutating dicts. + """ + if level <= 0: return '{...}' + s = '' + n = len(obj) + items = obj.items()[:min(n, self.maxdict)] + items.sort() + for key, val in items: + entry = self.repr1(key, level-1) + ':' + self.repr1(val, level-1) + if s: s = s + ', ' + s = s + entry + if n > self.maxdict: s = s + ', ...' + return '{' + s + '}' + +# This object can be changed by other code updating this module's "brepr" +# variables. This is so that (a) code can use humanreadable with +# "from humanreadable import hr; hr(mything)", and (b) code can override +# humanreadable to provide application-specific human readable output +# (e.g. libbase32's base32id.AbbrevRepr). +brepr = BetterRepr() + +def hr(x): + return brepr.repr(x) diff --git a/src/allmydata/util/idlib.py b/src/allmydata/util/idlib.py new file mode 100644 index 00000000..b447a08d --- /dev/null +++ b/src/allmydata/util/idlib.py @@ -0,0 +1,7 @@ +from base64 import b32encode, b32decode + +def b2a(i): + return b32encode(i).lower() + +def a2b(i): + return b32decode(i.upper()) diff --git a/src/allmydata/util/iputil.py b/src/allmydata/util/iputil.py new file mode 100644 index 00000000..9b87b1c0 --- /dev/null +++ b/src/allmydata/util/iputil.py @@ -0,0 +1,21 @@ + +# adapted from nattraverso.ipdiscover + +import socket +from twisted.internet import reactor +from twisted.internet.protocol import DatagramProtocol + +def get_local_ip_for(target='A.ROOT-SERVERS.NET'): + """Find out what our IP address is for use by a given target. + + Returns a string that holds the IP address which could be used by + 'target' to connect to us. It might work for them, it might not. + """ + target_ipaddr = socket.gethostbyname(target) + udpprot = DatagramProtocol() + port = reactor.listenUDP(0, udpprot) + udpprot.transport.connect(target_ipaddr, 7) + localip = udpprot.transport.getHost().host + port.stopListening() # note, this returns a Deferred + return localip + diff --git a/src/allmydata/vdrive.py b/src/allmydata/vdrive.py new file mode 100644 index 00000000..22e012d0 --- /dev/null +++ b/src/allmydata/vdrive.py @@ -0,0 +1,176 @@ + +"""This is the client-side facility to manipulate virtual drives.""" + +from twisted.application import service +from twisted.internet import defer +from twisted.python import log +from allmydata import upload, download + +class VDrive(service.MultiService): + name = "vdrive" + + def set_root(self, root): + self.gvd_root = root + + def dirpath(self, dir_or_path): + if isinstance(dir_or_path, str): + return self.get_dir(dir_or_path) + return defer.succeed(dir_or_path) + + def get_dir(self, path): + """Return a Deferred that fires with a RemoteReference to a + MutableDirectoryNode at the given /-delimited path.""" + d = defer.succeed(self.gvd_root) + if path.startswith("/"): + path = path[1:] + if path == "": + return d + for piece in path.split("/"): + d.addCallback(lambda parent: parent.callRemote("list")) + def _find(table, subdir): + for name,target in table: + if name == subdir: + return target + else: + raise KeyError("no such directory '%s' in '%s'" % + (subdir, [t[0] for t in table])) + d.addCallback(_find, piece) + def _check(subdir): + assert not isinstance(subdir, str), "Hey, %s shouldn't be a string" % subdir + return subdir + d.addCallback(_check) + return d + + def get_verifierid_from_parent(self, parent, filename): + assert not isinstance(parent, str), "'%s' isn't a directory node" % (parent,) + d = parent.callRemote("list") + def _find(table): + for name,target in table: + if name == filename: + assert isinstance(target, str), "Hey, %s isn't a file" % filename + return target + else: + raise KeyError("no such file '%s' in '%s'" % + (filename, [t[0] for t in table])) + d.addCallback(_find) + return d + + def get_root(self): + return self.gvd_root + + def listdir(self, dir_or_path): + d = self.dirpath(dir_or_path) + d.addCallback(lambda parent: parent.callRemote("list")) + def _list(table): + return [t[0] for t in table] + d.addCallback(_list) + return d + + def put_file(self, dir_or_path, name, uploadable): + """Upload an IUploadable and add it to the virtual drive (as an entry + called 'name', in 'dir_or_path') 'dir_or_path' must either be a + string like 'root/subdir1/subdir2', or a directory node (either the + root directory node returned by get_root(), or a subdirectory + returned by list() ). + + The uploadable can be an instance of allmydata.upload.Data, + FileHandle, or FileName. + + I return a deferred that will fire when the operation is complete. + """ + + log.msg("putting file to '%s'" % name) + ul = self.parent.getServiceNamed("uploader") + d = self.dirpath(dir_or_path) + def _got_dir(dirnode): + d1 = ul.upload(uploadable) + d1.addCallback(lambda vid: + dirnode.callRemote("add_file", name, vid)) + return d1 + d.addCallback(_got_dir) + def _done(res): + log.msg("finished putting file to '%s'" % name) + return res + d.addCallback(_done) + return d + + def put_file_by_filename(self, dir_or_path, name, filename): + return self.put_file(dir_or_path, name, upload.FileName(filename)) + def put_file_by_data(self, dir_or_path, name, data): + return self.put_file(dir_or_path, name, upload.Data(data)) + def put_file_by_filehandle(self, dir_or_path, name, filehandle): + return self.put_file(dir_or_path, name, upload.FileHandle(filehandle)) + + def make_directory(self, dir_or_path, name): + d = self.dirpath(dir_or_path) + d.addCallback(lambda parent: parent.callRemote("add_directory", name)) + return d + + def remove(self, parent, name): + assert not isinstance(parent, str) + log.msg("vdrive removing %s" % name) + # first find the verifierid + d = self.get_verifierid_from_parent(parent, name) + def _got_verifierid(vid): + # TODO: delete the file's shares using this + pass + d.addCallback(_got_verifierid) + def _delete_from_parent(res): + return parent.callRemote("remove", name) + d.addCallback(_delete_from_parent) + def _done(res): + log.msg("vdrive done removing %s" % name) + d.addCallback(_done) + return d + + + def get_file(self, dir_and_name_or_path, download_target): + """Retrieve a file from the virtual drive and put it somewhere. + + The file to be retrieved may either be specified as a (dir, name) + tuple or as a full /-delimited pathname. In the former case, 'dir' + can be either a DirectoryNode or a pathname. + + The download target must be an IDownloadTarget instance like + allmydata.download.Data, .FileName, or .FileHandle . + """ + + log.msg("getting file from %s" % (dir_and_name_or_path,)) + dl = self.parent.getServiceNamed("downloader") + + if isinstance(dir_and_name_or_path, tuple): + dir_or_path, name = dir_and_name_or_path + d = self.dirpath(dir_or_path) + def _got_dir(dirnode): + return self.get_verifierid_from_parent(dirnode, name) + d.addCallback(_got_dir) + else: + rslash = dir_and_name_or_path.rfind("/") + if rslash == -1: + # we're looking for a file in the root directory + dir = self.gvd_root + name = dir_and_name_or_path + d = self.get_verifierid_from_parent(dir, name) + else: + dirpath = dir_and_name_or_path[:rslash] + name = dir_and_name_or_path[rslash+1:] + d = self.dirpath(dirpath) + d.addCallback(lambda dir: + self.get_verifierid_from_parent(dir, name)) + + def _got_verifierid(verifierid): + return dl.download(verifierid, download_target) + d.addCallback(_got_verifierid) + def _done(res): + log.msg("finished getting file") + return res + d.addCallback(_done) + return d + + def get_file_to_filename(self, from_where, filename): + return self.get_file(from_where, download.FileName(filename)) + def get_file_to_data(self, from_where): + return self.get_file(from_where, download.Data()) + def get_file_to_filehandle(self, from_where, filehandle): + return self.get_file(from_where, download.FileHandle(filehandle)) + diff --git a/src/allmydata/web/directory.xhtml b/src/allmydata/web/directory.xhtml new file mode 100644 index 00000000..38a09c9c --- /dev/null +++ b/src/allmydata/web/directory.xhtml @@ -0,0 +1,39 @@ + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + +
FilenameTypefileid
directory is empty!
+ +
+ + + + + diff --git a/src/allmydata/web/welcome.xhtml b/src/allmydata/web/welcome.xhtml new file mode 100644 index 00000000..7adb96ae --- /dev/null +++ b/src/allmydata/web/welcome.xhtml @@ -0,0 +1,39 @@ + + + Welcome To AllMyData (tahoe2) + + + + + + +

Welcome To AllMyData! (tahoe2)

+ +

To view the global shared filestore, Click Here!

+ +

Mesh Status

+ +
Queen:
+
Connected to queen?:
+
Known Peers:
+
Connected Peers:
+ +
+ + + + + + + + + + +
PeerIDConnected?
no peers!
+
+ +
+ + + diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py new file mode 100644 index 00000000..4de899db --- /dev/null +++ b/src/allmydata/webish.py @@ -0,0 +1,331 @@ + +from twisted.application import service, strports +from twisted.web import static, resource, server, html +from twisted.python import util, log +from nevow import inevow, rend, loaders, appserver, url, tags as T +from allmydata.util import idlib +from allmydata.download import IDownloadTarget#, IDownloader +from allmydata import upload +from zope.interface import implements, Interface +import urllib +from formless import annotate, webform + +def getxmlfile(name): + return loaders.xmlfile(util.sibpath(__file__, "web/%s" % name)) + +class IClient(Interface): + pass + +def get_downloader_service(ctx): + return IClient(ctx).getServiceNamed("downloader") +def get_uploader_service(ctx): + return IClient(ctx).getServiceNamed("uploader") +def get_vdrive_service(ctx): + return IClient(ctx).getServiceNamed("vdrive") + +class Welcome(rend.Page): + addSlash = True + docFactory = getxmlfile("welcome.xhtml") + + def data_queen_pburl(self, ctx, data): + return IClient(ctx).queen_pburl + def data_connected_to_queen(self, ctx, data): + if IClient(ctx).queen: + return "yes" + return "no" + def data_num_peers(self, ctx, data): + #client = inevow.ISite(ctx)._client + client = IClient(ctx) + return len(client.all_peers) + def data_num_connected_peers(self, ctx, data): + return len(IClient(ctx).connections) + def data_peers(self, ctx, data): + return sorted(IClient(ctx).all_peers) + def render_row(self, ctx, data): + if data in IClient(ctx).connections: + connected = "yes" + else: + connected = "no" + ctx.fillSlots("peerid", idlib.b2a(data)) + ctx.fillSlots("connected", connected) + return ctx.tag + + # this is a form where users can download files by URI + + def bind_download(self, ctx): + uriarg = annotate.Argument("uri", + annotate.String("URI of file to download: ")) + namearg = annotate.Argument("filename", + annotate.String("Filename to download as: ")) + ctxarg = annotate.Argument("ctx", annotate.Context()) + meth = annotate.Method(arguments=[uriarg, namearg, ctxarg], + label="Download File by URI") + # buttons always use value=data.label + # MethodBindingRenderer uses value=(data.action or data.label) + return annotate.MethodBinding("download", meth, action="Download") + + def download(self, uri, filename, ctx): + log.msg("webish downloading URI") + target = url.here.sibling("download_uri").add("uri", uri) + if filename: + target = target.add("filename", filename) + return target + + def render_forms(self, ctx, data): + return webform.renderForms() + + +class Directory(rend.Page): + addSlash = True + docFactory = getxmlfile("directory.xhtml") + + def __init__(self, dirnode, dirname): + self._dirnode = dirnode + self._dirname = dirname + + def childFactory(self, ctx, name): + if name.startswith("freeform"): # ick + return None + if self._dirname == "/": + dirname = "/" + name + else: + dirname = self._dirname + "/" + name + d = self._dirnode.callRemote("get", name) + def _got_child(res): + if isinstance(res, str): + dl = get_downloader_service(ctx) + return Downloader(dl, name, res) + return Directory(res, dirname) + d.addCallback(_got_child) + return d + + def render_title(self, ctx, data): + return ctx.tag["Directory of '%s':" % self._dirname] + + def render_header(self, ctx, data): + return "Directory of '%s':" % self._dirname + + def data_children(self, ctx, data): + d = self._dirnode.callRemote("list") + return d + + def render_row(self, ctx, data): + name, target = data + if isinstance(target, str): + # file + dlurl = urllib.quote(name) + ctx.fillSlots("filename", + T.a(href=dlurl)[html.escape(name)]) + ctx.fillSlots("type", "FILE") + uri = idlib.b2a(target) + dl_uri_url = url.root.child("download_uri").child(uri) + # add a filename= query argument to give it a Content-Type + dl_uri_url = dl_uri_url.add("filename", name) + ctx.fillSlots("fileid", T.a(href=dl_uri_url)[html.escape(uri)]) + + # this creates a button which will cause our child__delete method + # to be invoked, which deletes the file and then redirects the + # browser back to this directory + del_url = url.here.child("_delete") + #del_url = del_url.add("verifierid", idlib.b2a(target)) + del_url = del_url.add("name", name) + delete = T.form(action=del_url, method="post")[ + T.input(type='submit', value='del', name="del"), + ] + ctx.fillSlots("delete", delete) + else: + # directory + subdir_url = urllib.quote(name) + ctx.fillSlots("filename", + T.a(href=subdir_url)[html.escape(name)]) + ctx.fillSlots("type", "DIR") + ctx.fillSlots("fileid", "-") + ctx.fillSlots("delete", "-") + return ctx.tag + + def render_forms(self, ctx, data): + return webform.renderForms() + + def bind_upload(self, ctx): + """upload1""" + # Note: this comment is no longer accurate, as it reflects the older + # (apparently deprecated) formless.autocallable / + # annotate.TypedInterface approach. + + # Each method gets a box. The string in the autocallable(action=) + # argument is put on the border of the box, as well as in the submit + # button. The top-most contents of the box are the method's + # docstring, if any. Each row contains a string for the argument + # followed by the argument's input box. If you do not provide an + # action= argument to autocallable, the method name is capitalized + # and used instead. + up = annotate.FileUpload(label="Choose a file to upload: ", + required=True, + requiredFailMessage="Do iT!") + contentsarg = annotate.Argument("contents", up) + + ctxarg = annotate.Argument("ctx", annotate.Context()) + meth = annotate.Method(arguments=[contentsarg, ctxarg], + label="Upload File to this directory") + return annotate.MethodBinding("upload", meth, action="Upload") + + def upload(self, contents, ctx): + # contents is a cgi.FieldStorage instance + log.msg("starting webish upload") + + uploader = get_uploader_service(ctx) + d = uploader.upload(upload.Data(contents.value)) + name = contents.filename + d.addCallback(lambda vid: + self._dirnode.callRemote("add_file", name, vid)) + def _done(res): + log.msg("webish upload complete") + return res + d.addCallback(_done) + return d + return url.here.add("results", + "upload of '%s' complete!" % contents.filename) + + def bind_mkdir(self, ctx): + """Make new directory 1""" + namearg = annotate.Argument("name", + annotate.String("New directory name: ")) + meth = annotate.Method(arguments=[namearg], label="Make New Subdirectory") + return annotate.MethodBinding("mkdir", meth, action="Create Directory") + + def mkdir(self, name): + """mkdir2""" + log.msg("making new webish directory") + d = self._dirnode.callRemote("add_directory", name) + def _done(res): + log.msg("webish mkdir complete") + return res + d.addCallback(_done) + return d + + def child__delete(self, ctx): + # perform the delete, then redirect back to the directory page + args = inevow.IRequest(ctx).args + vdrive = get_vdrive_service(ctx) + d = vdrive.remove(self._dirnode, args["name"][0]) + def _deleted(res): + return url.here.up() + d.addCallback(_deleted) + return d + +class WebDownloadTarget: + implements(IDownloadTarget) + def __init__(self, req): + self._req = req + def open(self): + pass + def write(self, data): + self._req.write(data) + def close(self): + self._req.finish() + def fail(self): + self._req.finish() + def register_canceller(self, cb): + pass + def finish(self): + pass + +class TypedFile(static.File): + # serve data from a named file, but using a Content-Type derived from a + # different filename + isLeaf = True + def __init__(self, path, requested_filename): + static.File.__init__(self, path) + gte = static.getTypeAndEncoding + self.type, self.encoding = gte(requested_filename, + self.contentTypes, + self.contentEncodings, + self.defaultType) + +class Downloader(resource.Resource): + def __init__(self, downloader, name, verifierid): + self._downloader = downloader + self._name = name + self._verifierid = verifierid + + def render(self, ctx): + req = inevow.IRequest(ctx) + gte = static.getTypeAndEncoding + type, encoding = gte(self._name, + static.File.contentTypes, + static.File.contentEncodings, + defaultType="text/plain") + req.setHeader("content-type", type) + if encoding: + req.setHeader('content-encoding', encoding) + + t = WebDownloadTarget(req) + #dl = IDownloader(ctx) + dl = self._downloader + dl.download(self._verifierid, t) + return server.NOT_DONE_YET + + + +class Root(rend.Page): + def locateChild(self, ctx, segments): + if segments[0] == "download_uri": + req = inevow.IRequest(ctx) + dl = get_downloader_service(ctx) + filename = "unknown_filename" + if "filename" in req.args: + filename = req.args["filename"][0] + if len(segments) > 1: + # http://host/download_uri/URIGOESHERE + uri_a = segments[1] + elif "uri" in req.args: + # http://host/download_uri?uri=URIGOESHERE + uri_a = req.args["uri"][0] + else: + return rend.NotFound + child = Downloader(dl, filename, idlib.a2b(uri_a)) + return child, () + return rend.Page.locateChild(self, ctx, segments) + + child_webform_css = webform.defaultCSS + + child_welcome = Welcome() + + +class WebishServer(service.MultiService): + name = "webish" + + def __init__(self, webport): + service.MultiService.__init__(self) + self.root = Root() + placeholder = static.Data("sorry, still initializing", "text/plain") + self.root.putChild("vdrive", placeholder) + self.root.putChild("", url.here.child("welcome"))#Welcome()) + + self.site = site = appserver.NevowSite(self.root) + s = strports.service(webport, site) + s.setServiceParent(self) + self.listener = s # stash it so the tests can query for the portnum + + def startService(self): + service.MultiService.startService(self) + # to make various services available to render_* methods, we stash a + # reference to the client on the NevowSite. This will be available by + # adapting the 'context' argument to a special marker interface named + # IClient. + self.site.remember(self.parent, IClient) + # I thought you could do the same with an existing interface, but + # apparently 'ISite' does not exist + #self.site._client = self.parent + + def set_root_dirnode(self, dirnode): + self.root.putChild("vdrive", Directory(dirnode, "/")) + # I tried doing it this way and for some reason it didn't seem to work + #print "REMEMBERING", self.site, dl, IDownloader + #self.site.remember(dl, IDownloader) + + +# TODO: figleaf gets confused when the last line of a file is a comment. I +# suspect an off-by-one error in the code that decides which lines are code +# and which are not. +pass