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

news2024/11/20 16:36:47

前言

作为一名开发者,我们在构建安全可靠的应用时,确保接口请求中的关键信息不被泄露是非常重要的。加密与解密技术是实现这一目标的关键手段。本文将详细介绍如何在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则以其非对称加密的特点,在密钥交换、数字签名和安全通信等场景中展现出独特的优势。通过本文提供的代码示例和详细的对比表格,希望你能更好地掌握这两种加密算法,从而在实际项目中应用得更加得心应手。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何管理服务中的 “昂贵” 资源

如果接触过实际大型业务系统,就能体会到许多业务的正常运行都依赖于各种昂贵的第三方接口,调用一次都是要花元子的,例如 大语言模型nlp 服务:信息提取、分类等cv 服务:定位、信息提取、分类等 然而经常可能由于各种无…

蓝桥杯每日真题 - 第16天

题目:(卡牌) 题目描述(13届 C&C B组C题) 解题思路: 题目分析: 有 n 种卡牌,每种卡牌的现有数量为 a[i],所需的最大数量为 b[i],还有 m 张空白卡牌。 每…

CSS遮罩:mask

CSS属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。 // 一般用位图图片做遮罩 mask: url(~/assets/images/mask.png); mask-size: 100% 100%;// 使用 SVG 图形中的形状来做遮罩 mask: url(~/assets/images/mask.svg#star);…

Zabbix:使用CentOS 9,基于LNMP平台,源码部署Zabbix 7。

ZBX:源码部署Zabbix 7 一、Zabbix概述1. 什么是zabbix2. 为什么学习zabbix3. 逻辑架构3. 实验环境4. 软件下载: 二、安装前的系统准备工作1. 配置主机名2. 关闭防火墙3. 关闭selinux4. 配置yum源5. 配置时钟同步6. 优化系统限制7. 安装JDK 三、部署LNMP环…

5G与4G互通的桥梁:N26接口

5G的商用部署进程将是一个基于4G系统进行的长期的替换、升级、迭代的过程,4G系统是在过渡到5G全覆盖过程中,作为保障用户业务连续性体验这一目的的最好补充。 因此4G/5G融合组网,以及互操作技术将是各大运营商在网络演进中需要重点考虑的问题…

【计算机网络实验】之静态路由配置

【计算机网络实验】之静态路由配置 实验题目实验目的实验任务实验设备实验环境实验步骤路由器配置设置静态路由测试路由器之间的连通性配置主机PC的IP测试 实验题目 静态路由协议的配置 实验目的 熟悉路由器工作原理和机制;巩固静态路由理论;设计简单…

【专题】2024AIGC创新应用洞察报告汇总PDF洞察(附原数据表)

原文链接:https://tecdat.cn/?p38310 在科技日新月异的今天,人工智能领域正以前所未有的速度发展,AIGC(人工智能生成内容)成为其中最耀眼的明珠。从其应用场景的不断拓展,到对各行业的深刻变革&#xff0…

微知-动态链接库导出的三种方式?(LD_LIBRARY_PATH, /etc/ld.so.conf, -Wl,-rpath)

背景 经常需要导出动态库,最场景的方式是指定LD_LIBRARY_PATH。本文介绍3中 LD_LIBRARY_PATH 这种方式临时生效 export LD_LIBRARY_PATH/path/to/mylibdir:$LD_LIBRARY_PATH使用ldconfig和/etc/ld.so.conf 在配置文件 /etc/ld.so.conf 中指定动态库搜索路径。每…

Jenkins更换主题颜色+登录页面LOGO图片

默认主题和logo图片展示 默认主题黑色和白色。 默认LOGO图片 安装插件 Login ThemeMaterial Theme 系统管理–>插件管理–>Available plugins 搜不到Login Theme是因为我提前装好了 没有外网的可以参考这篇离线安装插件 验证插件并修改主题颜色 系统管理–>A…

HTB:Arctic[WriteUP]

目录 连接至HTB服务器并启动靶机 信息搜集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机开放端口进行脚本、服务扫描 使用curl访问靶机8500端口 漏洞利用 使用浏览器访问URL:http://10.10.10.11:8500 使用searchsploit搜索该WebAPP 启动Metasplo…

利用正则表达式批量修改文件名

首先, 我们需要稍微学习一下正则表达式的使用方式,可以看这里:Notepad正则表达式使用方法_notepad正则匹配-CSDN博客 经过初步学习之后,比较重要的内容我做如下转载: 元字符是正则表达式的基本构成单位,它们…

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

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

核心社群营销和覆盖区域选型

目录 一、背景介绍 (一)核心流程 (二)用户进群 (三)内容匹配 (四)数据追踪 (五)风险管控 二、业界调研 三、聚焦群覆盖区域 (一&#xf…

计算机毕业设计 | SpringBoot+vue汽车资讯网站 汽车购买咨询管理系统(附源码+论文)

1,绪论 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理汽车资讯网站的相关信息成为必然…

Java成员变量 成员方法的访问特点 结构体(上)

1. (1) public class dog {public void eat(){System.out.println("在吃狗粮");}public void drink(){System.out.println("在喝水");}public void lookhome(){System.out.println("在看家");} } (2&#x…

ctfshow-web入门-SSRF(web351-web360)

目录 1、web351 2、web352 3、web353 4、web354 5、web355 6、web356 7、web357 8、web358 9、web359 10、web360 1、web351 看到 curl_exec 函数,很典型的 SSRF 尝试使用 file 协议读文件: urlfile:///etc/passwd 成功读取到 /etc/passwd 同…

【Java】ArrayList与LinkedList详解!!!

目录 一🌞、List 1🍅.什么是List? 2🍅.List中的常用方法 二🌞、ArrayList 1🍍.什么是ArrayList? 2🍍.ArrayList的实例化 3🍍.ArrayList的使用 4🍍.ArrayList的遍…

蓝桥杯每日真题 - 第18天

题目:(出差) 题目描述(13届 C&C B组E题) 解题思路: 问题分析 问题实质是一个带权图的最短路径问题,但路径的权重包含两个部分: 从当前城市到下一个城市的路程时间。 当前城市的…

D73【 python 接口自动化学习】- python 基础之正则表达式

day73 正则表达式-元字符匹配 学习日期:20241119 学习目标:正则表达式--133 正则表达式-元字符匹配 学习笔记: 元字符匹配 数量匹配 实践操作 总结 字符串的r标记表示,字符串内转移字符无效,作为普通字符使用正则…