当前位置:首页 > 科技  > 软件

在 Go 项目中封装 AES 加解密客户端接口

来源: 责编: 时间:2024-01-02 17:28:32 297观看
导读1.摘要在一个中型以上的项目中, 我们一般会在项目工程中开辟一个pkg文件夹用来存放一些基础工具接口,比如:数据库、中间件、加解密算法、基础协议等等。在这篇文章中, 我主要分享一下在基于Go语言的项目中, 加解密算

1.摘要

在一个中型以上的项目中, 我们一般会在项目工程中开辟一个pkg文件夹用来存放一些基础工具接口,比如:数据库、中间件、加解密算法、基础协议等等。在这篇文章中, 我主要分享一下在基于Go语言的项目中, 加解密算法中如何封装一个通用的加解密接口, 并以使用比较广泛的AES加解密算法实现为基础进行讲解, 最后模拟客户端分别演示调用AES的加密接口和解密接口。OYf28资讯网——每日最新资讯28at.com

OYf28资讯网——每日最新资讯28at.com

2.工程文件结构

在一个正规项目中, 我们要封装的文件主要添加在算法文件夹下, 目录结构规划如下:OYf28资讯网——每日最新资讯28at.com

pkg | ---- algorithm        |        ---- base.go        // 基础接口函数定义        |        ---- aes.go         // aes加解密算法接口        |        ---- aes_test.go    // aes加解密算法接口函数测试

我在名为"algorithm"文件夹下新建了三个文件, 其中base.go为基础接口函数定义, 因为以后可能要加入进来的算法会比较多,因此需要有一个基础类文件来定义通用函数接口。OYf28资讯网——每日最新资讯28at.com

aes.go文件中主要实现AES算法的加解密过程, 并提供一个对外的初始化接口,方便应用层调用。OYf28资讯网——每日最新资讯28at.com

aes_test.go是作为单元测试的文件, 在里面可以针对AES加密函数和解密函数写测试用例, 不用编译整个工程实现单元测试。OYf28资讯网——每日最新资讯28at.com

如果后面有新的算法加入进来, 例如:des算法, 只需要添加一个des.go和des_test.go文件, 在里面实现函数功能即可。OYf28资讯网——每日最新资讯28at.com

3.基础接口实现

基础接口实现主要在base.go文件中, 因为对于所有加密算法来讲, 都有两个最基础通用的方法:加密函数和解密函数,因此这里定义了两个通用的方法接口:OYf28资讯网——每日最新资讯28at.com

