【Go实战】:使用AES和RSA加密算法保护关键信息

前言

作为一名开发者,我们在构建安全可靠的应用时,确保接口请求中的关键信息不被泄露是非常重要的。加密与解密技术是实现这一目标的关键手段。本文将详细介绍如何在Golang中使用AES(高级加密标准)和RSA加密算法来实现数据的加密与解密,帮助你在接口请求中隐藏关键信息,提升系统的安全性。通过本文,你将了解这两种算法的基本原理、适用场景及注意事项,并通过具体的代码示例掌握其实现方法。无论你是初学者还是有一定经验的开发者,本文都能为你提供有价值的参考。

1. AES加密算法

AES是一种对称加密算法,意味着加密和解密过程使用相同的密钥。它支持128、192和256位三种密钥长度,其中256位密钥提供了最高的安全性。AES以其高效性和强大的安全性,成为保护敏感数据的首选。

1.1 代码示例(Go语言):

package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"fmt"
	"log"
)

// PKCS7Padding 填充
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// PKCS7UnPadding 去除填充
func PKCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

// AESEncrypt AES 加密
func AESEncrypt(plaintext, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 填充
	plaintext = PKCS7Padding(plaintext, block.BlockSize())

	// 创建 CBC 模式的加密器
	ciphertext := make([]byte, len(plaintext))
	mode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	mode.CryptBlocks(ciphertext, plaintext)

	return ciphertext, nil
}

// AESDecrypt AES 解密
func AESDecrypt(ciphertext, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 创建 CBC 模式的解密器
	plaintext := make([]byte, len(ciphertext))
	mode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
	mode.CryptBlocks(plaintext, ciphertext)

	// 去除填充
	plaintext = PKCS7UnPadding(plaintext)

	return plaintext, nil
}

func main() {
	key := []byte("abcdefghijklmnop") // 密钥长度必须是 16, 24, 或 32 字节
	plaintext := []byte("Hello, AES!")

	// 加密
	encrypted, err := AESEncrypt(plaintext, key)
	if err != nil {
		log.Fatalf("加密失败: %v", err)
	}
	fmt.Printf("加密后: %s\n", base64.StdEncoding.EncodeToString(encrypted))

	// 解密
	decrypted, err := AESDecrypt(encrypted, key)
	if err != nil {
		log.Fatalf("解密失败: %v", err)
	}
	fmt.Printf("解密后: %s\n", decrypted)
}

1.2 运行结果:

加密后: KRw1wPLUXqEjxoSsywa8IA==
解密后: Hello, AES!

2. RSA加密算法

RSA是一种非对称加密算法,使用公钥和私钥对进行加密和解密。公钥用于加密数据,私钥用于解密数据。RSA以其强大的安全性、密钥交换能力和数字签名功能,成为信息安全领域的重要组成部分。

2.1 代码示例(Go语言):

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"log"
)

// 生成 RSA 密钥对
func generateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return nil, nil, err
	}
	publicKey := &privateKey.PublicKey
	return privateKey, publicKey, nil
}

// 使用公钥加密数据
func encryptWithPublicKey(data []byte, publicKey *rsa.PublicKey) ([]byte, error) {
	return rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, data, nil)
}

// 使用私钥解密数据
func decryptWithPrivateKey(ciphertext []byte, privateKey *rsa.PrivateKey) ([]byte, error) {
	return rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, nil)
}

// 将私钥转换为 PEM 格式
func privateKEYToPEM(privateKey *rsa.PrivateKey) ([]byte, error) {
	privateDER := x509.MarshalPKCS1PrivateKey(privateKey)
	privateBlock := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: privateDER,
	}
	return pem.EncodeToMemory(privateBlock), nil
}

// 将公钥转换为 PEM 格式
func publicKEYToPEM(publicKey *rsa.PublicKey) ([]byte, error) {
	publicDER, err := x509.MarshalPKIXPublicKey(publicKey)
	if err != nil {
		return nil, err
	}
	publicBlock := &pem.Block{
		Type:  "RSA PUBLIC KEY",
		Bytes: publicDER,
	}
	return pem.EncodeToMemory(publicBlock), nil
}

