美文网首页go语言
golang中crypto/des包

golang中crypto/des包

作者: ljh123 | 来源:发表于2018-12-09 10:06 被阅读3次

    des是对称加密算法,更多关于des算法以及des算法实现移步百度。

    说明,内容转载至:http://blog.studygolang.com/2013/01/go%E5%8A%A0%E5%AF%86%E8%A7%A3%E5%AF%86%E4%B9%8Bdes/
    Go DES加密解密
    1、crypto/des包
    Go 中 crypto/des 包实现了 Data Encryption Standard (DES) and the Triple Data Encryption Algorithm(TDEA,三重DES加密)。查看该包文档。
    定义了DES块大小(8bytes),定义了一个KeySizeError。另外定义了两个我们需要特别关注的函数,即

    func NewCipher(key []byte) (cipher.Block, error)
    func NewTripleDESCipher(key []byte) (cipher.Block, error)
    

    两个函数都是用来获得一个cipher.Block。从名字中可以很容易知道,DES使用NewCipher,3DES使用NewTripleDESCipher。参数都是密钥(key)

    DES加密解密(CBC模式)
    1)加密
    代码实现:

    func DesEncrypt(origData, key []byte) ([]byte, error) {
        block, err := des.NewCipher(key)
        if err != nil {
            return nil, err
        }
        origData = PKCS5Padding(origData, block.BlockSize())
        blockMode := cipher.NewCBCEncrypter(block, key)
        crypted := make([]byte, len(origData))
        blockMode.CryptBlocks(crypted, origData)
        return crypted, nil
    }
    

    以上代码使用DES加密(des.NewCipher),加密模式为CBC(cipher.NewCBCEncrypter(block, key)),填充方式PKCS5Padding,该函数的代码如下:

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

    可见,数据长度刚好是blockSize的整数倍时,也进行了填充。

    2、解密

    func DesDecrypt(crypted, key []byte) ([]byte, error) {
         block, err := des.NewCipher(key)
         if err != nil {
              return nil, err
         }
         blockMode := cipher.NewCBCDecrypter(block, key)
         origData := make([]byte, len(crypted))
         // origData := crypted
         blockMode.CryptBlocks(origData, crypted)
         origData = PKCS5UnPadding(origData)
         // origData = ZeroUnPadding(origData)
         return origData, nil
    }
    

    可见,解密无非是调用cipher.NewCBCDecrypter,最后unpadding,其他跟加密几乎一样。相应的PKCS5UnPadding:

    func PKCS5UnPadding(origData []byte) []byte {
        length := len(origData)
        // 去掉最后一个字节 unpadding 次
        unpadding := int(origData[length-1])
        return origData[:(length - unpadding)]
    }
    

    3DES加密解密
    1)加密代码

    // 3DES加密
    func TripleDesEncrypt(origData, key []byte) ([]byte, error) {
         block, err := des.NewTripleDESCipher(key)
         if err != nil {
              return nil, err
         }
         origData = PKCS5Padding(origData, block.BlockSize())
         // origData = ZeroPadding(origData, block.BlockSize())
         blockMode := cipher.NewCBCEncrypter(block, key[:8])
         crypted := make([]byte, len(origData))
         blockMode.CryptBlocks(crypted, origData)
         return crypted, nil
    }
    

    对比DES,发现只是换了NewTripleDESCipher。不过,需要注意的是,密钥长度必须24byte,否则直接返回错误。关于这一点,PHP中却不是这样的,只要是8byte以上就行;而Java中,要求必须是24byte以上,内部会取前24byte(相当于就是24byte)。

    另外,初始化向量长度是8byte(目前各个语言都是如此,不是8byte会有问题)。然而,如果你用的Go是1.0.3(或以下),iv可以不等于8byte。其实,在cipher.NewCBCEncrypter方法中有注释:
    The length of iv must be the same as the Block’s block size.
    可是代码中的实现却没有做判断。不过,go tips中修正了这个问题,如果iv不等于block size(des为8),则直接panic。所以,对于加解密,一定要测试,保证iv等于block size,否则可能会panic:

    func NewCBCDecrypter(b Block, iv []byte) BlockMode {
         if len(iv) != b.BlockSize() {
              panic("cipher.NewCBCDecrypter: IV length must equal block size")
         }
         return (*cbcDecrypter)(newCBC(b, iv))
    }
    

    此处之所有用panic而不是返回error,个人猜测,是由于目前发布的版本,该方法没有返回error,修改方法签名会导致兼容性问题,因此用panic了。

    解密代码:

    // 3DES解密
    func TripleDesDecrypt(crypted, key []byte) ([]byte, error) {
         block, err := des.NewTripleDESCipher(key)
         if err != nil {
              return nil, err
         }
         blockMode := cipher.NewCBCDecrypter(block, key[:8])
         origData := make([]byte, len(crypted))
         // origData := crypted
         blockMode.CryptBlocks(origData, crypted)
         origData = PKCS5UnPadding(origData)
         // origData = ZeroUnPadding(origData)
         return origData, nil
    }
    

    相关文章

      网友评论

        本文标题:golang中crypto/des包

        本文链接:https://www.haomeiwen.com/subject/oywqhqtx.html