Angular中使用Crypto/rsa加密并在Golang中解密的实现方法
Angular中使用Crypto/rsa加密并在Golang中解密的实现方法 我有一个应用程序,需要在Angular中使用公钥进行加密,然后在Golang REST API中使用私钥进行解密。
我已经尝试了crypto/rsa加密,它是有效的。
请指导我。
5 回复
很高兴能帮上忙
更多关于Angular中使用Crypto/rsa加密并在Golang中解密的实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
谢谢。
问题已解决。我在 Angular 端使用了错误的哈希算法。
我想在Angular端使用公钥加密载荷,然后在Golang端使用私钥解密。
我已经尝试过了。但在Golang端无法解密。
你有示例代码吗(包括Angular和Go的)?
你们是如何共享密钥的? 在Angular中你们使用哪种算法,在Go中又使用哪种算法?
在Angular中使用Crypto/rsa加密并在Golang中解密的实现方法
1. Angular端(前端)实现
首先安装必要的依赖:
npm install crypto-js
Angular加密服务示例:
// encryption.service.ts
import { Injectable } from '@angular/core';
import * as CryptoJS from 'crypto-js';
@Injectable({
providedIn: 'root'
})
export class EncryptionService {
// 将PEM格式公钥转换为CryptoKey
async importPublicKey(pemPublicKey: string): Promise<CryptoKey> {
// 移除PEM格式的头部和尾部
const pemHeader = "-----BEGIN PUBLIC KEY-----";
const pemFooter = "-----END PUBLIC KEY-----";
const pemContents = pemPublicKey
.replace(pemHeader, '')
.replace(pemFooter, '')
.replace(/\s/g, '');
// 将Base64转换为ArrayBuffer
const binaryDer = this.base64ToArrayBuffer(pemContents);
return await window.crypto.subtle.importKey(
'spki',
binaryDer,
{
name: 'RSA-OAEP',
hash: { name: 'SHA-256' }
},
false,
['encrypt']
);
}
// 使用RSA-OAEP加密数据
async encryptWithPublicKey(publicKey: CryptoKey, data: string): Promise<string> {
const encoder = new TextEncoder();
const encodedData = encoder.encode(data);
const encryptedData = await window.crypto.subtle.encrypt(
{
name: 'RSA-OAEP'
},
publicKey,
encodedData
);
// 转换为Base64字符串
return this.arrayBufferToBase64(encryptedData);
}
// 辅助方法:Base64转ArrayBuffer
private base64ToArrayBuffer(base64: string): ArrayBuffer {
const binaryString = window.atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
// 辅助方法:ArrayBuffer转Base64
private arrayBufferToBase64(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
}
组件中使用示例:
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { EncryptionService } from './encryption.service';
@Component({
selector: 'app-root',
template: `
<button (click)="encryptAndSend()">加密并发送</button>
`
})
export class AppComponent implements OnInit {
private publicKeyPem = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzXoQkQvKX7J8wJv6z6Z2
...(您的公钥内容)...
-----END PUBLIC KEY-----`;
constructor(private encryptionService: EncryptionService) {}
async encryptAndSend() {
try {
// 导入公钥
const publicKey = await this.encryptionService.importPublicKey(this.publicKeyPem);
// 要加密的数据
const sensitiveData = JSON.stringify({
username: 'john_doe',
password: 'secret123',
timestamp: new Date().toISOString()
});
// 加密数据
const encryptedData = await this.encryptionService.encryptWithPublicKey(
publicKey,
sensitiveData
);
// 发送到Golang后端
const response = await fetch('https://your-api.com/decrypt', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ encryptedData })
});
const result = await response.json();
console.log('解密结果:', result);
} catch (error) {
console.error('加密或发送失败:', error);
}
}
}
2. Golang端(后端)实现
生成RSA密钥对(一次性操作):
// generate_keys.go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
)
func main() {
// 生成2048位的RSA密钥对
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
// 保存私钥到文件
privateKeyFile, err := os.Create("private.pem")
if err != nil {
panic(err)
}
defer privateKeyFile.Close()
privateKeyPEM := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
}
if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil {
panic(err)
}
// 保存公钥到文件
publicKeyFile, err := os.Create("public.pem")
if err != nil {
panic(err)
}
defer publicKeyFile.Close()
publicKeyBytes, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
if err != nil {
panic(err)
}
publicKeyPEM := &pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyBytes,
}
if err := pem.Encode(publicKeyFile, publicKeyPEM); err != nil {
panic(err)
}
fmt.Println("密钥对已生成: private.pem, public.pem")
}
Golang REST API解密实现:
// main.go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
"net/http"
)
var privateKey *rsa.PrivateKey
// 初始化加载私钥
func init() {
// 从文件加载私钥
keyData, err := ioutil.ReadFile("private.pem")
if err != nil {
log.Fatal("无法读取私钥文件:", err)
}
block, _ := pem.Decode(keyData)
if block == nil || block.Type != "RSA PRIVATE KEY" {
log.Fatal("无效的私钥格式")
}
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
log.Fatal("解析私钥失败:", err)
}
}
// 请求结构体
type DecryptRequest struct {
EncryptedData string `json:"encryptedData"`
}
// 响应结构体
type DecryptResponse struct {
Success bool `json:"success"`
Data string `json:"data,omitempty"`
Error string `json:"error,omitempty"`
}
// 解密处理器
func decryptHandler(w http.ResponseWriter, r *http.Request) {
// 设置CORS头部
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")
// 只接受POST请求
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var req DecryptRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
sendError(w, "无效的请求格式", http.StatusBadRequest)
return
}
// Base64解码加密数据
encryptedBytes, err := base64.StdEncoding.DecodeString(req.EncryptedData)
if err != nil {
sendError(w, "Base64解码失败", http.StatusBadRequest)
return
}
// 使用RSA-OAEP解密
decryptedBytes, err := rsa.DecryptOAEP(
sha256.New(),
rand.Reader,
privateKey,
encryptedBytes,
nil, // 标签参数
)
if err != nil {
sendError(w, "解密失败", http.StatusBadRequest)
return
}
// 返回解密后的数据
response := DecryptResponse{
Success: true,
Data: string(decryptedBytes),
}
json.NewEncoder(w).Encode(response)
}
func sendError(w http.ResponseWriter, message string, statusCode int) {
response := DecryptResponse{
Success: false,
Error: message,
}
w.WriteHeader(statusCode)
json.NewEncoder(w).Encode(response)
}
func main() {
http.HandleFunc("/decrypt", decryptHandler)
fmt.Println("服务器启动在 :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
3. 测试示例
创建测试客户端:
// test_client.go
package main
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"
)
func testEncryption() {
// 模拟Angular端的加密
publicKeyPEM := `-----BEGIN PUBLIC KEY-----
...(您的公钥内容)...
-----END PUBLIC KEY-----`
block, _ := pem.Decode([]byte(publicKeyPEM))
if block == nil {
panic("无效的公钥")
}
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
publicKey := pubInterface.(*rsa.PublicKey)
// 要加密的数据
data := `{"username":"test","password":"test123"}`
// 使用RSA-OAEP加密
encrypted, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
publicKey,
[]byte(data),
nil,
)
if err != nil {
panic(err)
}
// Base64编码
encryptedBase64 := base64.StdEncoding.EncodeToString(encrypted)
// 发送到API
requestBody, _ := json.Marshal(map[string]string{
"encryptedData": encryptedBase64,
})
resp, err := http.Post("http://localhost:8080/decrypt",
"application/json",
bytes.NewBuffer(requestBody))
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("API响应:", string(body))
}
func main() {
testEncryption()
}
4. 注意事项
- 密钥管理:私钥必须安全存储,不应暴露给前端
- 加密限制:RSA加密有长度限制(对于2048位密钥,最多加密245字节)
- 性能考虑:对于大量数据,建议使用对称加密(如AES),用RSA加密对称密钥
- 错误处理:在实际应用中需要更完善的错误处理和日志记录
- 安全性:确保使用TLS/HTTPS传输加密数据
这个实现方案使用了RSA-OAEP with SHA-256,这是当前推荐的RSA加密方式,提供了良好的安全性和兼容性。

