为什么要使用加密传输呢?
避免网络传输过程中敏感信息泄露,避免泄露平台用户信息。
go和java加密解密写法
go
package test
import (
randRsa "crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"sync"
"testing"
)
// 生成 RSA 密钥对
func generateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
privateKey, err := rsa.GenerateKey(randRsa.Reader, bits)
if err != nil {
return nil, nil, err
}
return privateKey, &privateKey.PublicKey, nil
}
// 使用公钥加密
func encryptWithPublicKey(plainText string, publicKey *rsa.PublicKey) (string, error) {
cipherText, err := rsa.EncryptPKCS1v15(randRsa.Reader, publicKey, []byte(plainText))
if err != nil {
return "", err
}
// 返回 Base64 编码后的加密文本
return base64.StdEncoding.EncodeToString(cipherText), nil
}
// 使用私钥解密
func decryptWithPrivateKey(cipherText string, privateKey *rsa.PrivateKey) (string, error) {
// 先解码 Base64
decodedCipherText, err := base64.StdEncoding.DecodeString(cipherText)
if err != nil {
return "", err
}
// 使用私钥解密
plainText, err := rsa.DecryptPKCS1v15(randRsa.Reader, privateKey, decodedCipherText)
if err != nil {
return "", err
}
return string(plainText), nil
}
func exportPrivateKeyToPEM(privateKey *rsa.PrivateKey) string {
privKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: privKeyBytes})
return string(privKeyPEM)
}
func exportPublicKeyToPEM(publicKey *rsa.PublicKey) string {
pubKeyBytes, _ := x509.MarshalPKIXPublicKey(publicKey)
pubKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: pubKeyBytes})
return string(pubKeyPEM)
}
func loadPrivateKeyFromPEM(pemStr string) (*rsa.PrivateKey, error) {
block, _ := pem.Decode([]byte(pemStr))
return x509.ParsePKCS1PrivateKey(block.Bytes)
}
func loadPublicKeyFromPEM(pemStr string) (*rsa.PublicKey, error) {
block, _ := pem.Decode([]byte(pemStr))
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
return key.(*rsa.PublicKey), nil
}
func TestRSA(t *testing.T) {
// 生成 2048 位 RSA 密钥对
privateKey, publicKey, err := generateRSAKeyPair(2048)
if err != nil {
fmt.Println("Error generating RSA key pair:", err)
return
}
// 输出公钥私钥
fmt.Println("Private Key:", exportPrivateKeyToPEM(privateKey))
fmt.Println("Public Key:", exportPublicKeyToPEM(publicKey))
originalText := "Hello, RSA encryption and decryption in Go!"
fmt.Println("Original Text:", originalText)
// 加密
encryptedText, err := encryptWithPublicKey(originalText, publicKey)
if err != nil {
fmt.Println("Error encrypting:", err)
return
}
fmt.Println("Encrypted Text (Base64):", encryptedText)
// 解密
decryptedText, err := decryptWithPrivateKey(encryptedText, privateKey)
if err != nil {
fmt.Println("Error decrypting:", err)
return
}
fmt.Println("Decrypted Text:", decryptedText)
}
/**
* 测试并发加密解密性能
*
* 运行结果:
* goos: windows
* goarch: amd64
* pkg: wann-redmoon/test
* cpu: 12th Gen Intel(R) Core(TM) i5-12400F
* BenchmarkRSACrypto
* BenchmarkRSACrypto/ConcurrentEncryptionDecryption
* BenchmarkRSACrypto/ConcurrentEncryptionDecryption-12 1000000000 0.04600 ns/op
PASS
*/
func BenchmarkRSACrypto(b *testing.B) {
// 生成 2048 位 RSA 密钥对
privateKey, publicKey, err := generateRSAKeyPair(2048)
if err != nil {
b.Fatalf("Error generating RSA key pair: %v", err)
}
originalText := "Hello, RSA encryption and decryption in Go!"
// 测量并发加密解密性能
b.Run("ConcurrentEncryptionDecryption", func(b *testing.B) {
var wg sync.WaitGroup
// 运行多个并发任务来测试加密解密的性能
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// 加密
encryptedText, err := encryptWithPublicKey(originalText, publicKey)
if err != nil {
b.Errorf("Error encrypting: %v", err)
return
}
// 解密
_, err = decryptWithPrivateKey(encryptedText, privateKey)
if err != nil {
b.Errorf("Error decrypting: %v", err)
return
}
}()
}
// 等待所有并发任务完成
wg.Wait()
})
}
/**
性能测试 整体加密解密,只加密解密部分字段
*/
type MyStruct struct {
Name string
Age int
Password string
Email string
Address string
Phone string
Occupation string
Country string
ZipCode string
Salary float64
JoinedAt string
}
// 结构体转 JSON 后加密
func encryptStructToJSON(s MyStruct, publicKey *rsa.PublicKey) (string, error) {
jsonData, err := json.Marshal(s)
if err != nil {
return "", err
}
return encryptWithPublicKey(string(jsonData), publicKey)
}
// 分别加密结构体的字段
func encryptFields(s MyStruct, publicKey *rsa.PublicKey) (MyStruct, error) {
var encrypted MyStruct
var err error
encrypted.Name, err = encryptWithPublicKey(s.Name, publicKey)
if err != nil {
return encrypted, err
}
encrypted.Age = s.Age // 不加密
encrypted.Password, err = encryptWithPublicKey(s.Password, publicKey)
if err != nil {
return encrypted, err
}
encrypted.Email, err = encryptWithPublicKey(s.Email, publicKey)
if err != nil {
return encrypted, err
}
encrypted.Address, err = encryptWithPublicKey(s.Address, publicKey)
if err != nil {
return encrypted, err
}
encrypted.Phone, err = encryptWithPublicKey(s.Phone, publicKey)
if err != nil {
return encrypted, err
}
encrypted.Occupation, err = encryptWithPublicKey(s.Occupation, publicKey)
if err != nil {
return encrypted, err
}
encrypted.Country, err = encryptWithPublicKey(s.Country, publicKey)
if err != nil {
return encrypted, err
}
encrypted.ZipCode, err = encryptWithPublicKey(s.ZipCode, publicKey)
if err != nil {
return encrypted, err
}
encrypted.Salary = s.Salary // 不加密
encrypted.JoinedAt, err = encryptWithPublicKey(s.JoinedAt, publicKey)
if err != nil {
return encrypted, err
}
return encrypted, nil
}
// 基准测试:结构体转 JSON 后加密
func BenchmarkEncryptStructToJSON(b *testing.B) {
_, publicKey, _ := generateRSAKeyPair(2048)
originalStruct := MyStruct{
Name: "Alice", Age: 30, Password: "password123", Email: "alice@example.com",
Address: "123 Main St", Phone: "123-456-7890", Occupation: "Engineer", Country: "USA",
ZipCode: "12345", Salary: 75000.5, JoinedAt: "2023-01-01",
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, _ = encryptStructToJSON(originalStruct, publicKey)
}
}
/**
goos: windows
goarch: amd64
pkg: wann-redmoon/test
cpu: 12th Gen Intel(R) Core(TM) i5-12400F
BenchmarkEncryptStructToJSON
BenchmarkEncryptStructToJSON-12 24712 47684 ns/op 15586 B/op 106 allocs/op
PASS
*/
// 基准测试:分别加密结构体字段
func BenchmarkEncryptFields(b *testing.B) {
_, publicKey, _ := generateRSAKeyPair(2048)
originalStruct := MyStruct{
Name: "Alice", Age: 30, Password: "password123", Email: "alice@example.com",
Address: "123 Main St", Phone: "123-456-7890", Occupation: "Engineer", Country: "USA",
ZipCode: "12345", Salary: 75000.5, JoinedAt: "2023-01-01",
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, _ = encryptFields(originalStruct, publicKey)
}
}
/**
goos: windows
goarch: amd64
pkg: wann-redmoon/test
cpu: 12th Gen Intel(R) Core(TM) i5-12400F
BenchmarkEncryptFields
BenchmarkEncryptFields-12 2866 442560 ns/op 134717 B/op 931 allocs/op
PASS
*/
性能测试解释:
goos: windows:表示测试是在 Windows 操作系统上进行的。
goarch: amd64:表示测试是在 64 位架构的计算机上进行的。
pkg: wann-redmoon/test:表示基准测试运行在 wann-redmoon/test 包下。
cpu: 12th Gen Intel(R) Core(TM) i5-12400F:表示测试运行的 CPU 是第 12 代的 Intel Core i5-12400F 处理器。
基准测试输出:
BenchmarkRSACrypto/ConcurrentEncryptionDecryption:这个是你测试的基准测试用例的名称,表示测试的是并发加密和解密的性能。
BenchmarkRSACrypto/ConcurrentEncryptionDecryption-12:这个结果表示测试在 12 个并发的情况下运行。-12 是并发的数量,表示有 12 个 goroutine 在同时进行加密解密操作。
1000000000:表示基准测试的执行次数(每个 goroutine 执行的操作次数)。这个数值非常大(10 亿次),说明每个任务在短时间内就执行了大量的操作。
0.04278 ns/op:表示每个加密解密操作的平均耗时为 0.04278 纳秒。这个时间极其短,意味着你的加密解密操作非常快速。
BenchmarkEncryptStructToJSON 和 BenchmarkEncryptFields 的性能
- BenchmarkEncryptStructToJSON:
BenchmarkEncryptStructToJSON-12 24712 47684 ns/op 15586 B/op 106 allocs/op
运行时间:每次操作平均 47684 纳秒(约 47 毫秒)。
内存分配:每次操作会分配约 15586 字节的内存。
内存分配次数:每次操作进行 106 次内存分配。 - BenchmarkEncryptFields:
BenchmarkEncryptFields-12 2866 442560 ns/op 134717 B/op 931 allocs/op
运行时间:每次操作平均 442560 纳秒(约 442 毫秒)。
内存分配:每次操作会分配约 134717 字节的内存。
内存分配次数:每次操作进行 931 次内存分配。
分析:
运行时间:BenchmarkEncryptStructToJSON 显著比 BenchmarkEncryptFields 快,说明一次性对整个结构体进行 JSON 编码后加密,处理速度比逐个字段加密要快得多。
内存分配:BenchmarkEncryptFields 需要更多的内存分配(134717 字节),而 BenchmarkEncryptStructToJSON 的内存分配较少(15586 字节)。这是因为在 BenchmarkEncryptFields 中,每个字段都需要单独加密,因此会进行更多的内存分配。
内存分配次数:BenchmarkEncryptFields 的内存分配次数远高于 BenchmarkEncryptStructToJSON(931 次 vs. 106 次),这是由于每个字段都需要独立的加密处理并分配内存。
结论:
性能更好的方式:结构体转 JSON 后加密(BenchmarkEncryptStructToJSON)更快,且内存分配和处理更高效。
性能较差的方式:分别加密字段(BenchmarkEncryptFields)在处理时间、内存分配和分配次数上均显得更加低效。
java
package com.snpackage.web.controller;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Base64;
public class TestRSAExample {
// 生成RSA公钥私钥对
public static KeyPair generateRSAKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 设置密钥的大小
return keyPairGenerator.generateKeyPair();
}
// 使用公钥进行加密
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedBytes); // 返回加密后的字符串
}
// 使用私钥进行解密
public static String decrypt(String encryptedData, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
return new String(decryptedBytes); // 返回解密后的字符串
}
public static void main(String[] args) {
try {
// 生成RSA公钥私钥对
KeyPair keyPair = generateRSAKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 原始数据
String originalData = "Hello, RSA encryption and decryption!";
System.out.println("Original Data: " + originalData);
// 使用公钥加密
String encryptedData = encrypt(originalData, publicKey);
System.out.println("Encrypted Data: " + encryptedData);
// 使用私钥解密
String decryptedData = decrypt(encryptedData, privateKey);
System.out.println("Decrypted Data: " + decryptedData);
} catch (Exception e) {
e.printStackTrace();
}
}
}
评论区