diff options
author | akuchling <akuchling@rivest.dlitz.net> | 2005-05-09 14:20:57 -0700 |
---|---|---|
committer | akuchling <akuchling@rivest.dlitz.net> | 2005-05-09 14:20:57 -0700 |
commit | 816b39cfe28a6727f7535383a89c86dc7b2860aa (patch) | |
tree | 1a5257836fe8f22b652c386271d45cb7a142843a | |
parent | 44c61eb34ccac60ba5e3e5aacb93ae24c1311fe0 (diff) | |
download | pycrypto-816b39cfe28a6727f7535383a89c86dc7b2860aa.tar.gz |
[project @ akuchling-20050509212057-55ab47f8ceaba662]
[project @ 2005-05-09 14:20:54 by akuchling]
Remove Demo/ directory -- the code is old and possibly misleading, and no one is going to modernize it
-rw-r--r-- | Demo/README | 29 | ||||
-rw-r--r-- | Demo/chaum.py | 129 | ||||
-rwxr-xr-x | Demo/cipher | 150 | ||||
-rwxr-xr-x | Demo/enc.py | 334 | ||||
-rw-r--r-- | Demo/secimp/README | 24 | ||||
-rw-r--r-- | Demo/secimp/secimp.py | 84 | ||||
-rwxr-xr-x | Demo/secimp/sign.py | 46 | ||||
-rw-r--r-- | Demo/secimp/testkey.py | 41 | ||||
-rw-r--r-- | Doc/pycrypt.tex | 96 | ||||
-rw-r--r-- | MANIFEST | 8 | ||||
-rw-r--r-- | TODO | 5 |
11 files changed, 0 insertions, 946 deletions
diff --git a/Demo/README b/Demo/README deleted file mode 100644 index 0e48d7c..0000000 --- a/Demo/README +++ /dev/null @@ -1,29 +0,0 @@ -This directory contains demonstration files that use the modules -included in the Python Cryptography Toolkit. - -Note: These programs have version numbers of their own, which are not -necessarily the same as the version number of the Toolkit package. - -cipher Encrypt and decrypt sensitive files; type 'cipher -h' - for a usage message. - -voice Allows secure voice communication over a TCP/IP link. - Currently this is Linux-specific; changes to make it - run on other systems would be greatly appreciated. - -RSAgen.py Generates a new RSA key. Demonstrates using - randpool.py, and maintains a file of random data in - "randseed". Requires that the IDEA and MD5 modules - are installed. - -testkey.py RSA public/private key pair used by example programs. - -Secure importing of Python modules: - - sign.py Sign all *.pyc files in a directory, using the - key defined in testkey.py. - - secimp.py Implementation of the secure 'import' command. - - - diff --git a/Demo/chaum.py b/Demo/chaum.py deleted file mode 100644 index a2d3ec2..0000000 --- a/Demo/chaum.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/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/Demo/cipher b/Demo/cipher deleted file mode 100755 index 8533c87..0000000 --- a/Demo/cipher +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# -*-Python-*- -# Cipher 1.00 -# -# Part of the Python Cryptography Toolkit -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# - -import sys, getopt, os - -# Determine the name of this executable -executable = os.path.basename(sys.argv[0]) -if executable=='': executable='cipher' -cipher = '' # Unknown ciphering algorithm -key = (0, '') # Empty key -magic = 'ctx\001' # Magic string prefixed to the data -NoInputFile = '' # Exceptions raised on file errors -NoOutputFile = '' - -def PrintUsage(): - print 'Usage: cipher [OPTIONS] file1 file2 ...' - print '\n -c ciphername Force use of ciphername to encrypt/decrypt' - print ' -k key Key to use for encryption/decryption' - print '\nThe default cipher algorithm is IDEA; if no key is set on the command' - print 'line, you will be prompted to enter a key.' - print 'Files are read completely into memory, so do not try to encrypt' - print 'very large files.' - -def GenerateIV(length): - import whrandom - IV='' - for i in range(0, length): - IV=IV + chr(int(256*whrandom.random())) - return IV - -def Encipher(filename, cipher, key): - if (cipher==''): cipher='IDEA' - try: - exec ('from Crypto.Cipher import '+cipher) - module=eval(cipher) - except ImportError: - print executable+ ':', cipher, ': Cipher does not exist.' - sys.exit(1) - import Crypto.Hash.MD5 - try: - input=open(filename, 'r') - except IOError: - raise NoInputFile - try: - output=open(filename+'.cip', 'w') - except IOError: - raise NoOutputFile, filename+'.cip' - - if (key[0]==0): - key=raw_input('Enter encryption key for '+ filename+ ':') - else: key=key[1] - key=Crypto.Hash.MD5.new(key).digest() - IV='' - for i in range(0, module.blocksize): IV=IV+'A' - if (module.keysize==0): - cipherobj=module.new(key, module.CBC, IV) - else: - cipherobj=module.new(key[0:module.keysize], module.CBC, IV) - output.write(magic+cipher+'\0') - data = GenerateIV(module.blocksize) - filedata=input.read() - data = data + magic + str(len(filedata))+'\0'+filename+'\0' - data = data + filedata - input.close() - padding=module.blocksize - (len(data) % module.blocksize) - for i in range(0, padding): - data = data + chr(i) - ciphertext=cipherobj.encrypt(data) - output.write(ciphertext) - output.close() - -def Decipher(filename, cipher, key): - import Crypto.Hash.MD5, string - try: - input=open(filename, 'r') - except IOError: - raise NoInputFile - if (input.read(len(magic))!=magic): - print executable+':', filename+': Does not seem to be a ciphered file' - return - t='' - while (1): - c=input.read(1) - if (ord(c)==0): break - t=t+c - if (cipher==''): cipher=t - try: - from Crypto.Cipher import * - module=eval(cipher) - except ImportError: - print executable+ ':', cipher, ': Cipher does not exist.' - sys.exit(1) - if (key[0]==0): - key=raw_input('Enter encryption key for '+ filename+ ':') - else: key=key[1] - key=Crypto.Hash.MD5.new(key).digest() - IV = '' - for i in range(0, module.blocksize): IV=IV+'A' - data=input.read() - if (module.keysize==0): - cipherobj=module.new(key, module.CBC, IV) - else: - cipherobj=module.new(key[0:module.keysize], module.CBC, IV) - plain=cipherobj.decrypt(data) # Decrypt the data - plain=plain[module.blocksize:] # Discard first block of random data - if (plain[0:len(magic)]!=magic): - print executable+':', filename+': Incorrect key or cipher algorithm' - return - else: plain=plain[len(magic):] - i=string.find(plain, '\0') - length=string.atoi(plain[0:i]) - j=string.find(plain, '\0', i+1) - newfilename=plain[i+1:j] - try: - output=open(newfilename, 'w') - except IOError: - raise NoOutputFile, newfilename - output.write(plain[j+1:j+1+length]) - output.close() - -if len(sys.argv)==1: PrintUsage() ; sys.exit(0) - -options, args=getopt.getopt(sys.argv[1:], 'c:k:hH') -for opt in options: - letter, param = opt - if (letter=='-c'): cipher = param - if (letter=='-k'): key = (1, param) - if (letter=='-h' or letter=='-H'): - PrintUsage() - sys.exit(0) - -for file in args: - try: - if (file[-4:]=='.cip'): - Decipher(file, cipher, key) - else: - Encipher(file, cipher, key) - except NoInputFile: - print executable+ ':', file+ ': No such file.' - except NoOutputFile, filename: - print executable+ ':', filename+ ': Cannot open file' - diff --git a/Demo/enc.py b/Demo/enc.py deleted file mode 100755 index 1d6924c..0000000 --- a/Demo/enc.py +++ /dev/null @@ -1,334 +0,0 @@ -#!/usr/local/bin/python -Ou - -""" enc - encrypt/decrypt files using one of SSLeay's ciphers. - - Copyright (c) 1998 by Marc-Andre Lemburg; All Rights Reserved; - mailto:mal@lemburg.com; See the documentation for further - copyright information or contact the author. - - DISCLAIMER & WARNING: This tool comes with NO WARRANTY. Use at - YOUR OWN RISK. It may destroy data ! There is NO way to recover a - forgotten pass phrase ! -""" -import exceptions,os,string,time,sys -from 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/Demo/secimp/README b/Demo/secimp/README deleted file mode 100644 index 94a6e30..0000000 --- a/Demo/secimp/README +++ /dev/null @@ -1,24 +0,0 @@ - -This is a simple demonstration of adding an import hook that verifies -a digital signature on a Python code object before allowing it to be -imported. There are three files: - - * sign.py, which signs all the *.pyc files in the directories -listed on the command line. The contents of the .pyc file is stored -along with the signature in a file whose name ends with .pys . - - * secimp.py, which implements a secimport() function which -will use *.pys files. - - * testkey.py is the key used to sign and verify *.pys files. - -To try it out: - 1. Run "sign.py ." to compile and sign all the *.py files in -the current directory. - - 2. Run secimp.py from the command-line; it will try to -securely import testkey.pys, which should succeed. - - 3. Fire up your favorite editor, and change a single byte in a -string somewhere in testkey.pys. Run secimp.py again; it should raise -an exception when the signature can't be verified. diff --git a/Demo/secimp/secimp.py b/Demo/secimp/secimp.py deleted file mode 100644 index d4f38fc..0000000 --- a/Demo/secimp/secimp.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/local/bin/python - -import sys ; sys.path = ['../../../'] + sys.path - -import imp, os -from sys import modules - -# Secure import: -def secimport(name, globals=None, locals=None, fromlist=None): - # Fast path: let's see if it's already in sys.modules. - # Two speed optimizations are worth mentioning: - # - We use 'modules' instead of 'sys.modules'; this saves a - # dictionary look-up per call. - # - It's also faster to use a try-except statement than - # to use modules.has_key(name) to check if it's there. - try: - return modules[name] - except KeyError: - pass - - # See if it's a built-in module - m = imp.init_builtin(name) - if m: - return m - - # See if it's a frozen module - m = imp.init_frozen(name) - if m: - return m - - # Search the default path (i.e. sys.path). - # If this raises an exception, the module is not found -- - # let the caller handle the exception. - fp, pathname, (suffix, mode, type) = imp.find_module(name) - - # See what we got... - # Note that fp will be closed automatically when we return. - - # Extensions are written in C, and can just be loaded. - if type == imp.C_EXTENSION: - return imp.load_dynamic(name, pathname) - - # For a compiled or source file, we'll check if there is a *.pys file - # present in the same directory. - if type == imp.PY_COMPILED or type == imp.PY_SOURCE: - root, ext = os.path.splitext(pathname) - testfile = root + '.pys' - try: - print testfile - secfile=open(testfile, 'rb') - except IOError, tuple: - if (tuple[0]==2): pass # Ignore 'file not found' error - else: raise IOError, tuple - else: - # Check the signature (a signed hash of the code object). - # We could sign the whole code object, but that would - # require a huge key and would double the size of the - # *.pys file. - import marshal - from Crypto.Hash import MD5 - fp.close() # Close the original *.pyc file - from testkey import key # 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/Demo/secimp/sign.py b/Demo/secimp/sign.py deleted file mode 100755 index f989159..0000000 --- a/Demo/secimp/sign.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python - -# Using the public key defined in testkey.py, sign all *.pyc files in -# the listed directories. - -from testkey import * -from 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/Demo/secimp/testkey.py b/Demo/secimp/testkey.py deleted file mode 100644 index e8fef6c..0000000 --- a/Demo/secimp/testkey.py +++ /dev/null @@ -1,41 +0,0 @@ - -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/Doc/pycrypt.tex b/Doc/pycrypt.tex index 926c422..1e38640 100644 --- a/Doc/pycrypt.tex +++ b/Doc/pycrypt.tex @@ -1065,102 +1065,6 @@ the number of words in \var{string} must be a multiple of 6. %====================================================================== -\section{The Demonstration Programs} - -The Python Cryptography Toolkit comes with various demonstration -programs, located in the \file{Demo/} directory. None of them is -particularly well-finished or suitable for serious use. Rather, -they're intended to illustrate how the toolkit is used, and to provide -some interesting possible uses. Feel free to incorporate the code (or -modifications of it) into your own programs. - -\subsection{Demo 1: \file{cipher}} - -\file{cipher} encrypts and decrypts files. On most Unix systems, the -\file{crypt} program uses a variant of the Enigma cipher. This is not -secure, and there exists a freely available program called ``Crypt -Breaker's Workbench'' which helps in breaking the cipher if you have -some knowledge of the encrypted data. - -\file{cipher} is a more secure file encryption program. Simply list -the names of the files to be encrypted on the command line. -\file{cipher} will go through the list and encrypt or decrypt them; -\file{cipher} can recognize files it has previously encrypted. The -ciphertext of a file is placed in a file of the same name with -'\samp{.cip}' appended; the original file is not deleted, since I'm -not sure that all errors during operation are caught, and I don't want -people to accidentally erase important files. - -There are two command-line options: \programopt{-c} and -\programopt{-k}. Both of them require an argument. \code{-c -\var{ciphername}} uses the given encryption algorithm -\var{ciphername}; for example, \code{-c des} will use the DES -algorithm. The name should be the same as an available module name; -thus it should be in lowercase letters. The default cipher is IDEA. - -\code{-k \var{key}} can be used to set the encryption key to be used. -Note that on a multiuser Unix system, the \code{ps} command can be -used to view the arguments of commands executed by other users, so -this is insecure; if you're the only user (say, on your home computer -running Linux) you don't have to worry about this. If no key is set -on the command line, \file{cipher} will prompt the user to input a key -on standard input. - - -\subsubsection{Technical Details} - -The encrypted file is not pure ciphertext. First comes a magic -string; this is currently the sequence \samp{ctx} and a byte -containing 1 (the version number of \file{cipher}). -This is followed by the null-terminated name of the encryption -algorithm, and the rest of the file contains the ciphertext. - -The plaintext is encrypted in CBC mode. The initial value for the -feedback is always set to a block filled with the letter 'A', and then -a block of random data is encrypted. This garbage block will be -discarded on decryption. Note that the random data is not generated -in a cryptographically secure way, and this may provide a tiny foothold for -an attacker. - -After the random block is generated, the magic string, length of the -original file, and original filename are all encrypted before the file -data is finally processed. Some extra characters of padding may be -added to obtain an integer number of blocks. This padding will also -be discarded on decryption. Note that the plaintext file will be -completely read into memory before encryption is performed; no -buffering is done. Therefore, don't encrypt 20-megabyte files unless -you're willing to face the consequences of a 20-megabyte process. - -Areas for improvements to \file{cipher} are: cryptographically secure -generation of random data for padding, key entry, and buffering of -file input. - - -\subsection{Demo 2: \file{secimp} and \file{sign}} - -\file{secimp} demonstrates an application of the Toolkit that may be -useful if Python is being used as an extension language for mail and Web -clients: secure importing of Python modules. To use it, run -\file{sign.py} in a directory with several compiled Python files -present. It will use the key in \file{testkey.py} to generate digital -signatures for the compiled Python code, and save both the signature and -the code in a file ending in \samp{.pys}. Then run \code{python -i -secimp.py}, and import a file by using \code{secimport}. - -For example, if \file{foo.pys} was constructed, do -\code{secimport('foo')}. The import should succeed. Now fire up Emacs -or some other editor, and change a string in the code in \file{foo.pys}; -you might try changing a letter in the name of a variable. When you run -\code{secimport('foo')}, it should raise an exception reporting the -failed signature. If you execute the statement \code{__import__ = -secimport}, the secure import will be used by default for all future -module imports. Alternatively, if you were creating a restricted -execution environment using \file{rexec.py}, you could place -\code{secimport()} in the restricted environment's namespace as the -default import function. - - -%====================================================================== \section{Extending the Toolkit} Preserving the a common interface for cryptographic routines is a good @@ -1,14 +1,6 @@ ACKS ChangeLog Cipher/__init__.py -Demo/README -Demo/chaum.py -Demo/cipher -Demo/enc.py -Demo/secimp/README -Demo/secimp/secimp.py -Demo/secimp/sign.py -Demo/secimp/testkey.py Doc/pycrypt.tex Hash/HMAC.py Hash/MD5.py @@ -3,8 +3,6 @@ * Manual and Web page: point to SF project for bug reports -* Update the demos - * Update documentation (mention dodgy status of PublicKey code) * Clean up markup in pycrypt.tex @@ -27,9 +25,6 @@ time. * A secret sharing module should be added to Util or Protocols. -Demo programs: - Shadowing of files into X parts - Documentation: Document chaff/winnow better Add docstrings everywhere. |