在日常开发中,经常需要临时加密一小段敏感文本(如配置密钥、API Token),但打开各种在线加密网站既繁琐又不安全。今天我们用 OpenCode 写一个命令行 AES-GCM 加解密工具,从标准输入读取明文/密文,通过 Base64 编码输出,方便复制粘贴。
crypto/aes、crypto/cipher、encoding/base64)-e 加密模式 / -d 解密模式,-k 指定密钥npm install -g opencode(或参考 opencode.ai)opencode 启动交互直接告诉 OpenCode 我们要做什么,它会自动创建项目结构。
> 我对 OpenCode 说:
> ```
> 创建一个 Go 项目目录 crypto-cli,初始化 go module,
> 我要做一个命令行文本加解密工具,从标准输入读取数据。
> ```
OpenCode 执行了 mkdir crypto-cli && cd crypto-cli && go mod init crypto-cli,并创建了空的 main.go。
要点:不用手动敲 go mod init,直接用自然语言描述意图,OpenCode 会推断需要的命令并执行。
> 我对 OpenCode 说:
> ```
> 在 main.go 中实现 AES-GCM 加密功能:
> - 从 stdin 读取全部输入作为明文
> - 用 -k 参数接收密钥字符串(自动补齐到 16/24/32 字节)
> - 加密结果用 Base64 编码后输出到 stdout
> - 错误信息输出到 stderr
> ```
OpenCode 直接写出了完整的 main.go,包含密钥补齐逻辑、AES-GCM 加密、随机 Nonce 生成和 Base64 输出。
要点:我特意描述了密钥"自动补齐"的需求,OpenCode 理解了并实现了对 3 种 AES 密钥长度(AES-128/192/256)的自动适配——你不需要自己查 crypto/aes 的文档。
> 我对 OpenCode 说:
> ```
> 增加解密模式,用 -d 参数触发:
> - 从 stdin 读取 Base64 密文
> - 先用 base64.StdEncoding.DecodeString 解码
> - 分离 Nonce 和密文,调用 aesgcm.Open 解密
> - 明文直接输出到 stdout
> ```
OpenCode 新增了解密分支,完整处理了 Nonce 提取、Base64 解码、GCM 解密。它甚至贴心地检查了密文长度是否合法,防止无效输入导致 panic。
要点:不需要解释 Nonce 的结构或 GCM 的 Seal/Open 签名,OpenCode 自己知道 Seal 会把 Nonce 拼接在密文前面,解密时按 NonceSize() 切分即可。
> 我对 OpenCode 说:
> ```
> 编译这个项目,然后用 echo 和管道测试加解密流程,
> 确认加密后能正确解密回原文。
> ```
OpenCode 运行了:
go build -o crypto-cli.exe . echo "Hello OpenCode!" | ./crypto-cli -e -k "my-secret-key" # 输出:pWQkZ7...Base64密文... echo "pWQkZ7..." | ./crypto-cli -d -k "my-secret-key" # 输出:Hello OpenCode!
两次输出完全一致,加解密验证通过。
要点:OpenCode 会自动构建然后执行测试命令,你不需要记住 go build 的交叉编译参数,说"编译测试"就够了。
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"flag"
"fmt"
"io"
"os"
)
func main() {
encrypt := flag.Bool("e", false, "加密模式")
decrypt := flag.Bool("d", false, "解密模式")
key := flag.String("k", "", "加密密钥")
flag.Parse()
if *key == "" {
fmt.Fprintln(os.Stderr, "错误:必须提供密钥 (-k)")
os.Exit(1)
}
keyBytes := padKey([]byte(*key))
block, err := aes.NewCipher(keyBytes)
if err != nil {
fmt.Fprintf(os.Stderr, "创建 cipher 失败: %v\n", err)
os.Exit(1)
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
fmt.Fprintf(os.Stderr, "创建 GCM 失败: %v\n", err)
os.Exit(1)
}
input, err := io.ReadAll(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "读取输入失败: %v\n", err)
os.Exit(1)
}
if *encrypt {
ciphertext := encryptData(aesgcm, input)
fmt.Println(base64.StdEncoding.EncodeToString(ciphertext))
} else if *decrypt {
plaintext, err := decryptData(aesgcm, input)
if err != nil {
fmt.Fprintf(os.Stderr, "解密失败: %v\n", err)
os.Exit(1)
}
fmt.Print(string(plaintext))
} else {
fmt.Fprintln(os.Stderr, "用法: crypto-cli -e|-d -k <密钥> < 输入")
flag.Usage()
os.Exit(1)
}
}
func padKey(key []byte) []byte {
switch {
case len(key) < 16:
padded := make([]byte, 16)
copy(padded, key)
return padded
case len(key) < 24:
padded := make([]byte, 24)
copy(padded, key)
return padded
case len(key) < 32:
padded := make([]byte, 32)
copy(padded, key)
return padded
default:
return key[:32]
}
}
func encryptData(gcm cipher.AEAD, plaintext []byte) []byte {
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
fmt.Fprintf(os.Stderr, "生成 Nonce 失败: %v\n", err)
os.Exit(1)
}
return gcm.Seal(nonce, nonce, plaintext, nil)
}
func decryptData(gcm cipher.AEAD, raw []byte) ([]byte, error) {
data, err := base64.StdEncoding.DecodeString(string(raw))
if err != nil {
return nil, fmt.Errorf("Base64 解码失败: %w", err)
}
nonceSize := gcm.NonceSize()
if len(data) < nonceSize {
return nil, fmt.Errorf("密文太短")
}
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
return gcm.Open(nil, nonce, ciphertext, nil)
}
从创建项目到编译测试成功,整个过程不到 4 分钟。我自己只需做两件事:描述需求和验证结果。中间所有的代码编写、命令执行、错误处理,全部由 OpenCode 完成。
如果手写这段代码,我需要查阅 crypto/cipher 的 AEAD 接口、GCM 的 NonceSize、Base64 的编解码 API——至少要多花 10-15 分钟。OpenCode 的价值不在于"替你写代码",而在于让你保持心流,不被查文档打断思路。
这个工具已经可以直接使用:
# 加密 echo "数据库密码是 p@ssw0rd" | ./crypto-cli -e -k "my-key" > secret.txt # 解密 cat secret.txt | ./crypto-cli -d -k "my-key"