func main() {
	// 生成 RSA 密钥对
	privateKey, publicKey, err := generateRSAKeyPair(2048)
	if err != nil {
		log.Fatalf("生成 RSA 密钥对失败: %v", err)
	}

	// 将私钥和公钥转换为 PEM 格式
	privateKeyPEM, err := privateKEYToPEM(privateKey)
	if err != nil {
		log.Fatalf("将私钥转换为 PEM 格式失败: %v", err)
	}
	publicKeyPEM, err := publicKEYToPEM(publicKey)
	if err != nil {
		log.Fatalf("将公钥转换为 PEM 格式失败: %v", err)
	}

	fmt.Println("私钥 (PEM):")
	fmt.Println(string(privateKeyPEM))
	fmt.Println("公钥 (PEM):")
	fmt.Println(string(publicKeyPEM))

	// 要加密的数据
	data := []byte("Hello, RSA!")

	// 使用公钥加密数据
	encryptedData, err := encryptWithPublicKey(data, publicKey)
	if err != nil {
		log.Fatalf("加密数据失败: %v", err)
	}
	fmt.Println("\n加密后的数据:")
	fmt.Printf("%x\n", encryptedData)

	// 使用私钥解密数据
	decryptedData, err := decryptWithPrivateKey(encryptedData, privateKey)
	if err != nil {
		log.Fatalf("解密数据失败: %v", err)
	}
	fmt.Println("\n解密后的数据:")
	fmt.Println(string(decryptedData))
}

2.2 运行结果:

私钥 (PEM):
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtU6Bgi8Rskjt36socqPDPdohqWYmnXGXZfApY8R6U93C4475
MetH1JGI1MsCCcBNO/3fUOe6PGfMmZziMNxWcxYErM3XOPtfBA4QWukUO+t/JSB9
d4Z7YS8hQVGF9zs9ztR4h38dmb2CEtl6XV6+YWO/WJSfesqA0V1BuPTKuYGFC8ps
7QAGd+UnJ+zfkgSQl06u7fTLiRZP84jQTSRUIPscRq1wbbOFDcwNoPXWCW8ybdz0
5+qoh1clD1Yp/+Lz/PI1WT4y846ZJ3YGAsfWC7LfPEIZrRBAnf58Hmzm7bT4ube2
4teWPWlQtJrVY977sPvFNxT+v1IPX3LqYc+11wIDAQABAoIBAFc14A3i3jxH4EQK
bHZYV33VAwQc4s4w6YZbM02OINlefnQ/PZbJec/CAXN6Awz1tzD4OQcNsAOGWmA5
moOuONc67BzDFpeOMnIc4bkZDGaWLJ6LNk7cHVTt+q0Urb/yexSWFzP17SMaiQrQ
GY/4FtN5y3ysYNoLtlL+7LIu7aS03JKr0kFecdGE2fd459coBCZOpKTAN+UIlFjo
n/s+Z84GaOu35ApeQIeO+/qsBRfJmSw6OgdjgNkU7dveV712w1dgt0cUxeF+OBct
QNfhmmQY7OERt6nLrXg8wRoPjjt8Pe9h6H9RmeENo7EbueYXKiaZq5vgbGae0Fj6
Ay/xCgECgYEAx7EEohUzIQObsFLWs+Gx9jGPmfP5YCoB/kiQDuFHhRUt5MWzAxnF
T4f0abTV3fKPvqkwjA77mTJ61eLmihnBHXk0EJKMncLzkFXi+0C5L6CLGqCnshdJ
ToEcdcXPg9exDaFgMgOgFZRki49Y+YIpEEhJWa4I2/fTme89fYg0HcECgYEA6G5b
VmGOTswqL+LvAGNfBG+p4QIg3gbiN/56Y4N1W4hKrOnLfaYHhb3Y6TIPqhlJiNXD
ttOPyOc3JA/ZZJ5jk88rEhmXIjali8/f1QWJlJqea9Co2owJm3LIass1y7jdrJFo
cZl1V0FNwPcix9MmRuZX52nlUPIV9/1tKj5eaZcCgYA0XaVbY7fOtoWDTZXkAhGL
ACAqPSJuJ1XyetDcNhNtQMqSLY3uCDoHyx07AyL6Wvt7Ah8q+1rbJ7OylxfhqzNL
KVeP6P5a+J6qgPtO7AAkDzOrPen798NPhOgTslXiuxNBAcqaEv1N62YaevLYK1vd
Wzdw/wRvuqOQwH4dhzQzgQKBgBBilzXDstCDPAYcLVUNrEkXxhYCnGaKfbAM1Hvn
bIKDXSBLavj0l1sqQvxNdyU6myB2UVG2IFC9W/nC1ERvlf15gUPJYgobaBgvE0xl
E4nSTJC1KPIfJR48PTyqDqTJ53ae2YoIk2kPRXfw9Ba6H9ynqFK7+Fp4dmwBBY0Q
0H8JAoGBALU3itfD5YsCBtQupQ94uNmCIymMjkvlSeoC7V+z3lvXGiQRISdq7A77
YVZVHM1b36bnK+7R9A/Ev1gBc3AvB4q9pXAHmCxlwtmOUjZvXuTK6Rem/gurJmkm
MIMzsl0ElCCySsMxXslyGAyZTEgpYHueakrw+aTYayxoDtYm7Yz3
-----END RSA PRIVATE KEY-----

