You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
mulit-agent/controller/internal/controlplane/secret_store_windows.go

48 lines
1.6 KiB

package controlplane
import (
"fmt"
"runtime"
"unsafe"
"golang.org/x/sys/windows"
)
// protectSecret binds encrypted data to the current Windows user through DPAPI.
// The database stores only this encrypted blob, never a plaintext Provider key.
func protectSecret(value string) ([]byte, error) {
input := []byte(value)
if len(input) == 0 {
return nil, fmt.Errorf("API Key 不能为空")
}
inputBlob := windows.DataBlob{Size: uint32(len(input)), Data: &input[0]}
var outputBlob windows.DataBlob
if err := windows.CryptProtectData(
&inputBlob, nil, nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &outputBlob,
); err != nil {
return nil, fmt.Errorf("无法使用 Windows 数据保护保存 API Key: %w", err)
}
defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(outputBlob.Data))))
protected := unsafe.Slice(outputBlob.Data, int(outputBlob.Size))
result := append([]byte(nil), protected...)
runtime.KeepAlive(input)
return result, nil
}
func unprotectSecret(protected []byte) (string, error) {
if len(protected) == 0 {
return "", fmt.Errorf("未找到 API Key")
}
inputBlob := windows.DataBlob{Size: uint32(len(protected)), Data: &protected[0]}
var outputBlob windows.DataBlob
if err := windows.CryptUnprotectData(
&inputBlob, nil, nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &outputBlob,
); err != nil {
return "", fmt.Errorf("无法读取受保护的 API Key: %w", err)
}
defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(outputBlob.Data))))
plain := unsafe.Slice(outputBlob.Data, int(outputBlob.Size))
result := string(plain)
runtime.KeepAlive(protected)
return result, nil
}