diff --git a/crypto/aliyun_kms.go b/crypto/aliyun_kms.go deleted file mode 100644 index f90d9378..00000000 --- a/crypto/aliyun_kms.go +++ /dev/null @@ -1,216 +0,0 @@ -package crypto - -import ( - "encoding/base64" - "fmt" - "os" - - kms "github.com/aliyun/alibaba-cloud-sdk-go/services/kms" -) - -// AliyunKMSManager 阿里雲 KMS 管理器 -type AliyunKMSManager struct { - client *kms.Client - keyID string // 主密鑰 ID -} - -// NewAliyunKMSManager 創建阿里雲 KMS 管理器 -func NewAliyunKMSManager() (*AliyunKMSManager, error) { - // 從環境變數讀取配置 - accessKeyID := os.Getenv("ALIYUN_ACCESS_KEY_ID") - accessKeySecret := os.Getenv("ALIYUN_ACCESS_KEY_SECRET") - regionID := os.Getenv("ALIYUN_REGION_ID") // 如 cn-hangzhou - keyID := os.Getenv("ALIYUN_KMS_KEY_ID") // 主密鑰 ID - - if accessKeyID == "" || accessKeySecret == "" { - return nil, fmt.Errorf("阿里雲憑證未配置,請設置環境變數 ALIYUN_ACCESS_KEY_ID 和 ALIYUN_ACCESS_KEY_SECRET") - } - - if keyID == "" { - return nil, fmt.Errorf("KMS 密鑰 ID 未配置,請設置環境變數 ALIYUN_KMS_KEY_ID") - } - - // 創建 KMS 客戶端 - client, err := kms.NewClientWithAccessKey(regionID, accessKeyID, accessKeySecret) - if err != nil { - return nil, fmt.Errorf("創建 KMS 客戶端失敗: %w", err) - } - - return &AliyunKMSManager{ - client: client, - keyID: keyID, - }, nil -} - -// Encrypt 使用 KMS 加密數據 -func (m *AliyunKMSManager) Encrypt(plaintext string) (string, error) { - request := kms.CreateEncryptRequest() - request.Scheme = "https" - request.KeyId = m.keyID - request.Plaintext = plaintext - - response, err := m.client.Encrypt(request) - if err != nil { - return "", fmt.Errorf("KMS 加密失敗: %w", err) - } - - return response.CiphertextBlob, nil -} - -// Decrypt 使用 KMS 解密數據 -func (m *AliyunKMSManager) Decrypt(ciphertext string) (string, error) { - request := kms.CreateDecryptRequest() - request.Scheme = "https" - request.CiphertextBlob = ciphertext - - response, err := m.client.Decrypt(request) - if err != nil { - return "", fmt.Errorf("KMS 解密失敗: %w", err) - } - - // Base64 解碼 - plaintext, err := base64.StdEncoding.DecodeString(response.Plaintext) - if err != nil { - return "", fmt.Errorf("解碼失敗: %w", err) - } - - return string(plaintext), nil -} - -// GenerateDataKey 生成數據密鑰(用於本地加密,KMS 僅管理主密鑰) -func (m *AliyunKMSManager) GenerateDataKey() (plaintext, ciphertext string, err error) { - request := kms.CreateGenerateDataKeyRequest() - request.Scheme = "https" - request.KeyId = m.keyID - request.KeySpec = "AES_256" // 256-bit AES 密鑰 - - response, err := m.client.GenerateDataKey(request) - if err != nil { - return "", "", fmt.Errorf("生成數據密鑰失敗: %w", err) - } - - // 明文密鑰(用於加密數據) - plaintextBytes, _ := base64.StdEncoding.DecodeString(response.Plaintext) - plaintext = string(plaintextBytes) - - // 密文密鑰(保存到數據庫,用於後續解密) - ciphertext = response.CiphertextBlob - - return plaintext, ciphertext, nil -} - -// CreateKey 創建新的 KMS 主密鑰(僅管理員操作) -func (m *AliyunKMSManager) CreateKey(description string) (string, error) { - request := kms.CreateCreateKeyRequest() - request.Scheme = "https" - request.Description = description - request.KeyUsage = "ENCRYPT/DECRYPT" - request.Origin = "Aliyun_KMS" // 阿里雲託管 - - response, err := m.client.CreateKey(request) - if err != nil { - return "", fmt.Errorf("創建 KMS 密鑰失敗: %w", err) - } - - return response.KeyMetadata.KeyId, nil -} - -// EnableKeyRotation 啟用自動密鑰輪換(每年自動輪換) -func (m *AliyunKMSManager) EnableKeyRotation() error { - request := kms.CreateEnableKeyRotationRequest() - request.Scheme = "https" - request.KeyId = m.keyID - - _, err := m.client.EnableKeyRotation(request) - if err != nil { - return fmt.Errorf("啟用密鑰輪換失敗: %w", err) - } - - return nil -} - -// ==================== 與現有加密系統集成 ==================== - -// EncryptionManagerWithKMS 混合加密管理器(本地 + KMS) -type EncryptionManagerWithKMS struct { - localEM *EncryptionManager - kmsEM *AliyunKMSManager - useKMS bool // 是否使用 KMS -} - -// NewEncryptionManagerWithKMS 創建混合加密管理器 -func NewEncryptionManagerWithKMS() (*EncryptionManagerWithKMS, error) { - // 初始化本地加密 - localEM, err := GetEncryptionManager() - if err != nil { - return nil, err - } - - // 嘗試初始化 KMS(如果配置了環境變數) - kmsEM, err := NewAliyunKMSManager() - useKMS := err == nil - - if useKMS { - fmt.Println("✅ 阿里雲 KMS 已啟用") - } else { - fmt.Println("⚠️ 阿里雲 KMS 未配置,使用本地加密") - } - - return &EncryptionManagerWithKMS{ - localEM: localEM, - kmsEM: kmsEM, - useKMS: useKMS, - }, nil -} - -// EncryptForDatabase 加密數據(自動選擇 KMS 或本地) -func (m *EncryptionManagerWithKMS) EncryptForDatabase(plaintext string) (string, error) { - if m.useKMS { - // 使用 KMS 加密 - encrypted, err := m.kmsEM.Encrypt(plaintext) - if err != nil { - // KMS 失敗時降級到本地加密 - fmt.Printf("⚠️ KMS 加密失敗,降級到本地加密: %v\n", err) - return m.localEM.EncryptForDatabase(plaintext) - } - return "kms:" + encrypted, nil // 添加前綴標識 - } - - // 使用本地加密 - return m.localEM.EncryptForDatabase(plaintext) -} - -// DecryptFromDatabase 解密數據(自動檢測 KMS 或本地) -func (m *EncryptionManagerWithKMS) DecryptFromDatabase(ciphertext string) (string, error) { - // 檢測是否為 KMS 加密 - if len(ciphertext) > 4 && ciphertext[:4] == "kms:" { - if !m.useKMS { - return "", fmt.Errorf("數據使用 KMS 加密,但 KMS 未配置") - } - return m.kmsEM.Decrypt(ciphertext[4:]) - } - - // 本地解密 - return m.localEM.DecryptFromDatabase(ciphertext) -} - -// MigrateToKMS 將現有本地加密數據遷移到 KMS -func (m *EncryptionManagerWithKMS) MigrateToKMS(localEncrypted string) (string, error) { - if !m.useKMS { - return "", fmt.Errorf("KMS 未啟用") - } - - // 1. 本地解密 - plaintext, err := m.localEM.DecryptFromDatabase(localEncrypted) - if err != nil { - return "", err - } - - // 2. KMS 加密 - kmsEncrypted, err := m.kmsEM.Encrypt(plaintext) - if err != nil { - return "", err - } - - return "kms:" + kmsEncrypted, nil -} diff --git a/scripts/migrate_encryption.go b/scripts/migrate_encryption.go index ae446777..f17fbe7e 100644 --- a/scripts/migrate_encryption.go +++ b/scripts/migrate_encryption.go @@ -8,7 +8,7 @@ import ( "nofx/crypto" - _ "github.com/mattn/go-sqlite3" + _ "modernc.org/sqlite" ) func main() { @@ -38,7 +38,7 @@ func main() { } // 3. 打開數據庫 - db, err := sql.Open("sqlite3", dbPath) + db, err := sql.Open("sqlite", dbPath) if err != nil { log.Fatalf("❌ 打開數據庫失敗: %v", err) }