公钥 (PEM):
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtU6Bgi8Rskjt36socqPD
PdohqWYmnXGXZfApY8R6U93C4475MetH1JGI1MsCCcBNO/3fUOe6PGfMmZziMNxW
cxYErM3XOPtfBA4QWukUO+t/JSB9d4Z7YS8hQVGF9zs9ztR4h38dmb2CEtl6XV6+
YWO/WJSfesqA0V1BuPTKuYGFC8ps7QAGd+UnJ+zfkgSQl06u7fTLiRZP84jQTSRU
IPscRq1wbbOFDcwNoPXWCW8ybdz05+qoh1clD1Yp/+Lz/PI1WT4y846ZJ3YGAsfW
C7LfPEIZrRBAnf58Hmzm7bT4ube24teWPWlQtJrVY977sPvFNxT+v1IPX3LqYc+1
1wIDAQAB
-----END RSA PUBLIC KEY-----


加密后的数据:
472886c86bf863a2dedf90dbed919c18fb0c43d8df05a696bcd9a6503372cda6adaac80dc0e1d9538f38b1b59ead2e15a0ffb08df840cda6b50c95d48d73d144a0283f20c649651f5a216ad91cfa4df63c294b9fedcd1b60ab020862ef420a83004c436400bffeece8320b678009236dea02bf8e45e700dbc903239e60242fffddee1b55f628a0b0bcdb0e87939d4117cd1eb4691bb0ba9e6b2e0deba31f4d6db023b8e75925c078de021ce13397e5888e887c54ebb839a4606a125869c6da6b04232c83ee625c8aa545005c1cd617c75fa9706694b0b058593bf5f565bb8cb4996691886d7941316b761935876700323aa8d8aa3d123fe0f9a4cc0296d3870b

解密后的数据:
Hello, RSA!

3. AES与RSA对比

为了更直观地比较AES和RSA两种加密算法,以下是一个详细的对比表格,涵盖了基本属性、密钥管理、加密效率、安全性、适用场景、密钥长度和加密模式等方面。

特性/算法AES  RSA
基本属性对称加密算法非对称加密算法
密钥管理加密和解密使用相同密钥公钥加密,私钥解密
加密效率高,适合处理大量数据较低,适合加密小量数据或对称密钥
安全性支持多种密钥长度,安全性高基于大数分解难题,安全性高
适用场景文件加密、数据库加密、网络通信密钥交换、数字签名、电子邮件加密
密钥长度128、192、256位至少2048位
加密模式ECB、CBC、CFB、OFB、GCM等通常使用PKCS#1标准,支持OAEP等填充模式

