共计 2644 个字符,预计需要花费 7 分钟才能阅读完成。
记录一下对一些稍大文件进行 SM4 加解密的实现,这里只列出了外围代码,其余不波及的代码或者有任何疑难能够查看我之前写的明码技术专题博客
var key = []byte("1234567812345678")
var iv = []byte("1111111122222222")
/*
函数名:paddingLastGroup
对 CBC 加密模式的加密算法提供最初一个分块的明文数据填充
参 数:plainText , 明文数据
blockSize , CBC 分块大小
返回值:填充后的明文数据
创立工夫及创建者:2021-06-15 Yuan_sr
*/
func paddingLastGroup(plainText []byte, blockSize int) []byte{padNum := blockSize - len(plainText) % blockSize
char := []byte{byte(padNum)}
newPlain := bytes.Repeat(char, padNum)
newText := append(plainText, newPlain...)
return newText
}
/*
函数名:unpaddingLastGroup
对 CBC 加密模式的加密算法提供最初一个分块的明文数据去填充
参 数:plainText , 明文数据
返回值:去填充后的明文数据
创立工夫及创建者:2021-06-15 Yuan_sr
*/
func unpaddingLastGroup(plainText []byte) []byte{length := len(plainText)
lastChar := plainText[length - 1]
number := int(lastChar)
return plainText[:length - number]
}
/*
函数名:sm4Enctrpt
sm4 加密算法实现对文件的加密
参 数:filePathIn , 待加密文件
key , 加密密钥
返回值:加密后密文文件名
错误信息
创立工夫及创建者:2021-06-17 Yuan_sr
*/
func sm4Enctrpt(filePathIn string, key []byte) (string, error){inFile, err := os.Open(filePathIn)
if err != nil {return "", err}
defer inFile.Close()
outFile, err := os.Create(encryptFileName)
if err != nil {return "", err}
defer outFile.Close()
buf := make([]byte, bufferSize)
// 初始化一个底层加密算法
block, err := sm4.NewCipher(key)
if err != nil {return "", err}
// 抉择加密模式
blockMode := cipher.NewCBCEncrypter(block, iv)
for {n, err := inFile.Read(buf)
if err == io.EOF{break}
if err != nil && err != io.EOF {return "", err}
// 判断时最初一段数据则进行数据填充
if n != bufferSize{groupData := paddingLastGroup(buf[:n], block.BlockSize())
n = len(groupData)
buf = make([]byte, n)
buf = groupData
}
cipherText := make([]byte, n)
blockMode.CryptBlocks(cipherText, buf[:n])
_, err = outFile.Write(cipherText)
if err != nil {return "", err}
}
//outFile.Write(iv)
return encryptFileName, nil
}
/*
函数名:sm4Decrypt
sm4 解密算法实现对文件的解密
参 数:cipherFile , 密文文件
key , 解密密钥
返回值:解密后文件名
错误信息
创立工夫及创建者:2021-06-17 Yuan_sr
*/
func sm4Decrypt(cipherFile string, key []byte) (string, error){
// 字符串解决
imgTagName := getImgTagName(dvImgName)
plainFileName := imgTagName + ".tar"
if dvOutPath != "./" {err := os.MkdirAll(dvOutPath, 0755)
if err != nil {return "", err}
plainFileName = dvOutPath + imgTagName + ".tar"
}
//1. 创立一个 aes 底层明码接口
block, err := sm4.NewCipher(key)
if err != nil {return "", err}
//2. 抉择解密模式
blockMode := cipher.NewCBCDecrypter(block, iv)
//3. 解密
fr, err := os.Open(dvOutPath + cipherFile)
if err != nil {return "", err}
defer fr.Close()
fileInfo, err := fr.Stat()
if err != nil {return "", err}
blockNum := fileInfo.Size() / bufferSize
var num int64
fw, err := os.Create(plainFileName)
if err != nil {return "", err}
defer fw.Close()
buf := make([]byte, bufferSize)
for {
num += 1
n, err := fr.Read(buf)
if err == io.EOF{break}
if err != nil && err != io.EOF {return "", err}
plainText := make([]byte, n)
blockMode.CryptBlocks(plainText, buf[:n])
// 判断时最初一段数据则进行数据去填充
if num == blockNum + 1{plainText = unpaddingLastGroup(plainText)
n = len(plainText)
}
_, err = fw.Write(plainText[:n])
if err != nil {return "", err}
}
return plainFileName, nil
}
正文完