成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

在 Go 項(xiàng)目中封裝 AES 加解密客戶端接口

開發(fā) 后端 安全
在這篇文章中, 我主要分享一下在基于Go語言的項(xiàng)目中, 加解密算法中如何封裝一個(gè)通用的加解密接口, 并以使用比較廣泛的AES加解密算法實(shí)現(xiàn)為基礎(chǔ)進(jìn)行講解, 最后模擬客戶端分別演示調(diào)用AES的加密接口和解密接口。

1.摘要

在一個(gè)中型以上的項(xiàng)目中, 我們一般會在項(xiàng)目工程中開辟一個(gè)pkg文件夾用來存放一些基礎(chǔ)工具接口,比如:數(shù)據(jù)庫、中間件、加解密算法、基礎(chǔ)協(xié)議等等。在這篇文章中, 我主要分享一下在基于Go語言的項(xiàng)目中, 加解密算法中如何封裝一個(gè)通用的加解密接口, 并以使用比較廣泛的AES加解密算法實(shí)現(xiàn)為基礎(chǔ)進(jìn)行講解, 最后模擬客戶端分別演示調(diào)用AES的加密接口和解密接口。

2.工程文件結(jié)構(gòu)

在一個(gè)正規(guī)項(xiàng)目中, 我們要封裝的文件主要添加在算法文件夾下, 目錄結(jié)構(gòu)規(guī)劃如下:

pkg
 |
 ---- algorithm
        |
        ---- base.go        // 基礎(chǔ)接口函數(shù)定義
        |
        ---- aes.go         // aes加解密算法接口
        |
        ---- aes_test.go    // aes加解密算法接口函數(shù)測試

我在名為"algorithm"文件夾下新建了三個(gè)文件, 其中base.go為基礎(chǔ)接口函數(shù)定義, 因?yàn)橐院罂赡芤尤脒M(jìn)來的算法會比較多,因此需要有一個(gè)基礎(chǔ)類文件來定義通用函數(shù)接口。

aes.go文件中主要實(shí)現(xiàn)AES算法的加解密過程, 并提供一個(gè)對外的初始化接口,方便應(yīng)用層調(diào)用。

aes_test.go是作為單元測試的文件, 在里面可以針對AES加密函數(shù)和解密函數(shù)寫測試用例, 不用編譯整個(gè)工程實(shí)現(xiàn)單元測試。

如果后面有新的算法加入進(jìn)來, 例如:des算法, 只需要添加一個(gè)des.go和des_test.go文件, 在里面實(shí)現(xiàn)函數(shù)功能即可。

3.基礎(chǔ)接口實(shí)現(xiàn)

基礎(chǔ)接口實(shí)現(xiàn)主要在base.go文件中, 因?yàn)閷τ谒屑用芩惴▉碇v, 都有兩個(gè)最基礎(chǔ)通用的方法:加密函數(shù)和解密函數(shù),因此這里定義了兩個(gè)通用的方法接口:

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

因?yàn)楝F(xiàn)在不知道項(xiàng)目默認(rèn)需要使用什么算法,因此實(shí)現(xiàn)這兩個(gè)方法的空接口:

type DefaultAlgorithm struct{}

func (dal DefaultAlgorithm) Encrypt() {}

func (dal DefaultAlgorithm) Decrypt() {}

考慮在應(yīng)用層方便切換不同的算法, 這里需要設(shè)計(jì)一個(gè)管理接口的方法, 首先定義一個(gè)結(jié)構(gòu)體:

type AlgorithmManager struct {
  algorithm IAlgorithm
}

在這個(gè)結(jié)構(gòu)體中, 成員是上面接口名稱的對象。

然后我定義了兩個(gè)方法, 一個(gè)是設(shè)置算法對象的方法, 另一個(gè)是執(zhí)行算法方式的方法。

首先是設(shè)置算法對象的方法:

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

這個(gè)方法會接收一個(gè)參數(shù),這個(gè)參數(shù)就是用戶想要調(diào)用哪種算法的對象, 只有給接口賦對應(yīng)算法的對象,接口才知道調(diào)用哪個(gè)算法的方法。

其次是運(yùn)行算法類型的方法:

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
  }
}

這里我定義了兩個(gè)模式用來標(biāo)識加密模式和解密模式, 當(dāng)給RunAlgorithm傳參encryptMode, 則會執(zhí)行加密函數(shù),反之則執(zhí)行解密函數(shù)。

4.AES加解密算法實(shí)現(xiàn)

在AES加解密客戶端調(diào)用接口中, 我選擇了選項(xiàng)設(shè)計(jì)模式, 用戶可以根據(jù)加密算法和解密算法參數(shù)不同進(jìn)行靈活的選項(xiàng)傳參。

首先定義一個(gè)方法結(jié)構(gòu)體:

type AesAlgorithm struct {
  AppAlg *AlgorithmManager
  EncryptKey string // 密鑰
  PlaintextContent string // 明文內(nèi)容
  CiphertextContent string // 密文內(nèi)容
}

在這個(gè)結(jié)構(gòu)體中, 密鑰、明文內(nèi)容、密文內(nèi)容是我們在使用功能過程中必須傳入的參數(shù), 其中還帶有一個(gè)結(jié)構(gòu)對象指針: *AlgorithmManager, 方便我們將AES算法的對象傳給接口,讓其調(diào)用AES的加密方法或解密方法。

其次定義一個(gè)方便客戶端調(diào)用的接口, 并使用動態(tài)選項(xiàng)傳參,實(shí)現(xiàn)代碼如下:

type AesAlgorithmOption func(aes *AesAlgorithm)

