Golang:如何使用 DES、CBC 和 PKCS7 解密?

Posted

技术标签:

【中文标题】Golang:如何使用 DES、CBC 和 PKCS7 解密?【英文标题】:Golang: How do I decrypt with DES, CBC, and PKCS7? 【发布时间】:2017-01-10 22:10:39 【问题描述】:

目前正试图弄清楚为什么我的解密方法不起作用。我使用 DES、CBC 和 PKCS7Padding 来加密我的字符串。我当前的code 在解密期间输出panic: crypto/cipher: input not full blocks

【问题讨论】:

1.不要使用 DES,它不安全,并且已被 AES 取代,AES 并不难使用。 2. 使用随机IV,只需在加密数据前加上IV前缀,用于解密(IV不需要保密)。当相同的加密密钥用于多条消息时,使用不同的 IV 很重要。 3. 考虑一下,加密的目的通常是为了创造安全性,使用不当的加密不会提供安全性。 不清楚你想解密一个12个字符的加密字符串并指定一个唯一的密钥和一个唯一的IV。必须使用用于加密的相同密钥和 IV 进行解密。这个问题可以更清楚,并提供更多关于你想要完成的事情的信息。 对于初学者来说,解密时您没有解码 base64,这就是数据大小错误的原因。 @zaph 感谢您的反馈和见解。我的代码是本地原型,而不是生产代码。 @JimB 哎呀!谢谢你接听。 【参考方案1】:

伙计,它工作得很好。

package main

    import (
        "bytes"
        "crypto/des"
        "crypto/cipher"
        "fmt"
    )

    func DesEncryption(key, iv, plainText []byte) ([]byte, error) 

        block, err := des.NewCipher(key)

        if err != nil 
            return nil, err
        

        blockSize := block.BlockSize()
        origData := PKCS5Padding(plainText, blockSize)
        blockMode := cipher.NewCBCEncrypter(block, iv)
        cryted := make([]byte, len(origData))
        blockMode.CryptBlocks(cryted, origData)
        return cryted, nil
    

    func DesDecryption(key, iv, cipherText []byte) ([]byte, error) 

        block, err := des.NewCipher(key)

        if err != nil 
            return nil, err
        

        blockMode := cipher.NewCBCDecrypter(block, iv)
        origData := make([]byte, len(cipherText))
        blockMode.CryptBlocks(origData, cipherText)
        origData = PKCS5UnPadding(origData)
        return origData, nil
    

    func PKCS5Padding(src []byte, blockSize int) []byte 
        padding := blockSize - len(src)%blockSize
        padtext := bytes.Repeat([]bytebyte(padding), padding)
        return append(src, padtext...)
    

    func PKCS5UnPadding(src []byte) []byte 
        length := len(src)
        unpadding := int(src[length-1])
        return src[:(length - unpadding)]
    


    func main() 
        originalText := "sysys"
        fmt.Println(originalText)
        mytext := []byte(originalText)

        key := []byte0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC 
        iv := []byte0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC 


        cryptoText,_ := DesEncryption(key, iv, mytext)
        fmt.Println(string(cryptoText))
        decryptedText,_ := DesDecryption(key, iv, cryptoText)
        fmt.Println(string(decryptedText))

    

【讨论】:

是的!谢谢!我只是在 main 中更改了一行。我将fmt.Println(string(cryptoText)) 更改为fmt.Println(base64.URLEncoding.EncodeToString(cryptoText)) 最好使用这个填充/取消填充代码:github.com/go-web/tokenizer/blob/master/pkcs7.go【参考方案2】:

你可以这样做

package controllers

import (
    "bytes"
    "crypto/aes"
    "crypto/cipher"
    "encoding/hex"
    "fmt"
)

func PKCS7Padding(ciphertext []byte) []byte 
    padding := aes.BlockSize - len(ciphertext) % aes.BlockSize
    padtext := bytes.Repeat([]bytebyte(padding), padding)
    return append(ciphertext, padtext...)


func PKCS7UnPadding(plantText []byte) []byte 
    length   := len(plantText)
    unpadding := int(plantText[length-1])
    return plantText[:(length - unpadding)]


func OpensslDecrypt(keyStr string, ivStr string, text string) string

    key, _ := hex.DecodeString(keyStr);
    iv, _ := hex.DecodeString(ivStr);
    ciphertext, _ := hex.DecodeString(text);

    block, err := aes.NewCipher(key)
    if err != nil 
        panic(err)
    
    plaintext := make([]byte,len(ciphertext))
    mode := cipher.NewCBCDecrypter(block, iv)
    mode.CryptBlocks(plaintext, ciphertext)

    plaintext = PKCS7UnPadding(plaintext)
    return fmt.Sprintf("%s\n", plaintext)


func OpensslEncrypt(keyStr string, ivStr string, text string) string

    plaintext := []byte(text)
    key, _ := hex.DecodeString(keyStr);
    iv, _ := hex.DecodeString(ivStr);

    plaintext = PKCS7Padding(plaintext);
    ciphertext := make([]byte,len(plaintext))
    block, err := aes.NewCipher(key)
    if err != nil 
        panic(err)
    

    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(ciphertext, plaintext)

    return fmt.Sprintf("%x\n", ciphertext)

【讨论】:

以上是关于Golang:如何使用 DES、CBC 和 PKCS7 解密?的主要内容,如果未能解决你的问题,请参考以下文章

常用的加密算法

常用的加密算法

如何在 Ruby 中使用('DES/CBC/PKCS5Padding'模式)实现 DES 加密?

如何使用 DES 实现 CBC-MAC?

DES--------Golang对称加密之模式问题实战

openssl 中调用哪个函数实现16字节des密钥cbc方式加密数据?