信封加密簡要
信封加密(Envelope Encryption)是一種應對海量數據的高性能加解密方案,國內的各種公有云都有密鑰管理系統,簡稱 KMS(Key Management Service),該系統中就包含信封加密方案。
一圖勝萬言(圖來自騰訊雲文檔):
    
名詞解釋:
- DEK = data encryption keys
 - KMS = Key Management Service
 - AES = Advanced Encryption Standard
 
加密核心流程:
- 
- 用戶向 KMS 請求的時候,系統會給你返回一對密鑰(明文 key+密文 key), 二者作用不同,明文 key 用來給本地文件加密,密文 key 用來從 KMS 系統獲取明文 key。至於 KMS 系統如何維護二者的對應關係的,這個讀者大可不必擔心。反正 2 個 key 關係非同一般,各司其職,要是真不能理解,可以想想婚姻登記所,傳統婚姻一個主內做家務,一個主外搞錢。
 
 - 
- 用明文 key 加密數據,比如你要加密一個 test.txt 文件什麼的。心急的可能要問,有了明文 key,到底怎麼加密呢?不要慌,我給你看簡單 Python 示例:
 
1from Crypto.Cipher import AES 2key = b'Sixteen byte key' # 這裏就是明文key(here is the plainkey) 3cipher = AES.new(key, AES.MODE_EAX) 4nonce = cipher.nonce 5ciphertext, tag = cipher.encrypt_and_digest(data) # 加密 data,返回 ciphertext(先忽略nonce和tag等) - 
- 假設上面的 text.txt 加密後命名爲 secret.bin,本地加密完成後總要放到一個地方存起來,大陸新聞裏面的貪官,錢財存牆體、保險櫃、小區空房什麼的,如今數字時代,文件一般存到雲存儲中,存起來的時候你不光要存加密文件本身,你還得存密文 key,不然沒法解密,那玩笑就開大了,白忙活。一般加密後明文 key 就刪除了,不留痕跡。加密後的文件和密文 key 一起存起來,好比用信封給包起來?(所以叫信封加密?這是我猜的...)
 
 
解密核心流程:
- 
- 若干年後,你要用數據了。先把信封從存儲系統中拿出來,信裏面有
加密數據+密文 key,你用密文 key 向 KMS 系統請求獲得明文 key,然後你想起上面雪封很久的加密程序,心理想太好了。當初是我親手加密的,現在親手解密,一切就像回到從前,存封許久的密密文件由你來解碼,感覺自己像軍統特務,神祕且居功至偉,這是熟悉的感覺! 
 - 若干年後,你要用數據了。先把信封從存儲系統中拿出來,信裏面有
 - 
- 回到現實,用 KMS 返回的明文 key 解密數據,也搞個簡單示例:
 
1 from Crypto.Cipher import AES 2 key = b'Sixteen byte key' # 還是那個熟悉的明文key(the same plainkey) 3 cipher = AES.new(key, AES.MODE_EAX, nonce=nonce) 4 plaintext = cipher.decrypt(ciphertext) # 解密得到plantext 5 try: 6 cipher.verify(tag) 7 print("The message is authentic:", plaintext) 8 except ValueError: 9 print("Key incorrect or message corrupted") - 
- 拿到數據明文後,閱後即焚燬,白天興奮不安、夜晚難以入眠,幾十年來,這個星球上只有你一個人知道這個機密,太不可思議了 😅。
 
 
好了,虛擬故事講完了,現實中,你不是戴笠,也沒有委員長給你撐腰。
苦哈哈寫代碼纔是日常.....
所謂幫人幫到底,下面我給一個比較完整的僞代碼示例:
 1
 2import requests
 3import base64
 4from Crypto.Cipher import AES    #pip install pycryptodome
 5
 6
 7url = "your_kms_url"
 8
 9
10def gen_signature(method, params, secret_key):
11
12    '''
13    signature
14    '''
15    pass
16
17
18def generate_data_key():
19    '''
20    get planinkey and cipherkey
21    '''
22    params = {
23        'xxx1': 'yyy1',
24        'xxx2': 'yyy2',
25    }
26    params['signature'] = gen_signature()
27    r = requests.get(url, params=params)
28    rdata = r.json()["data"]
29    plainkey, cipherkey = rdata["plaintext"], rdata["ciphertext"]
30    return plainkey,cipherkey
31
32
33def get_plainkey(cipherkey):
34    '''
35    use cipherkey get plainkey"
36    '''
37    params = {
38        'zzz1': 'mmm1'
39        'foo': 'bar'
40    }
41    params["ciphertext"] = cipherkey
42    params['signature'] = gen_signature()
43
44    r = requests.get(url, params=params)
45    rdata = r.json()["data"]
46    plainkey = rdata["plaintext"]
47    return plainkeypt
48
49
50def envelope_encrypt(plainkey):
51    '''encrypt'''
52    key = base64.b64decode(plainkey)
53    with open(to_be_encrypt_file, "rb") as f:
54        data = f.read()
55    cipher = AES.new(key, AES.MODE_SIV)  # chose your aes mode
56    ciphertext, tag = cipher.encrypt_and_digest(data)
57
58    with open(encrypted_file,"wb") as file_out:
59        [ file_out.write(x) for x in (tag, ciphertext) ]
60
61def envelope_decrypt():
62    '''decrypt'''
63    with open(cipherkey_file,'r') as f:
64        cipherkey = f.read()
65    key = getDatakeyPlaintext(cipherkey)
66    key = base64.b64decode(key)
67    if key:
68        with open(encrypted_file,"rb") as file_in:
69            tag, ciphertext = [ file_in.read(x) for x in (16, -1) ]
70        cipher = AES.new(key, AES.MODE_SIV)
71        data = cipher.decrypt_and_verify(ciphertext,tag)
72        with open(decrypt_file,"wb") as file_origin:
73            file_origin.write(data)
74
75def upload_to_cloud(upload_file):
76    '''
77    upload cipherkey and secret file to cloud like aws s3
78    '''
79    pass
80
81
82if __name__ == "__main__":
83
84    to_be_encrypt_file = 'text.txt'          # 待加密文件
85    encrypted_file = "secret.bin"            # 加密後的文件
86    decrypt_file = "origin"                  # 解密後的文件
87    cipherkey_file = "cipherkey"
88
89    plainkey, cipherkey = generate_data_key()
90
91    # encryt
92    envelope_encrypt(plainkey)
93
94    #upload
95    upload_to_cloud(upload_file)
96
97    # decrpyt at someday
98    #envelope_decrypt()
上面的僞代碼只是反應了核心流程,還需要讀者根據自己的業務狀況修改。
       最後修改於: Friday, December 22, 2023
    
版權申明:
- 未標註來源的內容皆為原創,未經授權請勿轉載(因轉載後排版往往錯亂、內容不可控、無法持續更新等);
 - 非營利為目的,演繹本博客任何內容,請以'原文出處'或者'參考鏈接'等方式給出本站相關網頁地址(方便讀者)。
 
相關文章:
- 百度網址收錄api Python示例
 - Linux安裝最新版本Python
 - Google網址收錄api Python示例
 - Linux環境下維護公衆號記錄
 - Wayland環境自動切換壁紙
 - SuperTuxKart 試玩
 - 爲什麼你的kill命令不能列出信號表
 - Linux環境按鍵檢測
 - Wayland環境ksnip無法複製問題解決
 - Wayland環境下截圖加後期修改