aboutsummaryrefslogtreecommitdiffstats
path: root/policyhandler/onap/crypto.py
diff options
context:
space:
mode:
Diffstat (limited to 'policyhandler/onap/crypto.py')
-rw-r--r--policyhandler/onap/crypto.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/policyhandler/onap/crypto.py b/policyhandler/onap/crypto.py
new file mode 100644
index 0000000..e2d58db
--- /dev/null
+++ b/policyhandler/onap/crypto.py
@@ -0,0 +1,72 @@
+"""ONAP specific encryption-decryption for passwords"""
+
+# org.onap.dcae
+# ================================================================================
+# Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+import base64
+from Crypto.Cipher import AES
+from Crypto.Protocol.KDF import PBKDF2
+from Crypto import Random
+
+class Cipher(object):
+ """class for AES-256 encryption and decryption of text using the salted password"""
+ KEY_SIZE = 32 # AES-256
+ KDF_ITERATIONS = 16384
+ AES_MODE = AES.MODE_CFB
+
+ @staticmethod
+ def encrypt(password, plain_text):
+ """
+ encrypt the :plain_text: into :cipher_text: using the password
+
+ :cipher_text: formatted as pbkdf2_salt + init_vector + encrypt(:plain_text:)
+ then cipher_text is encoded as base64 to make it textable (non-binary)
+
+ :pbkdf2_salt: has the fixed length of 32 (AES-256)
+ :init_vector: has the fixed length of AES.block_size
+ """
+ pbkdf2_salt = Random.new().read(Cipher.KEY_SIZE)
+ init_vector = Random.new().read(AES.block_size)
+ derived_key = PBKDF2(password, pbkdf2_salt, Cipher.KEY_SIZE, Cipher.KDF_ITERATIONS)
+
+ cipher = AES.new(derived_key, Cipher.AES_MODE, init_vector)
+ cipher_text = base64.b64encode(pbkdf2_salt + init_vector + cipher.encrypt(plain_text))
+ return cipher_text
+
+ @staticmethod
+ def decrypt(password, cipher_text):
+ """
+ decrypt the :cipher_text: into :plain_text: using the password
+
+ :cipher_text: is expected to be encoded as base64 to make it textable (non-binary)
+ inside of that it is expected to be formatted as
+ pbkdf2_salt + init_vector + encrypt(:plain_text:)
+
+ :pbkdf2_salt: has the fixed length of 32 (AES-256)
+ :init_vector: has the fixed length of AES.block_size
+ """
+ cipher_text = base64.b64decode(cipher_text)
+ pbkdf2_salt = cipher_text[: Cipher.KEY_SIZE]
+ init_vector = cipher_text[Cipher.KEY_SIZE : Cipher.KEY_SIZE + AES.block_size]
+ cipher_text = cipher_text[Cipher.KEY_SIZE + AES.block_size :]
+ derived_key = PBKDF2(password, pbkdf2_salt, Cipher.KEY_SIZE, Cipher.KDF_ITERATIONS)
+
+ cipher = AES.new(derived_key, Cipher.AES_MODE, init_vector)
+ plain_text = cipher.decrypt(cipher_text).decode('utf-8')
+ return plain_text