Files
docker-compose-updater/internal/auth/crypto.go
T
ilovintit cea9b941cf
Build and Push / build (push) Failing after 13m20s
Initial commit: docker-compose-updater
Go 项目,包含:
- 服务端 updater:两阶段协议,ECDSA 签名验证,AES-GCM 加密
- 发送端 dcu-send:Gitea Action CLI
- internal/auth:加解密/签名/会话管理
- internal/docker:Docker CLI 容器查找/拉取/重建
- action/:Gitea Action 定义
- deploy/Dockerfile:多阶段构建
- .gitea/workflows/build.yaml:CI/CD
2026-06-08 15:16:46 +08:00

76 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package auth 提供加解密、签名验签和会话密钥管理。
// 发送端 (dcu-send) 和接收端 (updater) 共用此包。
package auth
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"fmt"
"io"
"golang.org/x/crypto/hkdf"
)
// Encrypt 用 AES-256-GCM 加密明文,返回 nonce+ciphertext。
// key 必须是 32 字节。
func Encrypt(plaintext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("aes new cipher: %w", err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("aes gcm: %w", err)
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, fmt.Errorf("nonce: %w", err)
}
// GCM 附加认证数据 (AAD) 传空
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
return ciphertext, nil
}
// Decrypt 用 AES-256-GCM 解密,输入为 nonce+ciphertext。
func Decrypt(data []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("aes new cipher: %w", err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("aes gcm: %w", err)
}
nonceSize := gcm.NonceSize()
if len(data) < nonceSize {
return nil, fmt.Errorf("ciphertext too short")
}
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, fmt.Errorf("aes decrypt: %w", err)
}
return plaintext, nil
}
// DeriveKey 用 HKDF-SHA256 从 shared_secret 和 context 派生出 AES-256 密钥。
// salt: 每个请求的 nonce16 字节)
// info: 协议标识,如 "dcu-updater/v1"
func DeriveKey(sharedSecret []byte, salt []byte, info string) []byte {
hkdf := hkdf.New(sha256.New, sharedSecret, salt, []byte(info))
key := make([]byte, 32) // AES-256
if _, err := io.ReadFull(hkdf, key); err != nil {
// HKDF 使用 SHA-256,从不会返回错误
panic(fmt.Sprintf("hkdf read: %v", err))
}
return key
}