0daf8ba4b13e63b9a9f03e96c3b8d23f53992f54
[optf/has.git] / conductor / conductor / common / utils / cipherUtils.py
1 #
2 # -------------------------------------------------------------------------
3 #   Copyright (c) 2015-2017 AT&T Intellectual Property
4 #
5 #   Licensed under the Apache License, Version 2.0 (the "License");
6 #   you may not use this file except in compliance with the License.
7 #   You may obtain a copy of the License at
8 #
9 #       http://www.apache.org/licenses/LICENSE-2.0
10 #
11 #   Unless required by applicable law or agreed to in writing, software
12 #   distributed under the License is distributed on an "AS IS" BASIS,
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 #   See the License for the specific language governing permissions and
15 #   limitations under the License.
16 #
17 # -------------------------------------------------------------------------
18 #
19
20 import base64
21 from Cryptodome.Cipher import AES
22 from Cryptodome import Random
23 import hashlib
24 from oslo_config import cfg
25
26 CONF = cfg.CONF
27
28 cipher_opts = [
29     cfg.StrOpt('appkey',
30                default='ch00se@g003ntropy',
31                help='Master key to secure other secrets')
32 ]
33
34 CONF.register_opts(cipher_opts, group='auth')
35
36
37 class AESCipher(object):
38     __instance = None
39
40     @staticmethod
41     def get_instance(key=None):
42         if AESCipher.__instance is None:
43             print('Creating the singleton instance')
44             AESCipher(key)
45         return AESCipher.__instance
46
47     def __init__(self, key=None):
48         if AESCipher.__instance is not None:
49             raise Exception("This class is a singleton!")
50         else:
51             AESCipher.__instance = self
52
53         self.bs = 32
54         if key is None:
55             key = CONF.auth.appkey  # ---> python3.8 Code version code
56             # key= CONF.auth.appkey.encode() ---> Python 2.7 version code
57         # in Python 3+ key is already a b'' type so no need to encode it again.
58
59         self.key = hashlib.sha256(key.encode()).digest()
60
61     def encrypt(self, raw):
62         raw = self._pad(raw)
63         iv = Random.new().read(AES.block_size)
64         cipher = AES.new(self.key, AES.MODE_CBC, iv)
65         return base64.b64encode(iv + cipher.encrypt(raw))
66
67     def decrypt(self, enc):
68         enc = base64.b64decode(enc)
69         iv = enc[:AES.block_size]
70         cipher = AES.new(self.key, AES.MODE_CBC, iv)
71         return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
72
73     def _pad(self, s):
74         return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
75
76     @staticmethod
77     def _unpad(s):
78         return s[:-ord(s[len(s) - 1:])]