def _is_equal(b_a, b_b): b_b = string2bytes(b_b) b_a = string2bytes(b_a) if not (isinstance(b_a, bytes) and isinstance(b_b, bytes)): return False if len(b_a) != len(b_b): return False result = 0 for b_x, b_y in zip(b_a, b_b): result |= b_x ^ b_y return result == 0
def _gen_key_initctr(cls, b_password, b_salt): # 16 for AES 128, 32 for AES256 keylength = 32 # match the size used for counter.new to avoid extra work ivlength = 16 b_password = string2bytes(b_password) if HAS_PBKDF2HMAC: backend = default_backend() kdf = PBKDF2HMAC(algorithm=c_SHA256(), length=2 * keylength + ivlength, salt=b_salt, iterations=10000, backend=backend) b_derivedkey = kdf.derive(b_password) else: b_derivedkey = cls._create_key(b_password, b_salt, keylength, ivlength) b_key1 = b_derivedkey[:keylength] b_key2 = b_derivedkey[keylength:(keylength * 2)] b_iv = b_derivedkey[(keylength * 2):(keylength * 2) + ivlength] return b_key1, b_key2, hexlify(b_iv)
def __init__(self, password, header): ''' 对数据/文件进行加解密 :parm password : 加解密密码 :return 返回一个元组,(是否执行成功,成功加密数据/失败原因) ''' self.logger = logging.getLogger("security") self.password = password self.this_cipher = AES256_Algorithm(self.password) result = obj2bytes(header) if result[0]: temp = result[1] else: temp = string2bytes(header) self.b_header = temp result = obj2string(header) if result[0]: temp = result[1] else: temp = bytes2string(header) self.header = temp
def _get_vault_pwd(self): ''' 获取vault密码,并初始化vault密码 ''' vault_pwd_file = self.options_dict.get('vault_password_file', False) ask_vault_pass = self.options_dict.get('ask_vault_pass', False) if ask_vault_pass: vault_password = ask_vault_pass else: if vault_pwd_file: this_path = os.path.realpath( os.path.expanduser(vault_pwd_file)) if os.path.exists(this_path): mode = self.loader.is_executable(this_path) result = read_file(this_path, mode=mode, sprfmt=b'\r\n', outfmt='bytes') if result[0]: vault_password = result[1] else: vault_password = None else: vault_password = None else: vault_password = None if vault_password: b_vault_password = string2bytes(vault_password) self.loader.set_vault_password(b_vault_password) self.vault_password = vault_password else: self.vault_password = None
def _is_encrypt(self, data): ''' 判断加密数据是否使用使用非本系统加解密算法加密的 ''' ciphertext_list = self._split_header(data) temp_header = ciphertext_list[0] result = obj2bytes(temp_header) if result[0]: temp = result[1] else: temp = string2bytes(temp_header) b_header = temp result = obj2string(temp_header) if result[0]: temp = result[1] else: temp = bytes2string(temp_header) header = temp if b_header in self.b_header or header in self.header: return True else: return False
def __init__(self, b_password): ''' 使用AES256加解密数据 ''' self.check_result = check_module() self.logger = logging.getLogger("security") self.b_password = string2bytes(b_password) self.err_msg = "可能您的python3环境中,pycrypto模块版本太低或者没有安装,请升级/安装,请SSH登陆到服务器上,执行pip3 install pycrypto或者pip3 install --upgrade pycrypto"
def __init__(self, password): self.logger = logging.getLogger("ansible") self.password = password from library.config.security import vault_header tmp_header = vault_header + ';date:' + str(time.time()) self.vault_header = tmp_header result = obj2bytes(tmp_header) if result[0]: temp_header = result[1] else: temp_header = string2bytes(tmp_header) self.b_vault_header = temp_header self.cipher = Using_AES256(self.password, self.b_vault_header)
def _split_header(self, data): ''' 对加密数据进行分割,分为加密头和加密数据 :parm data :需要分割的加密数据 ''' result = obj2bytes(data) if result[0]: data = result[1] else: data = string2bytes(data) b_data = data.split(b'\n') b_header = b_data[0].strip() b_ciphertext = b''.join(b_data[1:]) return (b_header, b_ciphertext)
def encrypt(self, data): if not self.check_result: self.logger.error('使用AES256解密加密数据失败,原因:' + self.err_msg) return (False, self.err_msg) if not self.b_password or self.b_password is None: return (False, "加密密码为空") data = obj2bytes(data) if data[0]: b_plaintext = data[1] else: return data b_salt = os.urandom(32) b_key1, b_key2, b_iv = self._gen_key_initctr(self.b_password, b_salt) bs = AES.block_size padding_length = (bs - len(data) % bs) or bs temp = obj2bytes(padding_length * chr(padding_length)) if temp[0]: temp = temp[1] else: return temp b_plaintext += temp ctr = Counter.new(128, initial_value=int(b_iv, 16)) cipher = AES.new(b_key1, AES.MODE_CTR, counter=ctr) b_ciphertext = cipher.encrypt(b_plaintext) hmac = HMAC.new(b_key2, b_ciphertext, SHA256) b_temp_ciphertext = b'\n'.join([ hexlify(b_salt), string2bytes(hmac.hexdigest()), hexlify(b_ciphertext) ]) b_new_ciphertext = hexlify(b_temp_ciphertext) return self._handle_result(b_new_ciphertext)
def _format_output(self, data): ''' 对加密数据进行格式化,仅用于写入文件 :parm ciphertext :需要格式化的数据 ''' result = obj2bytes(data) if result[0]: b_ciphertext = result[1] else: b_ciphertext = string2bytes(data) b_new_ciphertext = [self.b_header] b_new_ciphertext += [ b_ciphertext[i:i + 80] for i in range(0, len(b_ciphertext), 80) ] b_new_ciphertext += [b''] b_new_ciphertext = b'\n'.join(b_new_ciphertext) return b_new_ciphertext
def _handle_ciphertext(self, data=None, filename=None): ''' 对加密数据/文件内容的头部进行判断使用哪种方式加密 data或者filename其中一个可以为空,至少一个不能为空 如果两个均不为空,默认使用filename :parm data:加密数据 filename:加密文件 :return 算法或者False ''' if data is None and filename is None: self.logger.error('解密ansible加密数据时出错,原因:参数data和filename不能同时为空') return (False, False, '参数data和filename不能同时为空') if filename is not None: result = read_file(filename) if result[0]: data = result[1] else: if data is None: self.logger.error('解密ansible文件' + filename + '时出错,无法读取文件,原因:' + result[1]) return (False, False, '无法读取文件') result = obj2bytes(data) if result[0]: b_data = result[1] else: b_data = string2bytes(data) b_data = b_data.split(b'\n') b_vault_header = b_data[0].strip() b_ciphertext = b''.join(b_data[1:]) vault_header = obj2string(b_vault_header)[1] if b_vault_header in self.b_vault_header: #这是自定义加密数据 self.logger.info('解密ansible加密数据成功,注:加密数据使用本系统自定义方法加密的') return (True, True, b_data) elif re.search('ANSIBLE_VAULT;1.1;', vault_header): #这是ansible2.3版本加密数据 # return (False, True, data) #在ansible 2.3版本中,vault加密后头部为'$ANSIBLE_VAULT;1.1;AES256',其他版本未知 if vault_header == '$ANSIBLE_VAULT;1.1;AES256': #说明加密方式为AES256,自定义加密算法一直,直接使用自定义方式进行解密 data = self.b_vault_header + b'\n' + b_ciphertext result = obj2bytes(data) if result[0]: self.logger.info('解密ansible加密数据成功,注:加密数据使用ansible2.3版本加密的') return (True, False, result[1]) else: self.logger.error( '解密ansible加密数据时失败,原因:加密数据使用ansible2.3版本加密的,' + str(result[1])) return (False, True, data) else: self.logger.error('解密ansible加密数据时失败,原因:未知格式的加密方法') return (False, True, data) else: self.logger.error('解密ansible加密数据时失败,原因:未知格式的加密方法') return (False, False, '未知格式的加密数据')