跳到內容

端對端加密 (E2EE)

PushGo 的 E2EE 設計用於保護敏感業務欄位。發送方把要保護的欄位加密後放入 ciphertext,Gateway 只負責透傳密文;用戶端在本機設定金鑰後解密並覆寫展示欄位。

內容是否由 E2EE 保護說明
放入 ciphertext 的業務欄位Gateway 無法讀取明文。
明文請求欄位例如 channel_idpasswordseverity、路由欄位仍依普通請求處理。
HTTP Header依賴 HTTPS/TLS 保護。
投遞元資料Gateway 仍需要基本元資料完成驗證、路由和分發。

E2EE 不是 Gateway 驗證的替代品。你仍然需要 Channel 密碼、可選配的 Gateway Bearer Token 和 HTTPS。

PushGo 用戶端支援 AES-GCM。金鑰長度決定演演算法位數。

金鑰長度演演算法Nonce / IVAuth Tag
16 位元組AES-128-GCM12 位元組16 位元組
24 位元組AES-192-GCM12 位元組16 位元組
32 位元組AES-256-GCM12 位元組16 位元組

二進位佈局:

[ ciphertext (N bytes) ][ auth tag (16 bytes) ][ nonce / iv (12 bytes) ]

最後把這段二進位整體 Base64 編碼,填入 API 的 ciphertext 欄位。

ciphertext 解密後必須是 JSON 物件。用戶端會識別以下 canonical 欄位,並將它們寫回通知負載。

欄位型別行為
titlestring覆蓋通知標題。
bodystring覆蓋訊息正文。
urlstring覆蓋點選跳轉 URL。
imagesstring[] 或 JSON 字串覆寫圖片清單。
tagsstring[] 或 JSON 字串覆寫標籤清單。
metadataobject 或 JSON 字串覆寫 metadata。
欄位型別行為
descriptionstring覆蓋事件描述。
statusstring覆蓋事件狀態。
messagestring覆蓋事件訊息。
started_atnumber覆蓋事件開始時間。
ended_atnumber覆蓋事件結束時間。
attrsobject 或 JSON 字串覆蓋事件 attrs patch。
欄位型別行為
primary_imagestring覆蓋主圖。
statestring覆蓋實體狀態。
created_atnumber覆蓋建立時間。
deleted_atnumber覆蓋刪除時間。
external_idsobject 或 JSON 字串覆寫外部 ID。
location_typestring覆蓋位置型別。
location_valuestring覆蓋位置值。
locationobject 或 JSON 字串覆寫位置物件。
import base64
import json
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def encrypt_payload(key_hex, payload):
key = bytes.fromhex(key_hex)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
plaintext = json.dumps(payload, separators=(",", ":")).encode("utf-8")
cipher_and_tag = aesgcm.encrypt(nonce, plaintext, None)
return base64.b64encode(cipher_and_tag + nonce).decode("utf-8")
payload = {
"title": "資料庫延遲",
"body": "從庫延遲超過 60 秒。",
"tags": ["encrypted", "database"],
"metadata": {"source": "replica-monitor"}
}
key_hex = "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
print(encrypt_payload(key_hex, payload))

key_hex 範例是 32 位元組金鑰,也就是 AES-256-GCM。實際生產中請使用安全隨機金鑰,並在用戶端本機設定相同金鑰。

Terminal window
curl -X POST https://gateway.pushgo.cn/message \
-H "Content-Type: application/json" \
-d '{
"channel_id": "YOUR_CHANNEL_ID",
"password": "YOUR_CHANNEL_PASSWORD",
"title": "加密訊息",
"body": "你的用戶端將嘗試解密 ciphertext。",
"severity": "normal",
"ciphertext": "BASE64_ENCODED_CIPHERTEXT"
}'

明文 titlebody 可以作為未配置金鑰或解密失敗時的退化展示;真正敏感內容應放入 ciphertext

用戶端可能會展示以下狀態:

狀態意義
decryptOk已成功解密並套用至少一個欄位。
decryptFailed存在密文,但解密或 JSON 解析失敗。
notConfigured用戶端未配置可用金鑰。
algMismatch用戶端配置的演演算法與負載不符。
問題檢查項
解密失敗金鑰是否一致;Base64 是否完整;二進位佈局是否為 ciphertext + tag + nonce
用戶端沒有覆寫欄位解密後的 JSON 是否是物件;欄位名稱是否使用 canonical 名稱。
Gateway 仍能看到標題標題如果放在明文欄位就不會被 E2EE 保護;敏感標題也應放入 ciphertext
severity 沒加密這是建議做法,因為 Gateway 和系統推送需要優先資訊進行投遞。