type IAlgorithm interface {  Encrypt() // 加密函数接口  Decrypt() // 解密函数接口}

因为现在不知道项目默认需要使用什么算法,因此实现这两个方法的空接口:OYf28资讯网——每日最新资讯28at.com

type DefaultAlgorithm struct{}func (dal DefaultAlgorithm) Encrypt() {}func (dal DefaultAlgorithm) Decrypt() {}

考虑在应用层方便切换不同的算法, 这里需要设计一个管理接口的方法, 首先定义一个结构体:OYf28资讯网——每日最新资讯28at.com

type AlgorithmManager struct {  algorithm IAlgorithm}

在这个结构体中, 成员是上面接口名称的对象。OYf28资讯网——每日最新资讯28at.com

然后我定义了两个方法, 一个是设置算法对象的方法, 另一个是执行算法方式的方法。OYf28资讯网——每日最新资讯28at.com

首先是设置算法对象的方法:OYf28资讯网——每日最新资讯28at.com

func (gor *AlgorithmManager) SetAlgorithm(algorithm IAlgorithm) {  gor.algorithm = algorithm}

这个方法会接收一个参数,这个参数就是用户想要调用哪种算法的对象, 只有给接口赋对应算法的对象,接口才知道调用哪个算法的方法。OYf28资讯网——每日最新资讯28at.com

其次是运行算法类型的方法:OYf28资讯网——每日最新资讯28at.com

const (  encryptMode = "encrypt"  decryptMode = "decrypt")func (gor *AlgorithmManager) RunAlgorithm(runMode string) {  switch runMode {  case encryptMode:    gor.algorithm.Encrypt()    break  case decryptMode:    gor.algorithm.Decrypt()    break  }}

这里我定义了两个模式用来标识加密模式和解密模式, 当给RunAlgorithm传参encryptMode, 则会执行加密函数,反之则执行解密函数。OYf28资讯网——每日最新资讯28at.com

4.AES加解密算法实现

在AES加解密客户端调用接口中, 我选择了选项设计模式, 用户可以根据加密算法和解密算法参数不同进行灵活的选项传参。OYf28资讯网——每日最新资讯28at.com

首先定义一个方法结构体:OYf28资讯网——每日最新资讯28at.com

type AesAlgorithm struct {  AppAlg *AlgorithmManager  EncryptKey string // 密钥  PlaintextContent string // 明文内容  CiphertextContent string // 密文内容}

在这个结构体中, 密钥、明文内容、密文内容是我们在使用功能过程中必须传入的参数, 其中还带有一个结构对象指针: *AlgorithmManager, 方便我们将AES算法的对象传给接口,让其调用AES的加密方法或解密方法。OYf28资讯网——每日最新资讯28at.com

其次定义一个方便客户端调用的接口, 并使用动态选项传参,实现代码如下:OYf28资讯网——每日最新资讯28at.com

type AesAlgorithmOption func(aes *AesAlgorithm)// 用户初始化调用并传参func NewAesAlgorithm(options ...AesAlgorithmOption) *AesAlgorithm {  aesAlg := &AesAlgorithm{    AppAlg: new(AlgorithmManager),    EncryptKey: "",    PlaintextContent: "",    CiphertextContent: "",  }  for _, option := range options {    option(aesAlg)  }  return aesAlg}// 通过该选项函数传入keyfunc WithEncryptKey(key string) AesAlgorithmOption {  return func(aes *AesAlgorithm) {    aes.EncryptKey = key  }}// 通过该选项函数传入明文func WithPlaintextContent(plainText string) AesAlgorithmOption {  return func(aes *AesAlgorithm) {    aes.PlaintextContent = plainText  }}// 通过该选项函数传入密文func WithCiphertextContent(cipherContent string) AesAlgorithmOption {  return func(aes *AesAlgorithm) {    aes.CiphertextContent = cipherContent  }}

下面我们还实现了两个内部函数,分别是加密和解密过程中需要填充块的实现方法,代码如下:OYf28资讯网——每日最新资讯28at.com

加密填充块:OYf28资讯网——每日最新资讯28at.com

func pkcs5Padding(cipherText []byte, blockSize int) []byte {  padding := blockSize - len(cipherText)%blockSize  padtext := bytes.Repeat([]byte{byte(padding)}, padding)  return append(cipherText, padtext...)}

解密填充块:OYf28资讯网——每日最新资讯28at.com

func pkcs5UnPadding(origData []byte) []byte {  length := len(origData)  unpadding := int(origData[length-1])  return origData[:(length - unpadding)]}

最后实现了加密接口函数和解密接口函数,代码如下:OYf28资讯网——每日最新资讯28at.com

加密接口函数实现:OYf28资讯网——每日最新资讯28at.com

func (aalg *AesAlgorithm) Encrypt() {  tmpKeys := []byte(aalg.EncryptKey)  tmpPlaintext := aalg.PlaintextContent  block, err := aes.NewCipher(tmpKeys)  if err != nil {    fmt.Println("aes加密失败,原因:" + err.Error())    return  }  blockSize := block.BlockSize()  origData := pkcs5Padding([]byte(tmpPlaintext), blockSize)  blockMode := cipher.NewCBCEncrypter(block, tmpKeys[:blockSize])  crypted := make([]byte, len(origData))  blockMode.CryptBlocks(crypted, origData)  aalg.CiphertextContent = hex.EncodeToString(crypted)}

解密接口函数实现:OYf28资讯网——每日最新资讯28at.com

func (aalg *AesAlgorithm) Decrypt() {  tmpKeys := []byte(aalg.EncryptKey)  cryptedByte, _ := hex.DecodeString(aalg.CiphertextContent)  block, err := aes.NewCipher(tmpKeys)  if err != nil {    fmt.Println("aes解密失败,原因:" + err.Error())    return  }  blockSize := block.BlockSize()  blockMode := cipher.NewCBCDecrypter(block, tmpKeys[:blockSize])  origin := make([]byte, len(cryptedByte))  blockMode.CryptBlocks(origin, cryptedByte)  decryptStrings := pkcs5UnPadding(origin)  aalg.PlaintextContent = string(decryptStrings)}

5.AES加密函数验证

我在aes_test.go中实现加密函数测试模块:TestEncrypt(t *testing.T), 代码如下:OYf28资讯网——每日最新资讯28at.com

func TestEncrypt(t *testing.T) {  aesAlg := NewAesAlgorithm(    WithEncryptKey("ZEplYJFPLlhhMaJI"),    WithPlaintextContent("qYWwo7!!Eq-TX3q"),  )  aesAlg.AppAlg.SetAlgorithm(aesAlg)  aesAlg.AppAlg.RunAlgorithm("encrypt")  fmt.Println(aesAlg.CiphertextContent)}

在上面的代码中, 我们调用了AES算法的对外统一接口函数:NewAesAlgorithm, 并分别调用WithEncryptKey和WithPlaintextContent传入了Key内容和明文内容, 并调用接口管理方法:SetAlgorithm进行对象赋值, 最后调用RunAlgorithm("encrypt")方法进行AES加密,实际结果如下:OYf28资讯网——每日最新资讯28at.com

OYf28资讯网——每日最新资讯28at.com

6.AES解密函数验证

同样在aes_test.go中实现加密函数测试模块:TestDecrypt(t *testing.T), 代码如下:OYf28资讯网——每日最新资讯28at.com

func TestDecrypt(t *testing.T) {  aesAlg := NewAesAlgorithm(    WithEncryptKey("ZEplYJFPLlhhMaJI"),    WithCiphertextContent("31404e2eb60e2d16faae152106882f4b"),  )  aesAlg.AppAlg.SetAlgorithm(aesAlg)  aesAlg.AppAlg.RunAlgorithm("decrypt")  fmt.Println(aesAlg.PlaintextContent)}

在上面的代码中, 我们调用了AES算法的对外统一接口函数:NewAesAlgorithm, 并分别调用WithEncryptKey和WithCiphertextContent传入了Key内容和上面加密的密文内容, 并调用接口管理方法:SetAlgorithm进行对象赋值, 最后调用RunAlgorithm("decrypt")方法进行AES解密,实际结果如下:OYf28资讯网——每日最新资讯28at.com

OYf28资讯网——每日最新资讯28at.com

可以看到,成功解密出密文且跟加密时传入的明文一致,解密正确。OYf28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-56425-0.html在 Go 项目中封装 AES 加解密客户端接口

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Rust结构体的定义和实例化

下一篇: Go 语言为什么很少使用数组?

标签:
  • 热门焦点
  • MIX Fold3包装盒泄露 新机本月登场

    小米的全新折叠屏旗舰MIX Fold3将于本月发布,近日该机的真机包装盒在网上泄露。从图上来看,新的MIX Fold3包装盒在外观设计方面延续了之前的方案,变化不大,这也是目前小米旗舰
  • 掘力计划第 20 期:Flutter 混合开发的混乱之治

    在掘力计划系列活动第20场,《Flutter 开发实战详解》作者,掘金优秀作者,Github GSY 系列目负责人恋猫的小郭分享了Flutter 混合开发的混乱之治。Flutter 基于自研的 Skia 引擎
  • 从 Pulsar Client 的原理到它的监控面板

    背景前段时间业务团队偶尔会碰到一些 Pulsar 使用的问题,比如消息阻塞不消费了、生产者消息发送缓慢等各种问题。虽然我们有个监控页面可以根据 topic 维度查看他的发送状态,
  • 分享六款相见恨晚的PPT模版网站, 祝你做出精美的PPT!

    1、OfficePLUSOfficePLUS网站旨在为全球Office用户提供丰富的高品质原创PPT模板、实用文档、数据图表及个性化定制服务。优点:OfficePLUS是微软官方网站,囊括PPT模板、Word模
  • 学习JavaScript的10个理由...

    作者 | Simplilearn编译 | 王瑞平当你决心学习一门语言的时候,很难选择到底应该学习哪一门,常用的语言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 之家push系统迭代之路

    前言在这个信息爆炸的互联网时代,能够及时准确获取信息是当今社会要解决的关键问题之一。随着之家用户体量和内容规模的不断增大,传统的靠"主动拉"获取信息的方式已不能满足用
  • .NET 程序的 GDI 句柄泄露的再反思

    一、背景1. 讲故事上个月我写过一篇 如何洞察 C# 程序的 GDI 句柄泄露 文章,当时用的是 GDIView + WinDbg 把问题搞定,前者用来定位泄露资源,后者用来定位泄露代码,后面有朋友反
  • JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 超闭合精工铰链 彻底消灭缝隙 三星Galaxy Z Flip5与Galaxy Z Fold5发布

    2023年7月26日,三星电子正式发布了Galaxy Z Flip5与Galaxy Z Fold5。三星新一代折叠屏手机采用超闭合精工铰链,让折叠后的缝隙不再可见。同时,配合处
Top