您好,登錄后才能下訂單哦!
背景
在實際項目實施中,會編寫很多在服務器執行的作業腳本。程序中凡是涉及到數據庫鏈接、操作系統用戶鏈接、IP地址、主機名稱的內容都是敏感信息。在純內網系統中往因為開發時間緊迫,往往都直接將這些敏感信息明文方式寫在腳本中了。
稍微規范一點的,創建一個通用的config文件,將所有這類敏感信息記錄在這個文件中,腳本以讀取文件方式獲取這些信息。這種方式的好處是腳本不用在應用遷移、災備部署的時候再起不同的版本,尤其是大數據平臺作業運行的腳本,如果是需要做災備集群,這種方式可以減少生產變更時的人工干預操作。但是這種方式仍不能解決安全性的問題,只要config文件泄露,那么平臺會非常危險。
因此在這個config文件的基礎上,對其進行改造,實現對內容的加密,而腳本使用時再對其進行解密。因此要求有一個程序能對文本內容進行加密,也能進行反向解密。
不可逆的加密方法使用最多的就是md5加密算法,我們一般用來檢驗文件的完整和安全性,不適用這個場景。
使用python語言對文本內容進行加解密有多種方式,從網上搜索結果看主要有以下幾種:
1.方法一 使用base64轉編碼
Base64是一種用64個字符來表示任意二進制數據的方法。
用記事本打開exe、jpg、pdf這些文件時,我們都會看到一大堆亂碼,因為二進制文件包含很多無法顯示和打印的字符,所以,如果要讓記事本這樣的文本處理軟件能處理二進制數據,就需要一個二進制到字符串的轉換方法。Base64是一種最常見的二進制編碼方法。
Base64的原理很簡單,首先,準備一個包含64個字符的數組:
['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/
']
然后,對二進制數據進行處理,每3個字節一組,一共是3x8=24bit,劃為4組,每組正好6個bit,得到4個數字作為索引,然后查表,獲得相應的4個字符,就是編碼后的字符串。
所以,Base64編碼會把3字節的二進制數據編碼為4字節的文本數據,長度增加33%,好處是編碼后的文本數據可以在郵件正文、網頁等直接顯示。
如果要編碼的二進制數據不是3的倍數,最后會剩下1個或2個字節怎么辦?
Base64用\x00字節在末尾補足后,再在編碼的末尾加上1個或2個=號,表示補了多少字節,解碼的時候,會自動去掉。
Python內置的base64可以直接進行base64的編解碼:
import base64 userPassword="sunlinemdp201810" unkownPassword=base64.b64encode(bytes(userPassword,'utf-8')) print("加密后:"+str(unkownPassword,'utf-8')) kownPassword=str(base64.b64decode(unkownPassword),'utf-8') print('解密后:'+kownPassword)
補充說明:python3中對字符串加解密的方法 base64.encodestring('test')
不能用 因此只能采用bytes方法然后中間進行格式轉換
由于標準的Base64編碼后可能出現字符+和/,在URL中就不能直接作為參數,所以又有一種"url urlsafe_b64encode"的base64編碼方法,實現對+和/的轉碼,在現在使用的版本中這個功能已經整合在b64encode方法中了
userPassword="sunlinemdp201810" unkownPassword=base64.b64encode(bytes(userPassword,'utf-8')) print("加密后:"+str(unkownPassword,'utf-8')) unkownPassword=base64.urlsafe_b64encode(bytes(userPassword,'utf-8')) print("解密后:"+str(unkownPassword,'utf-8')) base64.urlsafe_b64decode(unkownPassword)
2.方法二 win32com.client
樣例代碼如下:
import win32com.client def encrypt(key,content): # key:密鑰,content:明文 EncryptedData = win32com.client.Dispatch('CAPICOM.EncryptedData') EncryptedData.Algorithm.KeyLength = 5 EncryptedData.Algorithm.Name = 2 EncryptedData.SetSecret(key) EncryptedData.Content = content return EncryptedData.Encrypt() def decrypt(key,content): # key:密鑰,content:密文 EncryptedData = win32com.client.Dispatch('CAPICOM.EncryptedData') EncryptedData.Algorithm.KeyLength = 5 EncryptedData.Algorithm.Name = 2 EncryptedData.SetSecret(key) EncryptedData.Decrypt(content) str = EncryptedData.Content return str s1 = encrypt('sunline', 'hello world') s2 = decrypt('sunline', s1) print s1,s2
win32com是python操作windows程序的第三方包,放在服務器上使用不太合適。
3.方法三 PyCrypto
一個極好的用于信息安全的python庫,包括所有主流算法。
具體可以參考:
附pycrypto調用方法
服務器文件加密實現
現在假定要對一個存儲各類ip、賬戶、密碼的global.properties文件進行加密,同時,支持在讀取時進行解密。
global.properties的內容假定如下圖所示:
bgp.inceptor.in1.ip=10.22.179.13 bgp.inceptor.in1.default=cmr bgp.inceptor.in2.ip=10.22.179.14 bgp.inceptor.in2.default=default bdp.ldap.mdp.username=mdp bdp.ldap.mdp.password=mdp
每一行使用等號將信息分為兩段,等號左邊是信息項名稱,等號右邊是信息項具體的內容,我們要對信息項的具體的內容進行加密。
首先做需求分析,我們的需求可以拆分為以下幾個:
第二步做程序設計,我是從功能上進行拆分設計:
基本功能包括:
交互操作包括:
輸入輸出設計:
第三步,首先根據他人提供的方法做了一個對具體字符串進行加解密的類,唯一多做的處理就是對加密使用的密鑰多了一個base64編碼的過程,文件保存為optcrypt.py:
#coding: utf8
'''
實現對指定字符串內容基于某個密鑰的加解密內容輸出
密鑰使用base64多加一層處理
version: v0.0.1 author: Duwj date: 2018-10-24 ''' import sys from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex import base64 class optcrypt(): def __init__(self, key): self.key = str(base64.b64decode(key)) self.mode = AES.MODE_CBC #self.iv = Random.new().read(AES.block_size) #加密函數,如果text不是16的倍數【加密文本text必須為16的倍數!】,那就補足為16的倍數 def aesencrypt(self, text): #密鑰key 長度必須為16(AES-128)、24(AES-192)、或32(AES-256)Bytes 長度.目前AES-128足夠用 cipher = AES.new(self.key, self.mode, self.key) #cipher=AES.new(bytes(self.key), self.mode,Random.new().read(AES.block_size)) #加密文本text必須為16的倍數 add = 16 - (len(text) % 16) text = text + ('\0' * (16 - (len(text) % 16))) self.ciphertext = cipher.encrypt(text) #因為AES加密時候得到的字符串不一定是ascii字符集的,輸出到終端或者保存時候可能存在問題 #所以這里統一把加密后的字符串轉化為16進制字符串 return b2a_hex(self.ciphertext) #解密 def aesdecrypt(self, text): cryptor = AES.new(self.key, self.mode, self.key) #16進制轉回后解密 plain_text = cryptor.decrypt(a2b_hex(text)) #rstrip()去掉補的空格 return plain_text.rstrip('\0') if __name__ == '__main__': #設置環境編碼 reload(sys) sys.setdefaultencoding('utf8') #測試 pc = optcrypt('c3VubGluZW1kcDIwMTgxMQ==') e = pc.aesencrypt("duwj") d = pc.aesdecrypt("d518cdd30b854b84f5aa7c5511e03e38") print "info:duwj,encrypt:"+e+",decrypt:"+d 然后就是依托這個基礎的字符串加解密類,實現對字符串、文件、信息項的加解密功能,在這個過程中沒有對復雜的properties結構進行解析,單純的使用=實現信息項和密文內容的分離,文件保存為server.py: #!bin/python #-*- coding: UTF-8 -*- '''
腳本功能:
1. 實現對指定字符串內容基于某個密鑰的加解密內容輸出
2. 讀取指定加密配置文件,根據信息項名稱讀取指定內容后加解密輸出
3. 讀取指定配置文件,對文件內每一行信息項的具體內容進行加解密后生成新的加解密后的配置文件
使用說明:python server.py
-d [選擇方法[se 字符串加密 /sd 字符串解密/ie 信息項加密/id 信息項解密/fe 文件加密/fd 文件加密]]
-k [16位密鑰]
-c [加密內容]
-f [文件名稱]
-i [信息項名稱]
字符串加解密必選項: -k -c
信息項加解密必選項: -k -f -i
文件加解密必選項: -k -f
version: v0.0.1 author: Duwj date: 2018-11-05 ''' import os import sys import getopt from optcrypt import optcrypt #字符串加解密 def stringCrpyt(func_name,value): if func_name =="se": crpyt_value=pc.aesencrypt(value) else: crpyt_value=pc.aesdecrypt(value) return crpyt_value #信息項加解密輸出 def infoCrpyt(func_name,file_name,info_name): value="" try: pro_file = open(file_name, 'Ur') for line in pro_file.readlines(): line = line.strip().replace('\n', '') if info_name == line.split('=')[0]: value = line.split('=')[1] #print value except Exception, e: raise e finally: pro_file.close() if func_name == "ie": crpyt_value=pc.aesencrypt(value) elif func_name=="id": crpyt_value=pc.aesdecrypt(value) return crpyt_value #文件加解密 def fileCrpyt(func_name,file_name): try: read_file = open(file_name,'Ur') write_file = open(file_name+"."+func_name+"crypt",'w') if func_name == "fe": for line in read_file.readlines(): line = line.strip().replace('\n', '') if line=="": pass elif line.find("#")!=-1: write_file.write(line+"\n") else: strs=line.split('=')[0]+"="+pc.aesencrypt(line.split('=')[1]) write_file.write(strs+"\n") else: for line in read_file.readlines(): line = line.strip().replace('\n', '') if line.find("#")!=-1: write_file.write(line+"\n") else: strs=line.split('=')[0]+"="+pc.aesdecrypt(line.split('=')[1]) write_file.write(strs+"\n") except Exception, e: raise e finally: read_file.close() write_file.close() return file_name+"."+func_name+"crypt" if __name__ == "__main__": #設置環境編碼 reload(sys) sys.setdefaultencoding('utf8') msg='''使用說明:python server.py -d [選擇方法[se 字符串加密 /sd 字符串解密/ie 信息項加密/id 信息項解密/fe 文件加密/fd 文件加密]] -k [16位密鑰] -c [加密內容] -f [文件名稱] -i [信息項名稱] 字符串加解密必選項: -k -c 信息項加解密必選項: -k -f -i 文件加解密必選項: -k -f ''' #獲取參數 opts, args = getopt.getopt(sys.argv[1:], "d:k:c:f:i:") if len(opts)==0: print msg sys.exit(0) for op, value in opts: if op == "-d": func_name = value elif op == "-k": key_content = value elif op == "-c": txt_content = value elif op == "-f": file_name = value elif op == "-i": info_name = value #print(opts) #初始化密鑰 pc = optcrypt(key_content) #根據功能類型執行 if func_name in("se","sd"): print stringCrpyt(func_name,txt_content) elif func_name in ("ie","id"): print infoCrpyt(func_name,file_name,info_name) elif func_name in ("fe","fd"): print fileCrpyt(func_name,file_name) else: print("there is no function named "+func_name) sys.exit(0)
注意在項目文件夾中增加一個init.py文件以便于腳本能識別optcrypt模塊。
測試腳本test.sh:
#!/bin/bash #依賴python pycrypt模塊 安裝這個模塊的命令是 python setup.py install #系統必須現安裝yum install python-devel #測試加解密程序 #c3VubGluZW1kcDIwMTgxMQ== 是對 sunlinemdp201811 進行base64編碼后的值 可以修改 方法為: # 1.命令行執行 python 進入python編程環境 # 2.執行以下代碼 # import base64 # print s= base64.b64encode("sunlinemdp201811") # 引號內為想編碼的密鑰文本 #幫助 python server.py #字符串加密 python server.py -d se -k c3VubGluZW1kcDIwMTgxMQ== -c sunline #字符串解密 python server.py -d sd -k c3VubGluZW1kcDIwMTgxMQ== -c cd3f4a3b1c4a189d3fe985495f6f963b #文件加密 python server.py -d fe -k c3VubGluZW1kcDIwMTgxMQ== -f global.properties #文件解密 python server.py -d fd -k c3VubGluZW1kcDIwMTgxMQ== -f global.properties.fecrypt #信息項加密輸出 python server.py -d ie -k c3VubGluZW1kcDIwMTgxMQ== -f global.properties -i database.ora10g.username #信息項解密輸出 python server.py -d id -k c3VubGluZW1kcDIwMTgxMQ== -f global.properties.fecrypt -i database.ora10g.username #shell中獲取python輸出值的方法: outputString=`python server.py -d ie -k c3VubGluZW1kcDIwMTgxMQ== -f global.properties -i database.ora10g.username` echo outputString:${outputString} outputFile=`python server.py -d fe -k c3VubGluZW1kcDIwMTgxMQ== -f global.properties` echo outputFile:${outputFile}
輸出結果:
[root@localhost encrypt]# ./test.sh 使用說明:python server.py -d [選擇方法[se 字符串加密 /sd 字符串解密/ie 信息項加密/id 信息項解密/fe 文件加密/fd 文件加密]] -k [16位密鑰] -c [加密內容] -f [文件名稱] -i [信息項名稱] 字符串加解密必選項: -k -c 信息項加解密必選項: -k -f -i 文件加解密必選項: -k -f cd3f4a3b1c4a189d3fe985495f6f963b sunline global.properties.fecrypt global.properties.fecrypt.fdcrypt d518cdd30b854b84f5aa7c5511e03e38 dw outputString:d518cdd30b854b84f5aa7c5511e03e38 outputFile:global.properties.fecrypt
續會對腳本進行內容補充,主要是增加一些之前為了功能實現而忽略的異常處理和日志登記的內容。
附程序代碼地址
附加密算法介紹
總結
以上所述是小編給大家介紹的python實現對服務器腳本敏感信息的加密解密功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。