[英]Matching blowfish encryption in php openssl_encrypt and 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 实现,但到目前为止我失败了。
以下问题会导致不同的结果:
河豚有一个8字节块大小和4个56字节之间的可变密钥大小。 在 PHP 中,Blowfish 有一个错误,它将较短的键填充到 16 个字节,其中包含 0 个值。 从 7.1.8 版开始,有一个标志可以防止这种情况: OPENSSL_DONT_ZERO_PAD_KEY
。 如果另外设置了此标志 ( OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY
), OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY
产生以下输出结果(在所需的环境中):
253 145 220 198 224 78 40 124 61 82 97 183 42 220 119 173 26 156 153 20 152 139 105 237
这里有一个可以设置标志的在线 PHP 环境。
Go 中定义的填充是零填充,而在 PHP 代码中,openssl 使用 PKCS7 填充(默认情况下)。 对于 PKCS7,以下更改是必要的(没有注释,使用相同的名称):
func pad(pt []byte) []byte { modulus := len(pt) % blowfish.BlockSize padlen := blowfish.BlockSize - modulus for i := 0; i < padlen; i++ { pt = append(pt, byte(padlen)) } return pt }
通过此更改,Go - Code 给出了相同的结果:
[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。 如果需要,确切需要的缓冲区大小可以确定为明文长度加上填充长度(后者的确定类似于pad
函数中的padlen
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.