summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKali Kaneko (leap communications) <kali@leap.se>2016-10-21 17:06:52 -0400
committerKali Kaneko (leap communications) <kali@leap.se>2016-10-21 17:17:41 -0400
commit801f9318be9a0daf93205ac58e18d48efa358ebf (patch)
tree5b542346da55f833cd27b4502329a5c4c637fce1
parentce504db409ca2db4df5be807d636120d210061ad (diff)
[bug] workaround around scrypt.encrypt() failure in windows
scrypt raises a "unable to get salt from /dev/urandom" error when using encrypt method in windows. this is a quick workaround for obfuscating the uuid map, but it needs to be carefully reviewed as per the security implications (i'm using the hostname to salt the key hashing). doing this, I contemplated the possibility that the scrypt encryption we were using could be flawed, since the payloads can be easily guessed. so, take this with a pinch of salt (haha), and let's review it for the future. as always, this was in a rush trying to bring windows support.
-rw-r--r--src/leap/bitmask/core/uuid_map.py41
1 files changed, 34 insertions, 7 deletions
diff --git a/src/leap/bitmask/core/uuid_map.py b/src/leap/bitmask/core/uuid_map.py
index 5edc721..b7041aa 100644
--- a/src/leap/bitmask/core/uuid_map.py
+++ b/src/leap/bitmask/core/uuid_map.py
@@ -21,11 +21,21 @@ UUID Map: a persistent mapping between user-ids and uuids.
import base64
import os
import re
+import platform
import scrypt
from leap.common.config import get_path_prefix
+IS_WIN = platform.system() == "Windows"
+
+if IS_WIN:
+ import socket
+ from cryptography.fernet import Fernet
+ from cryptography.hazmat.backends.multibackend import MultiBackend
+ from cryptography.hazmat.backends.openssl.backend import Backend as OpenSSLBackend
+ crypto_backend = MultiBackend([OpenSSLBackend()])
+
MAP_PATH = os.path.join(get_path_prefix(), 'leap', 'uuids')
@@ -100,16 +110,33 @@ class UserMap(object):
def _encode_uuid_map(userid, uuid, passwd):
data = 'userid:%s:uuid:%s' % (userid, uuid)
- encrypted = scrypt.encrypt(data, passwd, maxtime=0.05)
- return base64.encodestring(encrypted).replace('\n', '')
+
+ # TODO review usage of the raw passwd here
+ if IS_WIN:
+ key = scrypt.hash(passwd, socket.gethostname())
+ key = base64.urlsafe_b64encode(key[:32])
+ f = Fernet(key, backend=crypto_backend)
+ encrypted = f.encrypt(data)
+ else:
+ encrypted = scrypt.encrypt(data, passwd, maxtime=0.05)
+ return base64.urlsafe_b64encode(encrypted)
def _decode_uuid_line(line, passwd):
- decoded = base64.decodestring(line)
- try:
- maybe_decrypted = scrypt.decrypt(decoded, passwd, maxtime=0.1)
- except scrypt.error:
- return None
+ decoded = base64.urlsafe_b64decode(line)
+ if IS_WIN:
+ key = scrypt.hash(passwd, socket.gethostname())
+ key = base64.urlsafe_b64encode(key[:32])
+ try:
+ f = Fernet(key, backend=crypto_backend)
+ maybe_decrypted = f.decrypt(key)
+ except Exception:
+ return None
+ else:
+ try:
+ maybe_decrypted = scrypt.decrypt(decoded, passwd, maxtime=0.1)
+ except scrypt.error:
+ return None
match = re.findall("userid\:(.+)\:uuid\:(.+)", maybe_decrypted)
if match:
return match[0]