go语言 实现对称加密解密算法

Posted mishell

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言 实现对称加密解密算法相关的知识,希望对你有一定的参考价值。

package main

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

// main 入口函数
func main() {
	// DES密钥
	key := "12345678" // 占8字节
	// 3DES密钥
	// key = "abcdefgh0123456712345678" //占24字节
	// AES密钥 key长度 16 24 32 对应 AES-128 AES-192 AES-256
	// key = "abcdefgh0123456712345678" //占24字节

	data := "学习技术,改变世界"
	chipherArr, err := SCEncryptString(data, key, "des")
	if err != nil {
		panic(err)
	}
	fmt.Printf("加密后字节数组:%v
", chipherArr)
	fmt.Printf("加密后16进制:%x
", chipherArr)

	originalBytes, err := SCDecryptString(chipherArr, key, "des")
	if err != nil {
		panic(err)
	}
	fmt.Println("解密后:", string(originalBytes))
}

// SCEncrypt DES加密
func SCEncrypt(originalBytes, key []byte, scType string) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	var err error
	var block cipher.Block
	switch scType {
	case "des":
		block, err = des.NewCipher(key)
	case "3des":
		block, err = des.NewTripleDESCipher(key)
	case "aes":
		block, err = aes.NewCipher(key)
	}
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	fmt.Println("---blockSize---", blockSize)
	// 2、对明文填充字节(参数为原始字节切片和密码对象的区块个数)
	paddingBytes := PKCSSPadding(originalBytes, blockSize)
	fmt.Println("填充后的字节切片:", paddingBytes)
	// 3、 实例化加密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
	fmt.Println("加密模式:", blockMode)
	// 4、对填充字节后的明文进行加密(参数为加密字节切片和填充字节切片)
	cipherBytes := make([]byte, len(paddingBytes))
	blockMode.CryptBlocks(cipherBytes, paddingBytes)
	return cipherBytes, nil
}

// SCDecrypt 解密字节切片,返回字节切片
func SCDecrypt(cipherBytes, key []byte, scType string) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	var err error
	var block cipher.Block
	switch scType {
	case "des":
		block, err = des.NewCipher(key)
	case "3des":
		block, err = des.NewTripleDESCipher(key)
	case "aes":
		block, err = aes.NewCipher(key)
	}
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 2、 实例化解密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	// fmt.Println("解密模式:", blockMode)
	// 3、对密文进行解密(参数为加密字节切片和填充字节切片)
	paddingBytes := make([]byte, len(cipherBytes))
	blockMode.CryptBlocks(paddingBytes, cipherBytes)
	// 4、去除填充字节(参数为填充切片)
	originalBytes := PKCSSUnPadding(paddingBytes)
	return originalBytes, nil
}

// SCEncryptString SCEncryptString
func SCEncryptString(originalText, key, scType string) (string, error) {
	chipherArr, err := SCEncrypt([]byte(originalText), []byte(key), scType)
	if err != nil {
		panic(err)
	}
	base64str := base64.StdEncoding.EncodeToString(chipherArr)
	return base64str, nil
}

// SCDecryptString SCDecryptString
func SCDecryptString(chipherText, key, scType string) (string, error) {
	chipherArr, _ := base64.StdEncoding.DecodeString(chipherText)
	chipherArr, err := SCDecrypt(chipherArr, []byte(key), scType)
	if err != nil {
		panic(err)
	}
	return string(chipherArr), nil
}

// PKCSSPadding 填充字节的函数
func PKCSSPadding(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	fmt.Println("要填充的字节:", padding)
	// 初始化一个元素为padding的切片
	slice1 := []byte{byte(padding)}
	slice2 := bytes.Repeat(slice1, padding)
	return append(data, slice2...)
}

// ZeroPadding 填充字节的函数
func ZeroPadding(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	fmt.Println("要填充的字节:", padding)
	// 初始化一个元素为padding的切片
	slice1 := []byte{0}
	slice2 := bytes.Repeat(slice1, padding)
	return append(data, slice2...)
}

// PKCSSUnPadding 去除填充字节的函数
func PKCSSUnPadding(data []byte) []byte {
	unpadding := data[len(data)-1]
	result := data[:(len(data) - int(unpadding))]
	return result
}

// ZeroUnPadding 去除填充字节的函数
func ZeroUnPadding(data []byte) []byte {
	return bytes.TrimRightFunc(data, func(r rune) bool {
		return r == 0
	})
}

  

以上是关于go语言 实现对称加密解密算法的主要内容,如果未能解决你的问题,请参考以下文章

对称加密算法的分组模式及其Go语言实现

密码技术--非对称加密算法及Go语言应用

go语言教程哪里有?Go从入门到精通系列视频3.1 对称加密算法

密码技术--对称加密算法及Go语言应用

对称加密的分组加密模式以及go语言实现

密码技术--国密SM4分组密码算法及Go语言应用