2002-04-03 18:45:09 -07:00
|
|
|
#! /usr/bin/env python
|
2002-07-11 14:31:19 -07:00
|
|
|
|
2008-08-06 21:27:50 -04:00
|
|
|
__revision__ = "$Id$"
|
2002-07-11 14:31:19 -07:00
|
|
|
|
2003-02-28 17:55:21 -07:00
|
|
|
from distutils import core
|
2008-11-21 13:04:18 -05:00
|
|
|
from distutils.core import Extension, Command
|
2003-02-28 17:38:29 -07:00
|
|
|
from distutils.command.build_ext import build_ext
|
|
|
|
import os, sys
|
2008-09-15 21:32:58 -04:00
|
|
|
import struct
|
2002-04-03 18:45:09 -07:00
|
|
|
|
2002-07-18 13:05:37 -07:00
|
|
|
if sys.version[0:1] == '1':
|
|
|
|
raise RuntimeError, ("The Python Cryptography Toolkit requires "
|
|
|
|
"Python 2.x to build.")
|
|
|
|
|
2002-06-19 13:07:12 -07:00
|
|
|
if sys.platform == 'win32':
|
|
|
|
HTONS_LIBS = ['ws2_32']
|
2002-10-23 04:52:20 -07:00
|
|
|
plat_ext = [
|
2008-09-17 11:00:45 -04:00
|
|
|
Extension("Crypto.Random.OSRNG.winrandom",
|
2002-10-23 04:52:20 -07:00
|
|
|
libraries = HTONS_LIBS + ['advapi32'],
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/winrand.c"])
|
|
|
|
]
|
2002-06-19 13:07:12 -07:00
|
|
|
else:
|
|
|
|
HTONS_LIBS = []
|
2002-10-23 04:52:20 -07:00
|
|
|
plat_ext = []
|
2003-02-28 17:38:29 -07:00
|
|
|
|
2008-08-13 23:11:05 -04:00
|
|
|
# List of pure Python modules that will be excluded from the binary packages.
|
|
|
|
# The list consists of (package, module_name) tuples
|
|
|
|
from distutils.command.build_py import build_py
|
|
|
|
EXCLUDE_PY = [
|
2008-08-14 16:57:22 -04:00
|
|
|
('Crypto', 'test'), # Top-level test module (it doesn't work outside the source tree anyway)
|
|
|
|
('Crypto.Hash', 'RIPEMD160'), # Included for your amusement, but the C version is much faster.
|
2008-08-13 23:11:05 -04:00
|
|
|
]
|
|
|
|
|
2003-02-28 17:38:29 -07:00
|
|
|
# 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
|
|
|
|
|
2008-09-15 21:32:58 -04:00
|
|
|
def endianness_macro():
|
2008-09-16 12:48:24 -04:00
|
|
|
s = struct.pack("@I", 0x33221100)
|
2008-09-15 21:32:58 -04:00
|
|
|
if s == "\x00\x11\x22\x33": # little endian
|
|
|
|
return ('PCT_LITTLE_ENDIAN', 1)
|
|
|
|
elif s == "\x33\x22\x11\x00": # big endian
|
|
|
|
return ('PCT_BIG_ENDIAN', 1)
|
|
|
|
raise AssertionError("Machine is neither little-endian nor big-endian")
|
|
|
|
|
2003-02-28 17:38:29 -07:00
|
|
|
class PCTBuildExt (build_ext):
|
|
|
|
def build_extensions(self):
|
|
|
|
self.extensions += [
|
|
|
|
# Hash functions
|
|
|
|
Extension("Crypto.Hash.MD4",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/MD4.c"]),
|
2003-12-19 15:24:25 -07:00
|
|
|
Extension("Crypto.Hash.SHA256",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/SHA256.c"]),
|
2008-08-14 16:57:22 -04:00
|
|
|
Extension("Crypto.Hash.RIPEMD160",
|
|
|
|
include_dirs=['src/'],
|
2008-09-15 21:32:58 -04:00
|
|
|
sources=["src/RIPEMD160.c"],
|
|
|
|
define_macros=[endianness_macro()]),
|
2003-02-28 17:38:29 -07:00
|
|
|
|
|
|
|
# Block encryption algorithms
|
|
|
|
Extension("Crypto.Cipher.AES",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/AES.c"]),
|
|
|
|
Extension("Crypto.Cipher.ARC2",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/ARC2.c"]),
|
Remove Blowfish, DES, DES3, IDEA, RC5, and XOR modules
Because:
- Blowfish: Uses the original (ambiguous) PyCrypto license. The
documentation says "the Blowfish algorithm has been placed in the public
domain and can be used freely", but this seems to be referring to
patents, not copyright.
- DES: The file says "Copyright (C) 1993 Eric Young", and appears to have
been taken from SSLeay. The license of SSLeay is not GPL-compatible,
since it has an advertising clause.
- DES3: Same reason as for the DES module.
- IDEA: Patent-encumbered.
- RC5: Patent-encumbered.
- XOR: Insecure as a stream cipher, and it silently truncates "keys"
to 32 bytes. The strxor module is a better replacement if you want to
do a bitwise exclusive-or between strings.
2009-03-01 09:51:00 -05:00
|
|
|
# Extension("Crypto.Cipher.Blowfish",
|
|
|
|
# include_dirs=['src/'],
|
|
|
|
# sources=["src/Blowfish.c"]),
|
2003-02-28 17:38:29 -07:00
|
|
|
Extension("Crypto.Cipher.CAST",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/CAST.c"]),
|
Remove Blowfish, DES, DES3, IDEA, RC5, and XOR modules
Because:
- Blowfish: Uses the original (ambiguous) PyCrypto license. The
documentation says "the Blowfish algorithm has been placed in the public
domain and can be used freely", but this seems to be referring to
patents, not copyright.
- DES: The file says "Copyright (C) 1993 Eric Young", and appears to have
been taken from SSLeay. The license of SSLeay is not GPL-compatible,
since it has an advertising clause.
- DES3: Same reason as for the DES module.
- IDEA: Patent-encumbered.
- RC5: Patent-encumbered.
- XOR: Insecure as a stream cipher, and it silently truncates "keys"
to 32 bytes. The strxor module is a better replacement if you want to
do a bitwise exclusive-or between strings.
2009-03-01 09:51:00 -05:00
|
|
|
# Extension("Crypto.Cipher.DES",
|
|
|
|
# include_dirs=['src/'],
|
|
|
|
# sources=["src/DES.c"]),
|
|
|
|
# Extension("Crypto.Cipher.DES3",
|
|
|
|
# include_dirs=['src/'],
|
|
|
|
# sources=["src/DES3.c"]),
|
2003-02-28 17:38:29 -07:00
|
|
|
|
|
|
|
# Stream ciphers
|
|
|
|
Extension("Crypto.Cipher.ARC4",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/ARC4.c"]),
|
2008-09-14 18:13:35 -04:00
|
|
|
|
|
|
|
# Utility modules
|
|
|
|
Extension("Crypto.Util.strxor",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=['src/strxor.c']),
|
2008-08-16 20:17:01 -04:00
|
|
|
|
|
|
|
# Counter modules
|
|
|
|
Extension("Crypto.Util._counter",
|
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=['src/_counter.c']),
|
2003-02-28 17:38:29 -07:00
|
|
|
]
|
|
|
|
|
2008-09-14 21:38:28 -04:00
|
|
|
# Platform-specific modules
|
|
|
|
self.extensions += plat_ext
|
|
|
|
|
2003-02-28 17:38:29 -07:00
|
|
|
# Detect which modules should be compiled
|
|
|
|
self.detect_modules()
|
|
|
|
build_ext.build_extensions(self)
|
|
|
|
|
|
|
|
def detect_modules (self):
|
2008-11-16 11:39:38 -05:00
|
|
|
if self.compiler.compiler_type == 'msvc':
|
|
|
|
self.compiler.include_dirs.insert(0, "src/inc-msvc/")
|
2003-02-28 17:38:29 -07:00
|
|
|
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')):
|
2003-04-03 19:17:41 -07:00
|
|
|
exts.append(Extension("Crypto.PublicKey._fastmath",
|
2003-02-28 17:38:29 -07:00
|
|
|
include_dirs=['src/'],
|
|
|
|
libraries=['gmp'],
|
2003-04-03 19:17:41 -07:00
|
|
|
sources=["src/_fastmath.c"]))
|
2008-09-20 17:25:34 -04:00
|
|
|
else:
|
|
|
|
print >>sys.stderr, "warning: GMP library not found; Not building Crypto.PublicKey._fastmath."
|
2003-02-28 17:38:29 -07:00
|
|
|
self.extensions += exts
|
|
|
|
|
2008-08-13 23:11:05 -04:00
|
|
|
class PCTBuildPy(build_py):
|
|
|
|
def find_package_modules(self, package, package_dir, *args, **kwargs):
|
|
|
|
modules = build_py.find_package_modules(self, package, package_dir, *args, **kwargs)
|
|
|
|
|
|
|
|
# Exclude certain modules
|
2008-09-15 18:16:11 -04:00
|
|
|
retval = []
|
|
|
|
for item in modules:
|
|
|
|
pkg, module = item[:2]
|
2008-08-13 23:11:05 -04:00
|
|
|
if (pkg, module) in EXCLUDE_PY:
|
|
|
|
continue
|
2008-09-15 18:16:11 -04:00
|
|
|
retval.append(item)
|
|
|
|
return retval
|
2008-08-13 23:11:05 -04:00
|
|
|
|
2008-11-21 13:04:18 -05:00
|
|
|
class TestCommand(Command):
|
|
|
|
|
|
|
|
description = "Run self-test"
|
|
|
|
|
|
|
|
user_options = [
|
|
|
|
('skip-slow-tests', None,
|
|
|
|
'Skip slow tests')
|
|
|
|
]
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
self.build_dir = None
|
|
|
|
self.skip_slow_tests = None
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
self.set_undefined_options('install', ('build_lib', 'build_dir'))
|
|
|
|
self.config = {'slow_tests': not self.skip_slow_tests}
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
# Make sure everything is built first
|
|
|
|
self.run_command('build')
|
|
|
|
|
|
|
|
# Run SelfTest
|
|
|
|
self.announce("running self-tests")
|
|
|
|
old_path = sys.path[:]
|
|
|
|
try:
|
|
|
|
sys.path.insert(0, self.build_dir)
|
|
|
|
from Crypto import SelfTest
|
|
|
|
SelfTest.run(verbosity=self.verbose, stream=sys.stdout, config=self.config)
|
|
|
|
finally:
|
|
|
|
# Restore sys.path
|
|
|
|
sys.path[:] = old_path
|
|
|
|
|
|
|
|
# Run slower self-tests
|
|
|
|
self.announce("running extended self-tests")
|
|
|
|
|
2003-02-28 17:55:21 -07:00
|
|
|
kw = {'name':"pycrypto",
|
2005-11-29 17:30:22 -07:00
|
|
|
'version':"2.0.2",
|
2003-02-28 17:55:21 -07:00
|
|
|
'description':"Cryptographic modules for Python.",
|
|
|
|
'author':"A.M. Kuchling",
|
2003-03-07 21:32:47 -07:00
|
|
|
'author_email':"amk@amk.ca",
|
2004-08-14 11:48:18 -07:00
|
|
|
'url':"http://www.amk.ca/python/code/crypto",
|
2003-02-28 17:38:29 -07:00
|
|
|
|
2008-11-21 13:04:18 -05:00
|
|
|
'cmdclass' : {'build_ext':PCTBuildExt, 'build_py': PCTBuildPy, 'test': TestCommand },
|
2003-02-28 17:55:21 -07:00
|
|
|
'packages' : ["Crypto", "Crypto.Hash", "Crypto.Cipher", "Crypto.Util",
|
2008-09-17 11:00:45 -04:00
|
|
|
"Crypto.Random",
|
2008-09-20 12:04:40 -04:00
|
|
|
"Crypto.Random.Fortuna",
|
2008-09-17 11:00:45 -04:00
|
|
|
"Crypto.Random.OSRNG",
|
2008-09-12 15:26:24 -04:00
|
|
|
"Crypto.SelfTest",
|
2008-09-13 00:13:29 -04:00
|
|
|
"Crypto.SelfTest.Cipher",
|
2008-09-12 15:26:24 -04:00
|
|
|
"Crypto.SelfTest.Hash",
|
2008-11-21 13:05:35 -05:00
|
|
|
"Crypto.SelfTest.Protocol",
|
2008-09-18 23:48:38 -04:00
|
|
|
"Crypto.SelfTest.PublicKey",
|
2008-09-17 13:35:25 -04:00
|
|
|
"Crypto.SelfTest.Random",
|
2008-09-20 12:04:40 -04:00
|
|
|
"Crypto.SelfTest.Random.Fortuna",
|
2008-09-17 13:35:25 -04:00
|
|
|
"Crypto.SelfTest.Random.OSRNG",
|
2008-09-15 18:59:25 -04:00
|
|
|
"Crypto.SelfTest.Util",
|
2002-05-23 13:22:04 -07:00
|
|
|
"Crypto.Protocol", "Crypto.PublicKey"],
|
2009-02-28 13:17:31 -05:00
|
|
|
'package_dir' : { "Crypto": "lib/Crypto" },
|
2003-02-28 17:38:29 -07:00
|
|
|
# One module is defined here, because build_ext won't be
|
|
|
|
# called unless there's at least one extension module defined.
|
2003-02-28 17:55:21 -07:00
|
|
|
'ext_modules':[Extension("Crypto.Hash.MD2",
|
2003-02-28 17:38:29 -07:00
|
|
|
include_dirs=['src/'],
|
|
|
|
sources=["src/MD2.c"])],
|
2003-02-28 17:55:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
# 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:
|
2003-04-07 16:09:41 -07:00
|
|
|
kw['download_url'] = ('http://www.amk.ca/files/python/crypto/'
|
2003-02-28 17:55:21 -07:00
|
|
|
'%s-%s.tar.gz' % (kw['name'], kw['version']) )
|
|
|
|
|
|
|
|
core.setup(**kw)
|
2002-04-03 18:45:09 -07:00
|
|
|
|