summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Encryption.py
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-02-05 14:04:09 -0500
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-02-05 14:04:09 -0500
commit25cb6db5ccb0c8e8302c220a90344a95baf3909b (patch)
tree80d6a81f2dcd164f0b127bdfe75a4b2d833c6be6 /src/lib/Bcfg2/Encryption.py
parent5d237f71575a109c10d5aad8d70dc5dda00a2d96 (diff)
downloadbcfg2-25cb6db5ccb0c8e8302c220a90344a95baf3909b.tar.gz
bcfg2-25cb6db5ccb0c8e8302c220a90344a95baf3909b.tar.bz2
bcfg2-25cb6db5ccb0c8e8302c220a90344a95baf3909b.zip
moved some libraries in Bcfg2/ into more specific (Server/ or Client/) places
Diffstat (limited to 'src/lib/Bcfg2/Encryption.py')
-rwxr-xr-xsrc/lib/Bcfg2/Encryption.py195
1 files changed, 0 insertions, 195 deletions
diff --git a/src/lib/Bcfg2/Encryption.py b/src/lib/Bcfg2/Encryption.py
deleted file mode 100755
index 341956e03..000000000
--- a/src/lib/Bcfg2/Encryption.py
+++ /dev/null
@@ -1,195 +0,0 @@
-""" Bcfg2.Encryption provides a number of convenience methods for
-handling encryption in Bcfg2. See :ref:`server-encryption` for more
-details. """
-
-import os
-import Bcfg2.Options
-from M2Crypto import Rand
-from M2Crypto.EVP import Cipher, EVPError
-from Bcfg2.Compat import StringIO, md5, b64encode, b64decode
-
-#: Constant representing the encryption operation for
-#: :class:`M2Crypto.EVP.Cipher`, which uses a simple integer. This
-#: makes our code more readable.
-ENCRYPT = 1
-
-#: Constant representing the decryption operation for
-#: :class:`M2Crypto.EVP.Cipher`, which uses a simple integer. This
-#: makes our code more readable.
-DECRYPT = 0
-
-#: Default initialization vector. For best security, you should use a
-#: unique IV for each message. :func:`ssl_encrypt` does this in an
-#: automated fashion.
-IV = '\0' * 16
-
-#: The config file section encryption options and passphrases are
-#: stored in
-CFG_SECTION = "encryption"
-
-#: The config option used to store the algorithm
-CFG_ALGORITHM = "algorithm"
-
-#: Default cipher algorithm. To get a full list of valid algorithms,
-#: you can run::
-#:
-#: openssl list-cipher-algorithms | grep -v ' => ' | \
-#: tr 'A-Z-' 'a-z_' | sort -u
-ALGORITHM = Bcfg2.Options.get_option_parser().cfp.get( # pylint: disable=E1103
- CFG_SECTION,
- CFG_ALGORITHM,
- default="aes_256_cbc").lower().replace("-", "_")
-
-Rand.rand_seed(os.urandom(1024))
-
-
-def _cipher_filter(cipher, instr):
- """ M2Crypto reads and writes file-like objects, so this uses
- StringIO to pass data through it """
- inbuf = StringIO(instr)
- outbuf = StringIO()
- while 1:
- buf = inbuf.read()
- if not buf:
- break
- outbuf.write(cipher.update(buf))
- outbuf.write(cipher.final())
- rv = outbuf.getvalue()
- inbuf.close()
- outbuf.close()
- return rv
-
-
-def str_encrypt(plaintext, key, iv=IV, algorithm=ALGORITHM, salt=None):
- """ Encrypt a string with a key. For a higher-level encryption
- interface, see :func:`ssl_encrypt`.
-
- :param plaintext: The plaintext data to encrypt
- :type plaintext: string
- :param key: The key to encrypt the data with
- :type key: string
- :param iv: The initialization vector
- :type iv: string
- :param algorithm: The cipher algorithm to use
- :type algorithm: string
- :param salt: The salt to use
- :type salt: string
- :returns: string - The decrypted data
- """
- cipher = Cipher(alg=algorithm, key=key, iv=iv, op=ENCRYPT, salt=salt)
- return _cipher_filter(cipher, plaintext)
-
-
-def str_decrypt(crypted, key, iv=IV, algorithm=ALGORITHM):
- """ Decrypt a string with a key. For a higher-level decryption
- interface, see :func:`ssl_decrypt`.
-
- :param crypted: The raw binary encrypted data
- :type crypted: string
- :param key: The encryption key to decrypt with
- :type key: string
- :param iv: The initialization vector
- :type iv: string
- :param algorithm: The cipher algorithm to use
- :type algorithm: string
- :returns: string - The decrypted data
- """
- cipher = Cipher(alg=algorithm, key=key, iv=iv, op=DECRYPT)
- return _cipher_filter(cipher, crypted)
-
-
-def ssl_decrypt(data, passwd, algorithm=ALGORITHM):
- """ Decrypt openssl-encrypted data. This can decrypt data
- encrypted by :func:`ssl_encrypt`, or ``openssl enc``. It performs
- a base64 decode first if the data is base64 encoded, and
- automatically determines the salt and initialization vector (both
- of which are embedded in the encrypted data).
-
- :param data: The encrypted data (either base64-encoded or raw
- binary) to decrypt
- :type data: string
- :param passwd: The password to use to decrypt the data
- :type passwd: string
- :param algorithm: The cipher algorithm to use
- :type algorithm: string
- :returns: string - The decrypted data
- """
- # base64-decode the data
- data = b64decode(data)
- salt = data[8:16]
- hashes = [md5(passwd + salt).digest()]
- for i in range(1, 3):
- hashes.append(md5(hashes[i - 1] + passwd + salt).digest())
- key = hashes[0] + hashes[1]
- iv = hashes[2]
-
- return str_decrypt(data[16:], key=key, iv=iv, algorithm=algorithm)
-
-
-def ssl_encrypt(plaintext, passwd, algorithm=ALGORITHM, salt=None):
- """ Encrypt data in a format that is openssl compatible.
-
- :param plaintext: The plaintext data to encrypt
- :type plaintext: string
- :param passwd: The password to use to encrypt the data
- :type passwd: string
- :param algorithm: The cipher algorithm to use
- :type algorithm: string
- :param salt: The salt to use. If none is provided, one will be
- randomly generated.
- :type salt: bytes
- :returns: string - The base64-encoded, salted, encrypted string.
- The string includes a trailing newline to make it fully
- compatible with openssl command-line tools.
- """
- if salt is None:
- salt = Rand.rand_bytes(8)
-
- hashes = [md5(passwd + salt).digest()]
- for i in range(1, 3):
- hashes.append(md5(hashes[i - 1] + passwd + salt).digest())
- key = hashes[0] + hashes[1]
- iv = hashes[2]
-
- crypted = str_encrypt(plaintext, key=key, salt=salt, iv=iv,
- algorithm=algorithm)
- return b64encode("Salted__" + salt + crypted) + "\n"
-
-
-def get_passphrases():
- """ Get all candidate encryption passphrases from the config file.
-
- :returns: dict - a dict of ``<passphrase name>``: ``<passphrase>``
- """
- setup = Bcfg2.Options.get_option_parser()
- if setup.cfp.has_section(CFG_SECTION):
- return dict([(o, setup.cfp.get(CFG_SECTION, o))
- for o in setup.cfp.options(CFG_SECTION)
- if o != CFG_ALGORITHM])
- else:
- return dict()
-
-
-def bruteforce_decrypt(crypted, passphrases=None, algorithm=ALGORITHM):
- """ Convenience method to decrypt the given encrypted string by
- trying the given passphrases or all passphrases (as returned by
- :func:`get_passphrases`) sequentially until one is found that
- works.
-
- :param crypted: The data to decrypt
- :type crypted: string
- :param passphrases: The passphrases to try.
- :type passphrases: list
- :param algorithm: The cipher algorithm to use
- :type algorithm: string
- :returns: string - The decrypted data
- :raises: :class:`M2Crypto.EVP.EVPError`, if the data cannot be decrypted
- """
- if passphrases is None:
- passphrases = get_passphrases().values()
- for passwd in passphrases:
- try:
- return ssl_decrypt(crypted, passwd, algorithm=algorithm)
- except EVPError:
- pass
- raise EVPError("Failed to decrypt")