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

Posted Yuan_sr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了密码技术应用--SM4文件加解密相关的知识,希望对你有一定的参考价值。

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

以上是关于密码技术应用--SM4文件加解密的主要内容,如果未能解决你的问题,请参考以下文章

SM4AESDES加解密算法性能比较

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

国密gmssl介绍(SM2SM3SM4算法)

SM4算法简介

mongodb敏感数据加解密

mongodb敏感数据加解密