sdk_generate/internal/prompts/tools/crypt/rsa.go

177 lines
4.5 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.

// rsa.go
package crypt
import (
"context"
"fmt"
"github.com/sashabaranov/go-openai"
"github.com/sashabaranov/go-openai/jsonschema"
)
// ========== RSA签名工具 ==========
type RSASignTool struct{}
func (t *RSASignTool) Name() string { return "rsa_sign" }
func (t *RSASignTool) Description() string {
return "RSA私钥签名实现指南。当文档要求使用RSA算法对请求进行数字签名时使用包含签名串拼接、私钥加载、PKCS1/PKCS8格式处理"
}
func (t *RSASignTool) GetFunctionDefinition() openai.FunctionDefinition {
return openai.FunctionDefinition{
Name: t.Name(),
Description: t.Description(),
Parameters: jsonschema.Definition{
Type: jsonschema.Object,
Properties: map[string]jsonschema.Definition{
"hash_algorithm": {
Type: jsonschema.String,
Description: "哈希算法,可选 SHA256, SHA384, SHA512默认 SHA256",
Enum: []string{"SHA256", "SHA384", "SHA512"},
},
"encoding": {
Type: jsonschema.String,
Description: "输出编码方式base64 或 hex默认 base64",
Enum: []string{"base64", "hex"},
},
},
Required: []string{},
},
}
}
func (t *RSASignTool) GetDetail(ctx context.Context, params map[string]string) (string, error) {
hashAlgo := "SHA256"
if v, ok := params["hash_algorithm"]; ok && v != "" {
hashAlgo = v
}
encoding := "base64"
if v, ok := params["encoding"]; ok && v != "" {
encoding = v
}
return fmt.Sprintf(`
### RSA签名完整实现指南
**适用场景**文档要求使用RSA私钥对请求参数进行签名
**配置参数**
- 哈希算法: %s
- 编码方式: %s
**完整代码模板**
`+"```go"+`
package crypto
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"fmt"
"sort"
"strings"
)
// RSAConfig RSA签名配置
type RSAConfig struct {
PrivateKeyPEM string // PEM格式的私钥
KeyID string // 密钥ID如文档要求携带
}
// SignWithRSA 使用RSA私钥对请求进行签名
func SignWithRSA(params map[string]string, config *RSAConfig) (string, error) {
// 1. 拼接参数(按字典序排序)
keys := make([]string, 0, len(params))
for k := range params {
if k != "sign" && k != "signature" {
keys = append(keys, k)
}
}
sort.Strings(keys)
var sb strings.Builder
for _, k := range keys {
if sb.Len() > 0 {
sb.WriteString("&")
}
sb.WriteString(k)
sb.WriteString("=")
sb.WriteString(params[k])
}
signStr := sb.String()
// 2. 加载私钥
block, _ := pem.Decode([]byte(config.PrivateKeyPEM))
if block == nil {
return "", fmt.Errorf("failed to decode PEM private key")
}
privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
// 尝试PKCS1格式
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("failed to parse private key: %%v", err)
}
}
rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
if !ok {
return "", fmt.Errorf("not a RSA private key")
}
// 3. 计算哈希
var hashed []byte
var hashFunc crypto.Hash
switch "%s" {
case "SHA384":
h := sha512.New384()
h.Write([]byte(signStr))
hashed = h.Sum(nil)
hashFunc = crypto.SHA384
case "SHA512":
h := sha512.New()
h.Write([]byte(signStr))
hashed = h.Sum(nil)
hashFunc = crypto.SHA512
default: // SHA256
h := sha256.New()
h.Write([]byte(signStr))
hashed = h.Sum(nil)
hashFunc = crypto.SHA256
}
// 4. RSA签名
signature, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey, hashFunc, hashed)
if err != nil {
return "", err
}
// 5. 编码
if "%s" == "hex" {
return hex.EncodeToString(signature), nil
}
return base64.StdEncoding.EncodeToString(signature), nil
}
`+"```"+`
**注意事项**
- 确认文档使用的是 PKCS1 还是 PKCS8 格式
- 确认是否需要添加额外的固定盐值
- 确认编码是 Base64 还是 Hex
- 注意排除签名字段本身sign/signature
`, hashAlgo, encoding, hashAlgo, encoding), nil
}
func (t *RSASignTool) Execute(ctx context.Context, params map[string]string) (string, error) {
return t.GetDetail(ctx, params)
}