注意事项

密钥的安全管理:无论是AES还是RSA,密钥的安全管理都是至关重要的。确保密钥的存储和传输过程是安全的,避免硬编码在源代码中。
填充方式:在使用对称加密算法时,选择合适的填充方式(如PKCS7)可以增强安全性。
哈希函数:在使用非对称加密算法时,选择合适的哈希函数(如SHA-256)可以增强安全性。
密钥长度:对于RSA,建议使用至少2048位的密钥长度,以确保足够的安全性。

总结

作为一名开发者,确保接口请求中的关键信息不被泄露是构建安全可靠应用的重要一环。通过使用AES和RSA加密算法,你可以在接口请求中有效地隐藏关键信息,提升系统的安全性。AES以其高效性和安全性,特别适合处理大量数据,如文件加密、数据库加密和网络通信。而RSA则以其非对称加密的特点,在密钥交换、数字签名和安全通信等场景中展现出独特的优势。通过本文提供的代码示例和详细的对比表格,希望你能更好地掌握这两种加密算法,从而在实际项目中应用得更加得心应手。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/919343.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VB.Net笔记-更新ing

1.1 设置默认VS的开发环境为VB.NET(2024/11/18) 1.2 新建一个“Hello,world”的窗体(2024/11/18) 1.3 计算圆面积的小程序(2024/11/18) 显示/隐式 声明 (2024/11/18&#xff0…

每日一练:【优先算法】双指针之移动零(easy)

双指针概念介绍 常见的双指针有两种形式,一种是对撞指针,一种是左右指针。 对撞指针:一般用于顺序结构中,也称左右指针。 • 对撞指针从两端向中间移动。一个指针从最左端开始,另一个从最右端开始,然后逐渐…

树状数组 Color the ball hdu 1556 线段树 洛谷p3372

目录 前言 树状数组 lowbit函数 直观表述 代码 运行结果 树状数组构建代码 树状数组的应用 单点修改和(单点)区间查询 结合差分数组区间修改 ,单点查询 差分数组 Color the ball hdu 1556 问题描述 问题分析 代码 线段树 洛谷p3372 问题描述 问题…

学习笔记022——Ubuntu 安装 MySQL8.0版本踩坑记录

目录 1、查看可安装 MySQL 版本 2、Ubuntu安装 MySQL8.0 3、MySQL8.0 区分大小写问题 4、MySQL8.0 设置sql_mode 5、MySQL8.0 改端口33060(个人遇到问题) 1、查看可安装 MySQL 版本 ## 列出可用的MySQL版本(列出所有可用的MySQL版本以…

【数据结构】树——链式存储二叉树的基础

写在前面 书接上文:【数据结构】树——顺序存储二叉树 本篇笔记主要讲解链式存储二叉树的主要思想、如何访问每个结点、结点之间的关联、如何递归查找每个结点,为后续更高级的树形结构打下基础。不了解树的小伙伴可以查看上文 文章目录 写在前面 一、链…

qt之QFTP对文件夹(含嵌套文件夹和文件)、文件删除下载功能

一、前言 主要功能如下: 1.实现文件夹的下载和删除,网上很多资料都是单独对某个路径的文件操作的,并不能对文件夹操作 2.实现目标机中含中文名称自动转码,有些系统编码方式不同,下载出来的文件会乱码 3.实现ftp功能…

集群聊天服务器(7)数据模块

目录 Mysql数据库代码封装头文件与源文件 Mysql数据库代码封装 业务层代码不要直接写数据库,因为业务层和数据层的代码逻辑也想完全区分开。万一不想存储mysql,想存redis的话,就要改动大量业务代码。解耦合就是改起来很方便。 首先需要安装m…

手机远程控制电脑,让办公更快捷

在数字化办公的浪潮下,远程控制软件已成为连接工作与生活的桥梁。它使得用户能够通过一台设备(主控端)来操作另一台设备(被控端),无论它们是否位于同一局域网内。这种软件广泛应用于远程办公、手机远程控制…

面向FWA市场!移远通信高性能5G-A模组RG650V-NA通过北美两大重要运营商认证

近日,全球领先的物联网整体解决方案供应商移远通信宣布,其旗下符合3GPP R17标准的新一代5G-A模组RG650V-NA成功通过了北美两家重要运营商认证。凭借高速度、大容量、低延迟、高可靠等优势,该模组可满足CPE、家庭/企业网关、移动热点、高清视频…

72项!湖北省2024年度第二批省级科技计划项目拟立项项目公示!

本期精选 SCI&EI ●IEEE 1区TOP 计算机类(含CCF); ●EI快刊:最快1周录用! 知网(CNKI)、谷歌学术期刊 ●7天录用-检索(100%录用),1周上线; 免费稿件评估 免费匹配…

LeetCode 热题 100 回顾

目录 一、哈希部分 1.两数之和 (简单) 2.字母异位词分组 (中等) 3.最长连续序列 (中等) 二、双指针部分 4.移动零 (简单) 5.盛最多水的容器 (中等) 6…

Chrome 浏览器 131 版本开发者工具(DevTools)更新内容

Chrome 浏览器 131 版本开发者工具(DevTools)更新内容 一、使用 Gemini 调试 CSS Chrome DevTools 现在推出了一个新的实验性 AI 辅助面板,可以与 Gemini 聊天并获得帮助来调试 CSS。 在 Elements 面板中,右键点击一个元素并选…

网络编程-002-UDP通信

1.UDP通信的简单介绍 1.1不需要通信握手,无需维持连接,网络带宽需求较小,而实时性要求高 1.2 包大小有限制,不发大于路径MTU的数据包 1.3容易丢包 1.4 可以实现一对多,多对多 2.客户端与服务端=发送端与接收端 代码框架 收数据方一般都是客户端/接收端 3.头文件 #i…

websocket身份验证

websocket身份验证 前言 上一集我们就完成了websocket初始化的任务,那么我们完成这个内容之后就应该完成一个任务,当客户端与服务端连接成功之后,客户端应该主动发起一个身份认证的消息。 身份认证proto 我们看一眼proto文件的内容。 我…

初识C++(1)

C是在C语言的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库以及编程范式等。 在C语言中&#xff0c;变量、函数和类的名称存在于全局作用域中&#xff0c;因此可能会发生许多冲突。比如&#xff1a; #include<stdio.h> #include<…

Axure9生成的阅览页面如何自动展开左侧页面导航?

问题 Axure9生成的阅览页面&#xff0c;默认情况是自动折叠的&#xff0c;如何自动展开左侧页面导航&#xff1f; 解决 Axure工具&#xff1a;发布 > 预览选项 > 播放器 > 打开页面列表

LeetCode:700. 二叉搜索树中的搜索

目录 题目描述: 代码: 题目描述: 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 示例 1: 输入&#xff1a;root [4,2,7,1,3…

架构图解析:如何构建高效的微服务系统

在当今的数字化浪潮中&#xff0c;构建高效、灵活且可扩展的系统已成为企业的重要目标。微服务架构作为一种先进的软件设计模式&#xff0c;通过将复杂的应用程序分解为一系列小型、独立的服务&#xff0c;显著提升了系统的灵活性、可扩展性和维护性。本文将通过解析微服务系统…

【Android、IOS、Flutter、鸿蒙、ReactNative 】实现 MVP 架构

Android Studio 版本 Android Java MVP 模式 参考 模型层 model public class User {private String email;private String password;public User(String email, String password) {this.email = email;this.password = password;}public String getEmail() {return email;}…

【海思Hi3519DV500】双目网络相机套板硬件规划方案

Hi3519DV500双目网络相机套板是针对该芯片设计的一款 IP 编码板 PCBA&#xff0c;硬件接口支持双目sensor 接入&#xff0c;SDIO3.0 接口、USB2.0、USB3.0、UART 接口以及丰富的 IO 扩展应用&#xff0c;可根据各种使用场景设计相应扩展板&#xff0c;丰富外围接口&#xff0c;…