From: Brian Warner Date: Thu, 14 Dec 2006 10:25:30 +0000 (-0700) Subject: first cut at creating allmydata.Crypto, starting with python-amycrypto-2.0.1.allmydat... X-Git-Tag: tahoe_v0.1.0-0-UNSTABLE~433 X-Git-Url: https://git.rkrishnan.org/components/com_hotproperty/%22doc.html/index.php?a=commitdiff_plain;h=8a3af8827ab3490576d045b7a9c87b7f1e410552;p=tahoe-lafs%2Ftahoe-lafs.git first cut at creating allmydata.Crypto, starting with python-amycrypto-2.0.1.allmydata2 (with working CTR mode) --- diff --git a/Crypto/ACKS b/Crypto/ACKS new file mode 100644 index 00000000..2acfc304 --- /dev/null +++ b/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/Crypto/ChangeLog b/Crypto/ChangeLog new file mode 100644 index 00000000..30e325c1 --- /dev/null +++ b/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/Crypto/Cipher/__init__.py b/Crypto/Cipher/__init__.py new file mode 100644 index 00000000..9f8096ae --- /dev/null +++ b/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/Crypto/Demo/README b/Crypto/Demo/README new file mode 100644 index 00000000..0e48d7c3 --- /dev/null +++ b/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/Crypto/Demo/chaum.py b/Crypto/Demo/chaum.py new file mode 100644 index 00000000..a2d3ec22 --- /dev/null +++ b/Crypto/Demo/chaum.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +""" Example of Chaumian blinding """ + +import time, pprint, os, sha +from Crypto.PublicKey import * +from Crypto.Util.randpool import RandomPool +from 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 new file mode 100644 index 00000000..8533c87e --- /dev/null +++ b/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/Crypto/Demo/enc.py b/Crypto/Demo/enc.py new file mode 100644 index 00000000..1d6924c9 --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..94a6e30e --- /dev/null +++ b/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/Crypto/Demo/secimp/secimp.py b/Crypto/Demo/secimp/secimp.py new file mode 100644 index 00000000..ad3ebc9c --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..f9891599 --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..e8fef6c7 --- /dev/null +++ b/Crypto/Demo/secimp/testkey.py @@ -0,0 +1,41 @@ + +import sys +import Crypto.PublicKey.DSA + +key = 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 Crypto.PublicKey import DSA + from 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 = 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 new file mode 100644 index 00000000..d9c9bf62 --- /dev/null +++ b/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/Crypto/Hash/HMAC.py b/Crypto/Hash/HMAC.py new file mode 100644 index 00000000..eeb57823 --- /dev/null +++ b/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/Crypto/Hash/MD5.py b/Crypto/Hash/MD5.py new file mode 100644 index 00000000..b0eba394 --- /dev/null +++ b/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/Crypto/Hash/SHA.py b/Crypto/Hash/SHA.py new file mode 100644 index 00000000..ea3c6a34 --- /dev/null +++ b/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/Crypto/Hash/__init__.py b/Crypto/Hash/__init__.py new file mode 100644 index 00000000..30cbe1b6 --- /dev/null +++ b/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/Crypto/LICENSE b/Crypto/LICENSE new file mode 100644 index 00000000..ad3ae419 --- /dev/null +++ b/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/Crypto/MANIFEST b/Crypto/MANIFEST new file mode 100644 index 00000000..d19134e2 --- /dev/null +++ b/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/Crypto/PKG-INFO b/Crypto/PKG-INFO new file mode 100644 index 00000000..764da08a --- /dev/null +++ b/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/Crypto/Protocol/AllOrNothing.py b/Crypto/Protocol/AllOrNothing.py new file mode 100644 index 00000000..6f3505d2 --- /dev/null +++ b/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 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 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__('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 new file mode 100644 index 00000000..fdfb82d0 --- /dev/null +++ b/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 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 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 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 new file mode 100644 index 00000000..a6d68bcf --- /dev/null +++ b/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/Crypto/PublicKey/DSA.py b/Crypto/PublicKey/DSA.py new file mode 100644 index 00000000..7947b6f5 --- /dev/null +++ b/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 Crypto.PublicKey.pubkey import * +from Crypto.Util import number +from Crypto.Util.number import bytes_to_long, long_to_bytes +from Crypto.Hash import SHA + +try: + from 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 new file mode 100644 index 00000000..026881c9 --- /dev/null +++ b/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 Crypto.PublicKey.pubkey import * +from 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 new file mode 100644 index 00000000..e0e877ec --- /dev/null +++ b/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 Crypto.PublicKey import pubkey +from Crypto.Util import number + +try: + from 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 new file mode 100644 index 00000000..ad1c80ca --- /dev/null +++ b/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/Crypto/PublicKey/pubkey.py b/Crypto/PublicKey/pubkey.py new file mode 100644 index 00000000..5c75c3e3 --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..65f8ae36 --- /dev/null +++ b/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 Crypto.PublicKey import pubkey +from Crypto.Util.number import * +from 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 new file mode 100644 index 00000000..e2b07d66 --- /dev/null +++ b/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 Crypto.PublicKey import * +from Crypto.Util.randpool import RandomPool +from 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 new file mode 100644 index 00000000..c0a134f7 --- /dev/null +++ b/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/Crypto/TODO b/Crypto/TODO new file mode 100644 index 00000000..a79ad719 --- /dev/null +++ b/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/Crypto/Util/RFC1751.py b/Crypto/Util/RFC1751.py new file mode 100644 index 00000000..0a479524 --- /dev/null +++ b/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/Crypto/Util/__init__.py b/Crypto/Util/__init__.py new file mode 100644 index 00000000..0d147681 --- /dev/null +++ b/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/Crypto/Util/bench.py b/Crypto/Util/bench.py new file mode 100644 index 00000000..ae181b5f --- /dev/null +++ b/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 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 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 new file mode 100644 index 00000000..9d50563e --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..467501c5 --- /dev/null +++ b/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 Crypto.Util.number import long_to_bytes +try: + import 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 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__('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 new file mode 100644 index 00000000..020fb146 --- /dev/null +++ b/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 Crypto.Cipher import * +from 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 new file mode 100644 index 00000000..320c132d --- /dev/null +++ b/Crypto/Util/test/prime_speed.py @@ -0,0 +1,24 @@ + +import time +from 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 new file mode 100644 index 00000000..b8626c4c --- /dev/null +++ b/Crypto/debian/compat @@ -0,0 +1 @@ +4 diff --git a/Crypto/debian/control b/Crypto/debian/control new file mode 100644 index 00000000..1e6f4e1a --- /dev/null +++ b/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/Crypto/debian/copyright b/Crypto/debian/copyright new file mode 100644 index 00000000..7f39a182 --- /dev/null +++ b/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/Crypto/debian/dirs b/Crypto/debian/dirs new file mode 100644 index 00000000..ca882bbb --- /dev/null +++ b/Crypto/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/Crypto/debian/pathmangle.sh b/Crypto/debian/pathmangle.sh new file mode 100644 index 00000000..32bf8ced --- /dev/null +++ b/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/Crypto/debian/python2.3-amdcrypto.docs b/Crypto/debian/python2.3-amdcrypto.docs new file mode 100644 index 00000000..9b472891 --- /dev/null +++ b/Crypto/debian/python2.3-amdcrypto.docs @@ -0,0 +1,4 @@ +README +TODO +debian/README.Debian +Doc/pycrypt.ps diff --git a/Crypto/debian/python2.4-amdcrypto.docs b/Crypto/debian/python2.4-amdcrypto.docs new file mode 100644 index 00000000..9b472891 --- /dev/null +++ b/Crypto/debian/python2.4-amdcrypto.docs @@ -0,0 +1,4 @@ +README +TODO +debian/README.Debian +Doc/pycrypt.ps diff --git a/Crypto/debian/rules b/Crypto/debian/rules new file mode 100644 index 00000000..6520a8ff --- /dev/null +++ b/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/Crypto/setup.py b/Crypto/setup.py new file mode 100644 index 00000000..94f7a08e --- /dev/null +++ b/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/Crypto/src/AES.c b/Crypto/src/AES.c new file mode 100644 index 00000000..cf9bba9f --- /dev/null +++ b/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/Crypto/src/ARC2.c b/Crypto/src/ARC2.c new file mode 100644 index 00000000..f1292e82 --- /dev/null +++ b/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/Crypto/src/ARC4.c b/Crypto/src/ARC4.c new file mode 100644 index 00000000..71df6fe7 --- /dev/null +++ b/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/Crypto/src/Blowfish.c b/Crypto/src/Blowfish.c new file mode 100644 index 00000000..df69afad --- /dev/null +++ b/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/Crypto/src/CAST.c b/Crypto/src/CAST.c new file mode 100644 index 00000000..395318db --- /dev/null +++ b/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/Crypto/src/DES.c b/Crypto/src/DES.c new file mode 100644 index 00000000..e35699f5 --- /dev/null +++ b/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/Crypto/src/DES3.c b/Crypto/src/DES3.c new file mode 100644 index 00000000..49bf6f48 --- /dev/null +++ b/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/Crypto/src/MD2.c b/Crypto/src/MD2.c new file mode 100644 index 00000000..aa53c59c --- /dev/null +++ b/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/Crypto/src/SHA256.c b/Crypto/src/SHA256.c new file mode 100644 index 00000000..6bd9df2b --- /dev/null +++ b/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/Crypto/src/XOR.c b/Crypto/src/XOR.c new file mode 100644 index 00000000..f2c74afa --- /dev/null +++ b/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/Crypto/src/_dsa.c b/Crypto/src/_dsa.c new file mode 100644 index 00000000..4752f438 --- /dev/null +++ b/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/Crypto/src/_fastmath.c b/Crypto/src/_fastmath.c new file mode 100644 index 00000000..7fe7abec --- /dev/null +++ b/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/Crypto/src/_rsa.c b/Crypto/src/_rsa.c new file mode 100644 index 00000000..e51d1884 --- /dev/null +++ b/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/Crypto/src/block_template.c b/Crypto/src/block_template.c new file mode 100644 index 00000000..37aa0453 --- /dev/null +++ b/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("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 new file mode 100644 index 00000000..0843b98d --- /dev/null +++ b/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/Crypto/src/hash_template.c b/Crypto/src/hash_template.c new file mode 100644 index 00000000..6662dd54 --- /dev/null +++ b/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("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 new file mode 100644 index 00000000..71d125c1 --- /dev/null +++ b/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("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 new file mode 100644 index 00000000..8c82bd45 --- /dev/null +++ b/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/Crypto/test.py b/Crypto/test.py new file mode 100644 index 00000000..97a4748a --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..dce6c9b4 --- /dev/null +++ b/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/Crypto/test/test_chaffing.py b/Crypto/test/test_chaffing.py new file mode 100644 index 00000000..a9d02965 --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..91630797 --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..776d33e4 --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..83fdea75 --- /dev/null +++ b/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 Crypto.PublicKey import * +from Crypto.Util.randpool import RandomPool +from 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 new file mode 100644 index 00000000..f1cb6a55 --- /dev/null +++ b/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 Crypto.Hash import SHA +from 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 new file mode 100644 index 00000000..c86fb4c8 --- /dev/null +++ b/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 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 new file mode 100644 index 00000000..3c21b8e8 --- /dev/null +++ b/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 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/setup.py b/setup.py index bb384b24..765990cd 100644 --- a/setup.py +++ b/setup.py @@ -2,14 +2,204 @@ #from setuptools import setup, find_packages from distutils.core import setup +from distutils.core import Extension +from distutils.command.build_ext import build_ext +import os, sys + +# we build and install a copy of pycrypto as allmydata.Crypto, because we've +# made some improvements that have not yet made it upstream (specifically a +# much faster version of CTR mode). To accomplish this, we must include a +# couple of pieces from the pycrypto setup.py file here. + +if sys.platform == 'win32': + HTONS_LIBS = ['ws2_32'] + plat_ext = [ + Extension("Crypto.Util.winrandom", + libraries = HTONS_LIBS + ['advapi32'], + include_dirs=['Crypto/src/'], + extra_compile_args=['-O0 -g',], + extra_link_args=['-g',], + undef_macros=['NDEBUG',], + sources=["Crypto/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): + debug_build_kw = {} + self.extensions += [ + # Hash functions + Extension("allmydata.Crypto.Hash.MD4", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/MD4.c"], + **debug_build_kw), + Extension("allmydata.Crypto.Hash.SHA256", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/SHA256.c"], + **debug_build_kw), + + # Block encryption algorithms + Extension("allmydata.Crypto.Cipher.AES", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/AES.c"], + **debug_build_kw), + Extension("allmydata.Crypto.Cipher.ARC2", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/ARC2.c"], + **debug_build_kw), + Extension("allmydata.Crypto.Cipher.Blowfish", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/Blowfish.c"], + **debug_build_kw), + Extension("allmydata.Crypto.Cipher.CAST", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/CAST.c"], + **debug_build_kw), + Extension("allmydata.Crypto.Cipher.DES", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/DES.c"], + **debug_build_kw), + Extension("allmydata.Crypto.Cipher.DES3", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/DES3.c"], + **debug_build_kw), + + # Stream ciphers + Extension("allmydata.Crypto.Cipher.ARC4", + include_dirs=['Crypto/src/'], + sources=["Crypto/src/ARC4.c"], + **debug_build_kw), + Extension("allmydata.Crypto.Cipher.XOR", + include_dirs=['Crypto/src/'], + sources=["Crypto/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("allmydata.Crypto.PublicKey._fastmath", + include_dirs=['Crypto/src/'], + libraries=['gmp'], + sources=["Crypto/src/_fastmath.c"])) + self.extensions += exts + + +# these are the setup() args for the original pycrypto module. We only use a +# subset of them. +""" +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)], + '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', + ] + } +""" + +# this is our actual setup() call 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" }, scripts = ["bin/allmydata"], package_data={ 'allmydata': ['web/*.xhtml'] }, + + cmdclass= {'build_ext': PCTBuildExt}, + # 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"])], + description="AllMyData (tahoe2)", )