You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Go实现Github Action Secrets API仓库秘钥加密?

问题分析与修正方案

你的代码存在三个核心问题,导致GitHub无法正确解密秘钥:

  1. 固定全零Nonce:GitHub要求加密必须使用随机生成的24字节nonce,原代码中nonce := new([24]byte)生成的全零nonce会导致解密失败。
  2. 缺少临时公钥:GitHub的加密格式要求将临时生成的公钥(ephemeral public key)放在加密数据最前面,原代码未拼接该公钥,导致GitHub无法用仓库私钥解密原始内容。
  3. 错误处理缺失:忽略了base64解码、密钥生成等步骤的错误,可能引发静默失败。

正确的加密实现

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"

	"golang.org/x/crypto/nacl/box"
)

func EncodeWithPublicKey(text string, publicKey string) (string, error) {
	// 解码仓库公钥并验证长度
	publicKeyBytes, err := base64.StdEncoding.DecodeString(publicKey)
	if err != nil {
		return "", fmt.Errorf("解码公钥失败: %w", err)
	}
	if len(publicKeyBytes) != 32 {
		return "", fmt.Errorf("公钥长度必须为32字节,当前为%d字节", len(publicKeyBytes))
	}

	// 将公钥转换为nacl/box要求的数组格式
	var repoPublicKey [32]byte
	copy(repoPublicKey[:], publicKeyBytes)

	// 生成临时密钥对(每次加密都需要新的密钥对)
	ephemeralPubKey, ephemeralPrivKey, err := box.GenerateKey(rand.Reader)
	if err != nil {
		return "", fmt.Errorf("生成临时密钥对失败: %w", err)
	}

	// 生成随机nonce(必须24字节)
	var nonce [24]byte
	if _, err := rand.Read(nonce[:]); err != nil {
		return "", fmt.Errorf("生成nonce失败: %w", err)
	}

	// 加密明文:box.Seal会将nonce作为前缀拼接在密文前
	encrypted := box.Seal(nonce[:], []byte(text), &nonce, &repoPublicKey, ephemeralPrivKey)

	// 拼接临时公钥到加密数据头部(GitHub API要求的格式)
	finalEncrypted := append(ephemeralPubKey[:], encrypted...)

	// 编码为base64字符串返回
	return base64.StdEncoding.EncodeToString(finalEncrypted), nil
}

关键流程说明

  1. 公钥处理:解码仓库提供的base64公钥,确保长度为32字节(nacl/box要求的Curve25519密钥长度)。
  2. 临时密钥对:每次加密生成新的临时密钥对,用于和仓库公钥完成端到端加密。
  3. 随机Nonce:生成24字节随机nonce,保证加密的唯一性和安全性。
  4. 加密与格式拼接:使用box.Seal生成nonce+密文的组合,再将临时公钥拼接在最前面,形成GitHub要求的临时公钥(32字节)+nonce(24字节)+密文格式。
  5. 错误处理:对所有可能失败的步骤添加错误捕获与返回,便于排查问题。

内容的提问来源于stack exchange,提问作者UDESHYA DHUNGANA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:08:11