2024年4月14日 星期日

Python 學習筆記 : 用 AES-Encryption 為帳號密碼加密與解密

周末將兩年半前買的 "Python 金融市場大賺錢投資聖經" 這本書帶回鄉下看, 我記得裡面有寫一些網路爬蟲的密技, 在其中第三章看到作者描述如何用 AES 為帳號密碼等機敏資料加密, 覺得還蠻有用的, 今天就來測試看看唄.


1. 下載 AES-Encryption : 

到下面這個 GitHub 下載 AES-Encryption 的模組 : 

按右上角的 Code 鈕選擇 Download ZIP 下載壓縮檔 : 




將此壓縮檔 AES-Encryption-main.zip 解開, 如果產生兩層 AES-Encryption 資料夾, 就複製最下層的 AES-Encryption 資料夾到工作目錄下, 例如我的工作目錄是 D:\python\test\ 則子目錄 AES_Encryption 底下就是解開的兩個 .py 檔 : 




第一個模組 en_decrype.py 利用一個第三方模組 Crypto 來做 AES 加密解密作; 第二個模組 encrype_process.py 則是利用 en_decrype.py 編寫了加密函式 input_new_encrype() 與解密函式 check_encrype(), 不過實際上使用時只需要呼叫 check_encrype() 即可, 若未找到密鑰名稱, 它會自動呼叫 input_new_encrype() 讓你輸入帳號密碼與名稱來建立密鑰. 這三個模組關係如下 :

Crypto 
     |__ encrype_process
                |__ encrype_process

所以要讓 check_encrype() 能用必須先有 Crypto 模組才行. Crypto 模組在 Python 中正式名稱是 pycrypto, 不過此套件已經停止更新很久了, 必須改安裝它的延伸套件 pycryptodome, 它裡面就有 Crypto 模組, 參考 :



2. 安裝 pycryptodome 套件 : 

可以使用 pip install 指令直接安裝 :

pip install pycryptodome 

D:\python\test>pip install pycryptodome   
Collecting pycryptodome
  Using cached pycryptodome-3.20.0-cp35-abi3-win_amd64.whl.metadata (3.4 kB)
Using cached pycryptodome-3.20.0-cp35-abi3-win_amd64.whl (1.8 MB)
Installing collected packages: pycryptodome
Successfully installed pycryptodome-3.20.0

我在 Thonny 套件管理安裝了最新版的 v3.20.0 :




安裝完就可匯入 Crypto 模組了 :

>>> import Crypto  
>>> dir(Crypto)   
['Cipher', 'Hash', 'Protocol', 'Random', 'Util', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'version_info']

上面 en_decrypt.py 裡面第一行就是從 Crypto.Cipher 匯入 AES 類別來進行加密與解密 : 

from Crypto.Cipher import AES 

但我們只要直接使用上面 AES-Encryption 套件中第二個模 encrype_process.py 的 check_encrype() 函式就可以進行加密解密了. 


3. 使用 AES_encryption 套件 : 

使用 AES_Encryption 套件進行加密解密只要從它的 encrype_process 模組中匯入全部函式即可 :

from AES_Encryption.encrype_process import *

>>> from AES_Encryption.encrype_process import *     # 注意是 encrype 不是 encrypt

不過 encrype_process 模組中的 input_new_encrype() 函式是作者為了 Gmail 登入帳密而特製, 我將其改為較一般化的設定指引, 將其中 print() 與 input() 中的英文提示修改如下 :

def input_new_encrype(fuc_name,key_path,result_path):
    print(f'名稱:{fuc_name}')
    user_id = input('帳號:')
    password = input('密碼:')
    print(result_path)
    result_file_path = (result_path+'encrype.config').replace('\n','')
    key = get_key(key_path,result_path)
    user_encrype = aes_encrypt(user_id, key)
    password_encrype = aes_encrypt(password, key)
    store_encrype = dict()
    store_encrype['name'] = fuc_name
    store_encrype['user_id'] = user_encrype
    store_encrype['password'] = password_encrype
    with open(result_file_path, 'a') as outfile:
        json.dump(store_encrype, outfile)
        outfile.write('\n')
    outfile.close()
    print('加密完成!')
    return user_id,password

參考 :


然後設定儲存金鑰檔與設定檔的資料夾路徑變數, 注意, 最好不要放在工作目錄下, 否則打包時很容易把金鑰都打包進去分享給他人, 其次是路徑結尾必須有斜線 "/", 例如 : 

>>> key_path="D:/key/"             # 金鑰路徑
>>> config_path="D:/config/"    # config 檔路徑

然後呼叫 check_encrype() 函式並傳入金鑰名稱, 金鑰路徑, 與設定檔路徑, 如果金鑰名稱存在會傳回解碼後的帳號與密碼組成之 tuple, 否則會出現輸入框要求設定金鑰名稱與鑰加密之帳密 : 

user_id, password=check_encrype(name, key_path, config_path)     

例如要加密我的網站 tony1966.cc 的登入帳密 : 

>>> user, pwd=check_encrype('tony1966.cc', key_path, config_path)    
名稱:tony1966.cc  
帳號:admin  
密碼:123456  
D:/config/  
加密完成!  

這時檢視 D 碟會發現已建立 key 與 config 這兩個資料夾, 裡面分別有 key.key 與 encrype.config 這兩個檔案 :





用 utf-8 編碼格式開啟 key.key 會發現是不可讀之亂碼 : 

�����\=�NA��6w�|���Y���7�

開啟 encrype.config 則是加密過的明碼 : 

{"name": "tony1966.cc", "user_id": "SgALjY8Tq7EnCo2uM45Z/MyIXtUU65qJDgDEDQv5jKE=\n", "password": "RlqD34SyRjK/Q3tGB9jx3dycB0PB9HiW1wrCtYfdYsU=\n"}

再次執行 check_encrype() 時因為有找到金鑰名稱 tony1966.cc 所以就傳回解碼後的帳密 : 

>>> user, pwd=check_encrype('tony1966.cc', key_path, config_path)    
>>> user   
'admin'  
>>> pwd    
'123456'   

這樣就能增強帳號密碼的安全性了. 如果要重設帳密, 只要將 key 與 config 這兩個資料夾刪除, 重新呼叫 check_encrype() 就可以再次設定了. 當然也可以用來儲存 OpenAI API 的 key, 例如 name 名稱可以取名為 tony1966_openai_key, 前面是註冊的 email 帳號 (我有多個帳號), 帳號就用 email, 而密碼就輸入 API Key, 解密回來時就用 password 當 API Key 用. 


2024-04-15 補充 :

我把修改後的 AES_Encryption 資料夾壓縮後放在 GitHub : 


沒有留言 :