ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

密码技术应用--SM4文件加解密

2021-06-20 23:30:49  阅读:212  来源: 互联网

标签:return nil err -- SM4 加解密 plainText byte buf


记录一下对一些稍大文件进行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
}

标签:return,nil,err,--,SM4,加解密,plainText,byte,buf
来源: https://blog.csdn.net/weixin_38299404/article/details/118077054

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有