猿问

在 php openssl_encrypt 和 golang blowfish 中匹配河豚加密

PHP:


$key = "testtesttest";

$text = "bublijuja";

$iv = openssl_random_pseudo_bytes( openssl_cipher_iv_length("blowfish"));

for($i = 0; $i < strlen($iv); $i++)

{

    echo ord($iv[$i])." ";

}

echo "\n";

$et = openssl_encrypt( $text, "blowfish", $key, OPENSSL_RAW_DATA, $iv );

for($i = 0; $i < strlen($et); $i++)

{

    echo ord($et[$i])." ";

}

echo "\n";

这打印(第一行是 IV,第二行是加密文本:


253 145 220 198 224 78 40 124 

208 51 12 30 46 92 13 181 19 210 50 57 174 207 93 130 

将该IV复制到golang:


package main


import (

    "golang.org/x/crypto/blowfish"

    "crypto/cipher"

    "fmt"

)




func main() {

    key  := "testtesttest"

    plaintext := "bublijuja"

    byteSlice := []int{253, 145, 220, 198, 224, 78, 40, 124}

    iv := make([]byte, len(byteSlice))

    for i, b := range byteSlice {

        iv[i] = byte(b)

    }

    fmt.Println(iv)

    ciphertext := make([]byte, blowfish.BlockSize+len(plaintext))

    block, err := blowfish.NewCipher([]byte(key))

    if err != nil {

    fmt.Println(err.Error())

    return

    }

    mode := cipher.NewCBCEncrypter(block, iv)

    mode.CryptBlocks(ciphertext, pad([]byte(plaintext)))


    fmt.Println(ciphertext)

}



func pad(pt []byte) []byte {

    // calculate modulus of plaintext to blowfish's cipher block size

    // if result is not 0, then we need to pad

    modulus := len(pt) % blowfish.BlockSize

    if modulus != 0 {

        // how many bytes do we need to pad to make pt to be a multiple of

        //blowfish's block size?

        padlen := blowfish.BlockSize - modulus

        // let's add the required padding

        for i := 0; i < padlen; i++ {

            // add the pad, one at a time

            pt = append(pt, 0)

        }

    }

    // return the whole-multiple-of-blowfish.BlockSize-sized plaintext

    // to the calling function

    return pt

}

我得到:


[253 145 220 198 224 78 40 124]

[61 82 97 183 42 220 119 173 114 107 250 139 174 236 113 91 0]

我也尝试过 ECB 模式。我曾经能够匹配前 8 个字节,但我搞砸了。我试图弄清楚 php 版本如何处理它,以便我可以匹配 go 实现,但到目前为止我失败了。


FFIVE
浏览 217回答 1
1回答

手掌心

以下问题导致不同的结果:Blowfish具有 8 字节的块大小和4 到 56 字节之间的可变密钥大小。在 PHP 中,Blowfish 存在一个错误,它将较短的键填充为 16 个字节,值为 0。从 7.1.8 版开始,有一个标志可以防止这种情况:OPENSSL_DONT_ZERO_PAD_KEY. 如果额外设置了此标志 ( OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY),则以下输出结果(在所需环境中):253 145 220 198 224 78 40 124&nbsp;61 82 97 183 42 220 119 173 26 156 153 20 152 139 105 237&nbsp;这里有一个可以设置标志的在线PHP环境。Go 中定义的填充是零填充,而在 PHP 代码中 PKCS7 填充由 openssl 使用(默认情况下)。对于 PKCS7,需要进行以下更改(不加注释,使用相同的名称):func pad(pt []byte) []byte {&nbsp; &nbsp; modulus := len(pt) % blowfish.BlockSize&nbsp; &nbsp; padlen := blowfish.BlockSize - modulus&nbsp; &nbsp; for i := 0; i < padlen; i++ {&nbsp; &nbsp; &nbsp; &nbsp; pt = append(pt, byte(padlen))&nbsp; &nbsp; }&nbsp; &nbsp; return pt}通过此更改,Go - 代码给出了相同的结果:[253 145 220 198 224 78 40 124][61 82 97 183 42 220 119 173 26 156 153 20 152 139 105 237 0]末尾的 0 是由于密文缓冲区过大造成的。在 Go 代码中,输出缓冲区的长度是用明文长度加上块大小(Blowfish 为 8 字节)计算的,这确保有足够的空间用于填充,因为最大填充是一个块。对于较短的填充,缓冲区太大,例如在当前情况下,明文的长度为 9 个字节,这导致缓冲区为 17 个字节。密文的长度为 16 个字节,最后是 0。如果需要,可以将确切需要的缓冲区大小确定为明文长度加上填充长度(后者的确定类似于函数padlen中的pad内容)。
随时随地看视频慕课网APP

相关分类

Go
我要回答