Golang中如何使用OpenSSL签名HTTP请求
Golang中如何使用OpenSSL签名HTTP请求 大家好, 我们有一个私有的RSA密钥和一个密码短语, 如何使用这个密钥对请求进行签名?
我知道如何使用证书对请求进行签名,并且以下方法有效:
cert, err := tls.LoadX509KeyPair(path+"user.crt", path+"user.key")
if err != nil {
log.Fatal(err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
}
t := &http.Transport{
TLSClientConfig: tlsConfig,
}
client := &http.Client{
Transport: t,
}
.....
.....
resp, err := client.Do(request)
它运行得很好…
但是在Go语言中如何实现同样的功能呢?这里有一个用PHP完成的示例:
....
$data = json_encode($data);
$privateKey = openssl_pkey_get_private(
file_get_contents(__DIR__ . 'private.pem'),
file_get_contents(__DIR__ . 'password.txt')
);
openssl_sign($data, $sign, $privateKey);
$sign = base64_encode($sign);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'apiurl');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Sign: ' . $sign,
]);
在Go语言中如何获取签名呢?
更多关于Golang中如何使用OpenSSL签名HTTP请求的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中如何使用OpenSSL签名HTTP请求的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,你可以使用crypto/rsa和crypto/x509包来加载私钥并进行签名。以下是一个完整的示例:
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
// 加载加密的PEM私钥
func loadPrivateKey(keyPath, password string) (*rsa.PrivateKey, error) {
// 读取密钥文件
keyBytes, err := ioutil.ReadFile(keyPath)
if err != nil {
return nil, err
}
// 解码PEM块
block, _ := pem.Decode(keyBytes)
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block")
}
// 如果密钥是加密的,使用密码解密
if x509.IsEncryptedPEMBlock(block) {
decryptedBlock, err := x509.DecryptPEMBlock(block, []byte(password))
if err != nil {
return nil, err
}
block.Bytes = decryptedBlock
block.Type = "RSA PRIVATE KEY"
}
// 解析私钥
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
// 尝试PKCS8格式
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return key.(*rsa.PrivateKey), nil
}
return privateKey, nil
}
// 使用私钥对数据进行签名
func signData(data []byte, privateKey *rsa.PrivateKey) (string, error) {
// 创建数据的哈希
hashed := sha256.Sum256(data)
// 使用PKCS1v15进行签名
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])
if err != nil {
return "", err
}
// 返回Base64编码的签名
return base64.StdEncoding.EncodeToString(signature), nil
}
func main() {
// 你的数据
data := map[string]interface{}{
"name": "test",
"value": 123,
}
// 将数据转换为JSON
jsonData, err := json.Marshal(data)
if err != nil {
log.Fatal(err)
}
// 加载私钥(假设私钥文件为private.pem,密码从文件读取)
passwordBytes, err := ioutil.ReadFile("password.txt")
if err != nil {
log.Fatal(err)
}
password := string(passwordBytes)
privateKey, err := loadPrivateKey("private.pem", password)
if err != nil {
log.Fatal(err)
}
// 对数据进行签名
signature, err := signData(jsonData, privateKey)
if err != nil {
log.Fatal(err)
}
// 创建HTTP请求
req, err := http.NewRequest("POST", "https://apiurl", bytes.NewBuffer(jsonData))
if err != nil {
log.Fatal(err)
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Sign", signature)
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 处理响应
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
如果你使用的是PKCS8格式的私钥,这里还有一个使用crypto/rsa和crypto/x509的替代方案:
// 使用PKCS8格式的私钥
func loadPKCS8PrivateKey(keyPath, password string) (*rsa.PrivateKey, error) {
keyBytes, err := ioutil.ReadFile(keyPath)
if err != nil {
return nil, err
}
block, _ := pem.Decode(keyBytes)
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block")
}
// 解密加密的PKCS8私钥
var decryptedKey []byte
if block.Type == "ENCRYPTED PRIVATE KEY" {
decryptedKey, err = x509.DecryptPEMBlock(block, []byte(password))
if err != nil {
return nil, err
}
} else {
decryptedKey = block.Bytes
}
key, err := x509.ParsePKCS8PrivateKey(decryptedKey)
if err != nil {
return nil, err
}
return key.(*rsa.PrivateKey), nil
}
这个实现与你的PHP代码功能相同:
- 加载加密的PEM私钥
- 使用密码解密私钥
- 对JSON数据进行SHA256哈希
- 使用RSA私钥进行PKCS1v15签名
- 将签名进行Base64编码
- 将签名添加到HTTP请求头中

