mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Finish port to PyCA cryptography
* add missing default_backend * unpad encrypted data * use cryptography's hashes and HMAC construct * remove hard dependency on python-nss from setup.py Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
This commit is contained in:
committed by
Martin Basti
parent
d00ae870dd
commit
135d0b5dd1
@@ -20,20 +20,18 @@
|
|||||||
import abc
|
import abc
|
||||||
import base64
|
import base64
|
||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
|
||||||
import hmac
|
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
import struct
|
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
import dateutil.tz
|
import dateutil.tz
|
||||||
import gssapi
|
import gssapi
|
||||||
import six
|
import six
|
||||||
from six.moves import xrange
|
|
||||||
|
|
||||||
from cryptography.hazmat.primitives import hashes
|
from cryptography.exceptions import InvalidSignature
|
||||||
|
from cryptography.hazmat.primitives import hashes, hmac
|
||||||
|
from cryptography.hazmat.primitives.padding import PKCS7
|
||||||
from cryptography.hazmat.primitives.kdf import pbkdf2
|
from cryptography.hazmat.primitives.kdf import pbkdf2
|
||||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
@@ -111,25 +109,32 @@ def convertHMACType(value):
|
|||||||
"Converts HMAC URI to hashlib object."
|
"Converts HMAC URI to hashlib object."
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"http://www.w3.org/2000/09/xmldsig#hmac-sha1": hashlib.sha1,
|
"http://www.w3.org/2000/09/xmldsig#hmac-sha1": hashes.SHA1,
|
||||||
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha224": hashlib.sha224,
|
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha224": hashes.SHA224,
|
||||||
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha256": hashlib.sha256,
|
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha256": hashes.SHA256,
|
||||||
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha384": hashlib.sha384,
|
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha384": hashes.SHA384,
|
||||||
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha512": hashlib.sha512,
|
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha512": hashes.SHA512,
|
||||||
}.get(value.lower(), hashlib.sha1)
|
}.get(value.lower(), hashes.SHA1)
|
||||||
|
|
||||||
|
|
||||||
def convertAlgorithm(value):
|
def convertAlgorithm(value):
|
||||||
"Converts encryption URI to (mech, ivlen)."
|
"Converts encryption URI to (mech, ivlen)."
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"http://www.w3.org/2001/04/xmlenc#aes128-cbc": (algorithms.AES, modes.CBC, 128),
|
"http://www.w3.org/2001/04/xmlenc#aes128-cbc": (
|
||||||
"http://www.w3.org/2001/04/xmlenc#aes192-cbc": (algorithms.AES, modes.CBC, 192),
|
algorithms.AES, modes.CBC, 128),
|
||||||
"http://www.w3.org/2001/04/xmlenc#aes256-cbc": (algorithms.AES, modes.CBC, 256),
|
"http://www.w3.org/2001/04/xmlenc#aes192-cbc": (
|
||||||
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc": (algorithms.TripleDES, modes.CBC, 64),
|
algorithms.AES, modes.CBC, 192),
|
||||||
"http://www.w3.org/2001/04/xmldsig-more#camellia128": (algorithms.Camellia, modes.CBC, 128),
|
"http://www.w3.org/2001/04/xmlenc#aes256-cbc": (
|
||||||
"http://www.w3.org/2001/04/xmldsig-more#camellia192": (algorithms.Camellia, modes.CBC, 192),
|
algorithms.AES, modes.CBC, 256),
|
||||||
"http://www.w3.org/2001/04/xmldsig-more#camellia256": (algorithms.Camellia, modes.CBC, 256),
|
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc": (
|
||||||
|
algorithms.TripleDES, modes.CBC, 64),
|
||||||
|
"http://www.w3.org/2001/04/xmldsig-more#camellia128": (
|
||||||
|
algorithms.Camellia, modes.CBC, 128),
|
||||||
|
"http://www.w3.org/2001/04/xmldsig-more#camellia192": (
|
||||||
|
algorithms.Camellia, modes.CBC, 192),
|
||||||
|
"http://www.w3.org/2001/04/xmldsig-more#camellia256": (
|
||||||
|
algorithms.Camellia, modes.CBC, 256),
|
||||||
|
|
||||||
# TODO: add support for these formats.
|
# TODO: add support for these formats.
|
||||||
# "http://www.w3.org/2001/04/xmlenc#kw-aes128": "kw-aes128",
|
# "http://www.w3.org/2001/04/xmlenc#kw-aes128": "kw-aes128",
|
||||||
@@ -174,10 +179,14 @@ class PBKDF2KeyDerivation(XMLKeyDerivation):
|
|||||||
if params is None:
|
if params is None:
|
||||||
raise ValueError("XML file is missing PBKDF2 parameters!")
|
raise ValueError("XML file is missing PBKDF2 parameters!")
|
||||||
|
|
||||||
salt = fetch(params, "./xenc11:Salt/xenc11:Specified/text()", base64.b64decode)
|
salt = fetch(
|
||||||
itrs = fetch(params, "./xenc11:IterationCount/text()", int)
|
params, "./xenc11:Salt/xenc11:Specified/text()", base64.b64decode)
|
||||||
klen = fetch(params, "./xenc11:KeyLength/text()", int)
|
itrs = fetch(
|
||||||
hmod = fetch(params, "./xenc11:PRF/@Algorithm", convertHMACType, hashlib.sha1)
|
params, "./xenc11:IterationCount/text()", int)
|
||||||
|
klen = fetch(
|
||||||
|
params, "./xenc11:KeyLength/text()", int)
|
||||||
|
hmod = fetch(
|
||||||
|
params, "./xenc11:PRF/@Algorithm", convertHMACType, hashes.SHA1)
|
||||||
|
|
||||||
if salt is None:
|
if salt is None:
|
||||||
raise ValueError("XML file is missing PBKDF2 salt!")
|
raise ValueError("XML file is missing PBKDF2 salt!")
|
||||||
@@ -189,10 +198,11 @@ class PBKDF2KeyDerivation(XMLKeyDerivation):
|
|||||||
raise ValueError("XML file is missing PBKDF2 key length!")
|
raise ValueError("XML file is missing PBKDF2 key length!")
|
||||||
|
|
||||||
self.kdf = pbkdf2.PBKDF2HMAC(
|
self.kdf = pbkdf2.PBKDF2HMAC(
|
||||||
algorithm=hmod,
|
algorithm=hmod(),
|
||||||
length=klen,
|
length=klen,
|
||||||
salt=salt,
|
salt=salt,
|
||||||
iterations=itrs
|
iterations=itrs,
|
||||||
|
backend=default_backend()
|
||||||
)
|
)
|
||||||
|
|
||||||
def derive(self, masterkey):
|
def derive(self, masterkey):
|
||||||
@@ -217,8 +227,13 @@ class XMLDecryptor(object):
|
|||||||
self.__hmac = hmac
|
self.__hmac = hmac
|
||||||
|
|
||||||
def __call__(self, element, mac=None):
|
def __call__(self, element, mac=None):
|
||||||
(algo, mode, klen) = fetch(element, "./xenc:EncryptionMethod/@Algorithm", convertAlgorithm)
|
algo, mode, klen = fetch(
|
||||||
data = fetch(element, "./xenc:CipherData/xenc:CipherValue/text()", base64.b64decode)
|
element, "./xenc:EncryptionMethod/@Algorithm", convertAlgorithm)
|
||||||
|
data = fetch(
|
||||||
|
element,
|
||||||
|
"./xenc:CipherData/xenc:CipherValue/text()",
|
||||||
|
base64.b64decode
|
||||||
|
)
|
||||||
|
|
||||||
# Make sure the key is the right length.
|
# Make sure the key is the right length.
|
||||||
if len(self.__key) * 8 != klen:
|
if len(self.__key) * 8 != klen:
|
||||||
@@ -228,17 +243,24 @@ class XMLDecryptor(object):
|
|||||||
if mac:
|
if mac:
|
||||||
tmp = self.__hmac.copy()
|
tmp = self.__hmac.copy()
|
||||||
tmp.update(data)
|
tmp.update(data)
|
||||||
if tmp.digest() != mac:
|
try:
|
||||||
raise ValidationError("MAC validation failed!")
|
tmp.verify(mac)
|
||||||
|
except InvalidSignature as e:
|
||||||
|
raise ValidationError("MAC validation failed!", e)
|
||||||
|
|
||||||
iv = data[:algo.block_size / 8]
|
iv = data[:algo.block_size // 8]
|
||||||
data = data[len(iv):]
|
data = data[len(iv):]
|
||||||
|
|
||||||
cipher = Cipher(algo(self.__key), mode(iv))
|
algorithm = algo(self.__key)
|
||||||
|
cipher = Cipher(algorithm, mode(iv), default_backend())
|
||||||
decryptor = cipher.decryptor()
|
decryptor = cipher.decryptor()
|
||||||
|
padded = decryptor.update(data)
|
||||||
|
padded += decryptor.finalize()
|
||||||
|
|
||||||
|
unpadder = PKCS7(algorithm.block_size).unpadder()
|
||||||
|
out = unpadder.update(padded)
|
||||||
|
out += unpadder.finalize()
|
||||||
|
|
||||||
out = decryptor.update(data)
|
|
||||||
out += decryptor.finalize()
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -441,7 +463,11 @@ class PSKCDocument(object):
|
|||||||
# Load the decryptor.
|
# Load the decryptor.
|
||||||
self.__decryptor = XMLDecryptor(key)
|
self.__decryptor = XMLDecryptor(key)
|
||||||
if self.__mkey is not None and self.__algo is not None:
|
if self.__mkey is not None and self.__algo is not None:
|
||||||
tmp = hmac.HMAC(self.__decryptor(self.__mkey), digestmod=self.__algo)
|
tmp = hmac.HMAC(
|
||||||
|
self.__decryptor(self.__mkey),
|
||||||
|
self.__algo(),
|
||||||
|
backend=default_backend()
|
||||||
|
)
|
||||||
self.__decryptor = XMLDecryptor(key, tmp)
|
self.__decryptor = XMLDecryptor(key, tmp)
|
||||||
|
|
||||||
def getKeyPackages(self):
|
def getKeyPackages(self):
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ if __name__ == '__main__':
|
|||||||
"netaddr",
|
"netaddr",
|
||||||
"pyasn1",
|
"pyasn1",
|
||||||
"pyldap",
|
"pyldap",
|
||||||
"python-nss",
|
|
||||||
"six",
|
"six",
|
||||||
# not available on PyPI
|
# not available on PyPI
|
||||||
# "python-libipa_hbac",
|
# "python-libipa_hbac",
|
||||||
|
|||||||
@@ -71,12 +71,11 @@ if __name__ == '__main__':
|
|||||||
"pyldap",
|
"pyldap",
|
||||||
"pytest",
|
"pytest",
|
||||||
"pytest_multihost",
|
"pytest_multihost",
|
||||||
"python-nss",
|
|
||||||
"six",
|
"six",
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
"integration": ["dbus-python", "pyyaml", "ipaserver"],
|
"integration": ["dbus-python", "pyyaml", "ipaserver"],
|
||||||
"ipaserver": ["ipaserver"],
|
"ipaserver": ["ipaserver", "python-nss"],
|
||||||
"webui": ["selenium", "pyyaml", "ipaserver"],
|
"webui": ["selenium", "pyyaml", "ipaserver"],
|
||||||
"xmlrpc": ["ipaserver"],
|
"xmlrpc": ["ipaserver"],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user