// 用戶初始化調(diào)用并傳參
func NewAesAlgorithm(options ...AesAlgorithmOption) *AesAlgorithm {
  aesAlg := &AesAlgorithm{
    AppAlg: new(AlgorithmManager),
    EncryptKey: "",
    PlaintextContent: "",
    CiphertextContent: "",
  }
  for _, option := range options {
    option(aesAlg)
  }
  return aesAlg
}

// 通過該選項(xiàng)函數(shù)傳入key
func WithEncryptKey(key string) AesAlgorithmOption {
  return func(aes *AesAlgorithm) {
    aes.EncryptKey = key
  }
}

// 通過該選項(xiàng)函數(shù)傳入明文
func WithPlaintextContent(plainText string) AesAlgorithmOption {
  return func(aes *AesAlgorithm) {
    aes.PlaintextContent = plainText
  }
}

// 通過該選項(xiàng)函數(shù)傳入密文
func WithCiphertextContent(cipherContent string) AesAlgorithmOption {
  return func(aes *AesAlgorithm) {
    aes.CiphertextContent = cipherContent
  }
}

下面我們還實(shí)現(xiàn)了兩個(gè)內(nèi)部函數(shù),分別是加密和解密過程中需要填充塊的實(shí)現(xiàn)方法,代碼如下:

加密填充塊:

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

解密填充塊:

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

最后實(shí)現(xiàn)了加密接口函數(shù)和解密接口函數(shù),代碼如下:

加密接口函數(shù)實(shí)現(xiàn):

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)
}

解密接口函數(shù)實(shí)現(xiàn):

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加密函數(shù)驗(yàn)證

我在aes_test.go中實(shí)現(xiàn)加密函數(shù)測試模塊:TestEncrypt(t *testing.T), 代碼如下:

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)
}

在上面的代碼中, 我們調(diào)用了AES算法的對外統(tǒng)一接口函數(shù):NewAesAlgorithm, 并分別調(diào)用WithEncryptKey和WithPlaintextContent傳入了Key內(nèi)容和明文內(nèi)容, 并調(diào)用接口管理方法:SetAlgorithm進(jìn)行對象賦值, 最后調(diào)用RunAlgorithm("encrypt")方法進(jìn)行AES加密,實(shí)際結(jié)果如下:

6.AES解密函數(shù)驗(yàn)證

同樣在aes_test.go中實(shí)現(xiàn)加密函數(shù)測試模塊:TestDecrypt(t *testing.T), 代碼如下:

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

在上面的代碼中, 我們調(diào)用了AES算法的對外統(tǒng)一接口函數(shù):NewAesAlgorithm, 并分別調(diào)用WithEncryptKey和WithCiphertextContent傳入了Key內(nèi)容和上面加密的密文內(nèi)容, 并調(diào)用接口管理方法:SetAlgorithm進(jìn)行對象賦值, 最后調(diào)用RunAlgorithm("decrypt")方法進(jìn)行AES解密,實(shí)際結(jié)果如下:

可以看到,成功解密出密文且跟加密時(shí)傳入的明文一致,解密正確。

責(zé)任編輯:趙寧寧 來源: 二進(jìn)制空間安全
相關(guān)推薦

2010-10-28 14:21:52

2022-07-27 08:49:34

接口加密解密

2022-04-22 10:51:45

TSaxios前端

2024-09-27 15:24:15

Spring數(shù)據(jù)加解密

2025-06-27 10:12:15

Go封裝開發(fā)

2024-08-19 01:10:00

RedisGo代碼

2022-05-11 13:56:08

Java項(xiàng)目redis客戶端

2022-12-14 09:06:58

接口Spring解密

2022-09-14 18:23:01

工具加解密接口

2022-02-21 08:15:15

Go項(xiàng)目語言

2024-07-02 09:15:58

2012-10-11 17:02:02

IBMdw

2024-12-11 09:13:00

2017-12-07 10:25:55

LinuxGPG加密解密

2021-03-30 10:46:42

SpringBoot計(jì)數(shù)器漏桶算法

2009-03-04 10:27:50

客戶端組件桌面虛擬化Xendesktop

2024-10-17 08:58:31

2025-05-14 04:00:00

2022-01-26 07:25:09

PythonRSA加解密

2016-09-27 19:30:11

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 一区二区三区在线观看视频 | 成人三级影院 | 成人在线中文字幕 | 午夜网址| www.99精品 | 特黄毛片| 亚洲天堂一区 | 精品在线免费观看视频 | 国产精品久久久久久久久久久久久 | 国产三区在线观看视频 | 99免费在线观看 | 日韩精品av一区二区三区 | 精品视频在线一区 | a久久| 欧美成人猛片aaaaaaa | 亚洲精品久久嫩草网站秘色 | 亚洲精品欧美一区二区三区 | 亚洲精品一区二三区不卡 | 久久精品无码一区二区三区 | 午夜精品视频在线观看 | 91精品国产91久久久久久不卞 | 国产成人综合网 | 日韩中文字幕一区二区 | 九九热这里只有精品6 | 影音先锋中文字幕在线观看 | www.精品国产 | 在线观看亚洲专区 | 99久久精品国产一区二区三区 | 久久久久无码国产精品一区 | 精品人伦一区二区三区蜜桃网站 | 红色av社区 | 成人av免费 | 三级欧美 | 97超碰在线播放 | 亚洲嫩草 | 在线成人一区 | 91婷婷韩国欧美一区二区 | 日韩精品一区二区久久 | 中文字幕av亚洲精品一部二部 | 久久久综合久久 | 欧美日韩中文字幕在线 |