summaryrefslogtreecommitdiffstats
path: root/pyload/lib/beaker/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'pyload/lib/beaker/crypto')
-rw-r--r--pyload/lib/beaker/crypto/__init__.py44
-rw-r--r--pyload/lib/beaker/crypto/jcecrypto.py32
-rw-r--r--pyload/lib/beaker/crypto/nsscrypto.py45
-rw-r--r--pyload/lib/beaker/crypto/pbkdf2.py347
-rw-r--r--pyload/lib/beaker/crypto/pycrypto.py34
-rw-r--r--pyload/lib/beaker/crypto/util.py30
6 files changed, 0 insertions, 532 deletions
diff --git a/pyload/lib/beaker/crypto/__init__.py b/pyload/lib/beaker/crypto/__init__.py
deleted file mode 100644
index ac13da527..000000000
--- a/pyload/lib/beaker/crypto/__init__.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from warnings import warn
-
-from beaker.crypto.pbkdf2 import PBKDF2, strxor
-from beaker.crypto.util import hmac, sha1, hmac_sha1, md5
-from beaker import util
-
-keyLength = None
-
-if util.jython:
- try:
- from beaker.crypto.jcecrypto import getKeyLength, aesEncrypt
- keyLength = getKeyLength()
- except ImportError:
- pass
-else:
- try:
- from beaker.crypto.nsscrypto import getKeyLength, aesEncrypt, aesDecrypt
- keyLength = getKeyLength()
- except ImportError:
- try:
- from beaker.crypto.pycrypto import getKeyLength, aesEncrypt, aesDecrypt
- keyLength = getKeyLength()
- except ImportError:
- pass
-
-if not keyLength:
- has_aes = False
-else:
- has_aes = True
-
-if has_aes and keyLength < 32:
- warn('Crypto implementation only supports key lengths up to %d bits. '
- 'Generated session cookies may be incompatible with other '
- 'environments' % (keyLength * 8))
-
-
-def generateCryptoKeys(master_key, salt, iterations):
- # NB: We XOR parts of the keystream into the randomly-generated parts, just
- # in case os.urandom() isn't as random as it should be. Note that if
- # os.urandom() returns truly random data, this will have no effect on the
- # overall security.
- keystream = PBKDF2(master_key, salt, iterations=iterations)
- cipher_key = keystream.read(keyLength)
- return cipher_key
diff --git a/pyload/lib/beaker/crypto/jcecrypto.py b/pyload/lib/beaker/crypto/jcecrypto.py
deleted file mode 100644
index ce313d6e1..000000000
--- a/pyload/lib/beaker/crypto/jcecrypto.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""
-Encryption module that uses the Java Cryptography Extensions (JCE).
-
-Note that in default installations of the Java Runtime Environment, the
-maximum key length is limited to 128 bits due to US export
-restrictions. This makes the generated keys incompatible with the ones
-generated by pycryptopp, which has no such restrictions. To fix this,
-download the "Unlimited Strength Jurisdiction Policy Files" from Sun,
-which will allow encryption using 256 bit AES keys.
-"""
-from javax.crypto import Cipher
-from javax.crypto.spec import SecretKeySpec, IvParameterSpec
-
-import jarray
-
-# Initialization vector filled with zeros
-_iv = IvParameterSpec(jarray.zeros(16, 'b'))
-
-
-def aesEncrypt(data, key):
- cipher = Cipher.getInstance('AES/CTR/NoPadding')
- skeySpec = SecretKeySpec(key, 'AES')
- cipher.init(Cipher.ENCRYPT_MODE, skeySpec, _iv)
- return cipher.doFinal(data).tostring()
-
-# magic.
-aesDecrypt = aesEncrypt
-
-
-def getKeyLength():
- maxlen = Cipher.getMaxAllowedKeyLength('AES/CTR/NoPadding')
- return min(maxlen, 256) / 8
diff --git a/pyload/lib/beaker/crypto/nsscrypto.py b/pyload/lib/beaker/crypto/nsscrypto.py
deleted file mode 100644
index 3a7797877..000000000
--- a/pyload/lib/beaker/crypto/nsscrypto.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""Encryption module that uses nsscrypto"""
-import nss.nss
-
-nss.nss.nss_init_nodb()
-
-# Apparently the rest of beaker doesn't care about the particluar cipher,
-# mode and padding used.
-# NOTE: A constant IV!!! This is only secure if the KEY is never reused!!!
-_mech = nss.nss.CKM_AES_CBC_PAD
-_iv = '\0' * nss.nss.get_iv_length(_mech)
-
-def aesEncrypt(data, key):
- slot = nss.nss.get_best_slot(_mech)
-
- key_obj = nss.nss.import_sym_key(slot, _mech, nss.nss.PK11_OriginGenerated,
- nss.nss.CKA_ENCRYPT, nss.nss.SecItem(key))
-
- param = nss.nss.param_from_iv(_mech, nss.nss.SecItem(_iv))
- ctx = nss.nss.create_context_by_sym_key(_mech, nss.nss.CKA_ENCRYPT, key_obj,
- param)
- l1 = ctx.cipher_op(data)
- # Yes, DIGEST. This needs fixing in NSS, but apparently nobody (including
- # me :( ) cares enough.
- l2 = ctx.digest_final()
-
- return l1 + l2
-
-def aesDecrypt(data, key):
- slot = nss.nss.get_best_slot(_mech)
-
- key_obj = nss.nss.import_sym_key(slot, _mech, nss.nss.PK11_OriginGenerated,
- nss.nss.CKA_DECRYPT, nss.nss.SecItem(key))
-
- param = nss.nss.param_from_iv(_mech, nss.nss.SecItem(_iv))
- ctx = nss.nss.create_context_by_sym_key(_mech, nss.nss.CKA_DECRYPT, key_obj,
- param)
- l1 = ctx.cipher_op(data)
- # Yes, DIGEST. This needs fixing in NSS, but apparently nobody (including
- # me :( ) cares enough.
- l2 = ctx.digest_final()
-
- return l1 + l2
-
-def getKeyLength():
- return 32
diff --git a/pyload/lib/beaker/crypto/pbkdf2.py b/pyload/lib/beaker/crypto/pbkdf2.py
deleted file mode 100644
index 71df22198..000000000
--- a/pyload/lib/beaker/crypto/pbkdf2.py
+++ /dev/null
@@ -1,347 +0,0 @@
-#!/usr/bin/python
-# -*- coding: ascii -*-
-###########################################################################
-# PBKDF2.py - PKCS#5 v2.0 Password-Based Key Derivation
-#
-# Copyright (C) 2007 Dwayne C. Litzenberger <dlitz@dlitz.net>
-# All rights reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation.
-#
-# THE AUTHOR PROVIDES THIS SOFTWARE ``AS IS'' AND ANY EXPRESSED 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 AUTHOR 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.
-#
-# Country of origin: Canada
-#
-###########################################################################
-# Sample PBKDF2 usage:
-# from Crypto.Cipher import AES
-# from PBKDF2 import PBKDF2
-# import os
-#
-# salt = os.urandom(8) # 64-bit salt
-# key = PBKDF2("This passphrase is a secret.", salt).read(32) # 256-bit key
-# iv = os.urandom(16) # 128-bit IV
-# cipher = AES.new(key, AES.MODE_CBC, iv)
-# ...
-#
-# Sample crypt() usage:
-# from PBKDF2 import crypt
-# pwhash = crypt("secret")
-# alleged_pw = raw_input("Enter password: ")
-# if pwhash == crypt(alleged_pw, pwhash):
-# print "Password good"
-# else:
-# print "Invalid password"
-#
-###########################################################################
-# History:
-#
-# 2007-07-27 Dwayne C. Litzenberger <dlitz@dlitz.net>
-# - Initial Release (v1.0)
-#
-# 2007-07-31 Dwayne C. Litzenberger <dlitz@dlitz.net>
-# - Bugfix release (v1.1)
-# - SECURITY: The PyCrypto XOR cipher (used, if available, in the _strxor
-# function in the previous release) silently truncates all keys to 64
-# bytes. The way it was used in the previous release, this would only be
-# problem if the pseudorandom function that returned values larger than
-# 64 bytes (so SHA1, SHA256 and SHA512 are fine), but I don't like
-# anything that silently reduces the security margin from what is
-# expected.
-#
-###########################################################################
-
-__version__ = "1.1"
-
-from struct import pack
-from binascii import b2a_hex
-from random import randint
-
-from base64 import b64encode
-
-from beaker.crypto.util import hmac as HMAC, hmac_sha1 as SHA1
-
-
-def strxor(a, b):
- return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)])
-
-
-class PBKDF2(object):
- """PBKDF2.py : PKCS#5 v2.0 Password-Based Key Derivation
-
- This implementation takes a passphrase and a salt (and optionally an
- iteration count, a digest module, and a MAC module) and provides a
- file-like object from which an arbitrarily-sized key can be read.
-
- If the passphrase and/or salt are unicode objects, they are encoded as
- UTF-8 before they are processed.
-
- The idea behind PBKDF2 is to derive a cryptographic key from a
- passphrase and a salt.
-
- PBKDF2 may also be used as a strong salted password hash. The
- 'crypt' function is provided for that purpose.
-
- Remember: Keys generated using PBKDF2 are only as strong as the
- passphrases they are derived from.
- """
-
- def __init__(self, passphrase, salt, iterations=1000,
- digestmodule=SHA1, macmodule=HMAC):
- if not callable(macmodule):
- macmodule = macmodule.new
- self.__macmodule = macmodule
- self.__digestmodule = digestmodule
- self._setup(passphrase, salt, iterations, self._pseudorandom)
-
- def _pseudorandom(self, key, msg):
- """Pseudorandom function. e.g. HMAC-SHA1"""
- return self.__macmodule(key=key, msg=msg,
- digestmod=self.__digestmodule).digest()
-
- def read(self, bytes):
- """Read the specified number of key bytes."""
- if self.closed:
- raise ValueError("file-like object is closed")
-
- size = len(self.__buf)
- blocks = [self.__buf]
- i = self.__blockNum
- while size < bytes:
- i += 1
- if i > 0xffffffff:
- # We could return "" here, but
- raise OverflowError("derived key too long")
- block = self.__f(i)
- blocks.append(block)
- size += len(block)
- buf = "".join(blocks)
- retval = buf[:bytes]
- self.__buf = buf[bytes:]
- self.__blockNum = i
- return retval
-
- def __f(self, i):
- # i must fit within 32 bits
- assert (1 <= i and i <= 0xffffffff)
- U = self.__prf(self.__passphrase, self.__salt + pack("!L", i))
- result = U
- for j in xrange(2, 1 + self.__iterations):
- U = self.__prf(self.__passphrase, U)
- result = strxor(result, U)
- return result
-
- def hexread(self, octets):
- """Read the specified number of octets. Return them as hexadecimal.
-
- Note that len(obj.hexread(n)) == 2*n.
- """
- return b2a_hex(self.read(octets))
-
- def _setup(self, passphrase, salt, iterations, prf):
- # Sanity checks:
-
- # passphrase and salt must be str or unicode (in the latter
- # case, we convert to UTF-8)
- if isinstance(passphrase, unicode):
- passphrase = passphrase.encode("UTF-8")
- if not isinstance(passphrase, str):
- raise TypeError("passphrase must be str or unicode")
- if isinstance(salt, unicode):
- salt = salt.encode("UTF-8")
- if not isinstance(salt, str):
- raise TypeError("salt must be str or unicode")
-
- # iterations must be an integer >= 1
- if not isinstance(iterations, (int, long)):
- raise TypeError("iterations must be an integer")
- if iterations < 1:
- raise ValueError("iterations must be at least 1")
-
- # prf must be callable
- if not callable(prf):
- raise TypeError("prf must be callable")
-
- self.__passphrase = passphrase
- self.__salt = salt
- self.__iterations = iterations
- self.__prf = prf
- self.__blockNum = 0
- self.__buf = ""
- self.closed = False
-
- def close(self):
- """Close the stream."""
- if not self.closed:
- del self.__passphrase
- del self.__salt
- del self.__iterations
- del self.__prf
- del self.__blockNum
- del self.__buf
- self.closed = True
-
-
-def crypt(word, salt=None, iterations=None):
- """PBKDF2-based unix crypt(3) replacement.
-
- The number of iterations specified in the salt overrides the 'iterations'
- parameter.
-
- The effective hash length is 192 bits.
- """
-
- # Generate a (pseudo-)random salt if the user hasn't provided one.
- if salt is None:
- salt = _makesalt()
-
- # salt must be a string or the us-ascii subset of unicode
- if isinstance(salt, unicode):
- salt = salt.encode("us-ascii")
- if not isinstance(salt, str):
- raise TypeError("salt must be a string")
-
- # word must be a string or unicode (in the latter case, we convert to UTF-8)
- if isinstance(word, unicode):
- word = word.encode("UTF-8")
- if not isinstance(word, str):
- raise TypeError("word must be a string or unicode")
-
- # Try to extract the real salt and iteration count from the salt
- if salt.startswith("$p5k2$"):
- (iterations, salt, dummy) = salt.split("$")[2:5]
- if iterations == "":
- iterations = 400
- else:
- converted = int(iterations, 16)
- if iterations != "%x" % converted: # lowercase hex, minimum digits
- raise ValueError("Invalid salt")
- iterations = converted
- if not (iterations >= 1):
- raise ValueError("Invalid salt")
-
- # Make sure the salt matches the allowed character set
- allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"
- for ch in salt:
- if ch not in allowed:
- raise ValueError("Illegal character %r in salt" % (ch,))
-
- if iterations is None or iterations == 400:
- iterations = 400
- salt = "$p5k2$$" + salt
- else:
- salt = "$p5k2$%x$%s" % (iterations, salt)
- rawhash = PBKDF2(word, salt, iterations).read(24)
- return salt + "$" + b64encode(rawhash, "./")
-
-# Add crypt as a static method of the PBKDF2 class
-# This makes it easier to do "from PBKDF2 import PBKDF2" and still use
-# crypt.
-PBKDF2.crypt = staticmethod(crypt)
-
-
-def _makesalt():
- """Return a 48-bit pseudorandom salt for crypt().
-
- This function is not suitable for generating cryptographic secrets.
- """
- binarysalt = "".join([pack("@H", randint(0, 0xffff)) for i in range(3)])
- return b64encode(binarysalt, "./")
-
-
-def test_pbkdf2():
- """Module self-test"""
- from binascii import a2b_hex
-
- #
- # Test vectors from RFC 3962
- #
-
- # Test 1
- result = PBKDF2("password", "ATHENA.MIT.EDUraeburn", 1).read(16)
- expected = a2b_hex("cdedb5281bb2f801565a1122b2563515")
- if result != expected:
- raise RuntimeError("self-test failed")
-
- # Test 2
- result = PBKDF2("password", "ATHENA.MIT.EDUraeburn", 1200).hexread(32)
- expected = ("5c08eb61fdf71e4e4ec3cf6ba1f5512b"
- "a7e52ddbc5e5142f708a31e2e62b1e13")
- if result != expected:
- raise RuntimeError("self-test failed")
-
- # Test 3
- result = PBKDF2("X" * 64, "pass phrase equals block size", 1200).hexread(32)
- expected = ("139c30c0966bc32ba55fdbf212530ac9"
- "c5ec59f1a452f5cc9ad940fea0598ed1")
- if result != expected:
- raise RuntimeError("self-test failed")
-
- # Test 4
- result = PBKDF2("X" * 65, "pass phrase exceeds block size", 1200).hexread(32)
- expected = ("9ccad6d468770cd51b10e6a68721be61"
- "1a8b4d282601db3b36be9246915ec82a")
- if result != expected:
- raise RuntimeError("self-test failed")
-
- #
- # Other test vectors
- #
-
- # Chunked read
- f = PBKDF2("kickstart", "workbench", 256)
- result = f.read(17)
- result += f.read(17)
- result += f.read(1)
- result += f.read(2)
- result += f.read(3)
- expected = PBKDF2("kickstart", "workbench", 256).read(40)
- if result != expected:
- raise RuntimeError("self-test failed")
-
- #
- # crypt() test vectors
- #
-
- # crypt 1
- result = crypt("cloadm", "exec")
- expected = '$p5k2$$exec$r1EWMCMk7Rlv3L/RNcFXviDefYa0hlql'
- if result != expected:
- raise RuntimeError("self-test failed")
-
- # crypt 2
- result = crypt("gnu", '$p5k2$c$u9HvcT4d$.....')
- expected = '$p5k2$c$u9HvcT4d$Sd1gwSVCLZYAuqZ25piRnbBEoAesaa/g'
- if result != expected:
- raise RuntimeError("self-test failed")
-
- # crypt 3
- result = crypt("dcl", "tUsch7fU", iterations=13)
- expected = "$p5k2$d$tUsch7fU$nqDkaxMDOFBeJsTSfABsyn.PYUXilHwL"
- if result != expected:
- raise RuntimeError("self-test failed")
-
- # crypt 4 (unicode)
- result = crypt(u'\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2',
- '$p5k2$$KosHgqNo$9mjN8gqjt02hDoP0c2J0ABtLIwtot8cQ')
- expected = '$p5k2$$KosHgqNo$9mjN8gqjt02hDoP0c2J0ABtLIwtot8cQ'
- if result != expected:
- raise RuntimeError("self-test failed")
-
-if __name__ == '__main__':
- test_pbkdf2()
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/pyload/lib/beaker/crypto/pycrypto.py b/pyload/lib/beaker/crypto/pycrypto.py
deleted file mode 100644
index 6657bff56..000000000
--- a/pyload/lib/beaker/crypto/pycrypto.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"""Encryption module that uses pycryptopp or pycrypto"""
-try:
- # Pycryptopp is preferred over Crypto because Crypto has had
- # various periods of not being maintained, and pycryptopp uses
- # the Crypto++ library which is generally considered the 'gold standard'
- # of crypto implementations
- from pycryptopp.cipher import aes
-
- def aesEncrypt(data, key):
- cipher = aes.AES(key)
- return cipher.process(data)
-
- # magic.
- aesDecrypt = aesEncrypt
-
-except ImportError:
- from Crypto.Cipher import AES
- from Crypto.Util import Counter
-
- def aesEncrypt(data, key):
- cipher = AES.new(key, AES.MODE_CTR,
- counter=Counter.new(128, initial_value=0))
-
- return cipher.encrypt(data)
-
- def aesDecrypt(data, key):
- cipher = AES.new(key, AES.MODE_CTR,
- counter=Counter.new(128, initial_value=0))
- return cipher.decrypt(data)
-
-
-
-def getKeyLength():
- return 32
diff --git a/pyload/lib/beaker/crypto/util.py b/pyload/lib/beaker/crypto/util.py
deleted file mode 100644
index 7f96ac856..000000000
--- a/pyload/lib/beaker/crypto/util.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from warnings import warn
-from beaker import util
-
-
-try:
- # Use PyCrypto (if available)
- from Crypto.Hash import HMAC as hmac, SHA as hmac_sha1
- sha1 = hmac_sha1.new
-
-except ImportError:
-
- # PyCrypto not available. Use the Python standard library.
- import hmac
-
- # When using the stdlib, we have to make sure the hmac version and sha
- # version are compatible
- if util.py24:
- from sha import sha as sha1
- import sha as hmac_sha1
- else:
- # NOTE: We have to use the callable with hashlib (hashlib.sha1),
- # otherwise hmac only accepts the sha module object itself
- from hashlib import sha1
- hmac_sha1 = sha1
-
-
-if util.py24:
- from md5 import md5
-else:
- from hashlib import md5