对于我正在从事的项目,我需要使用Blowfish以跨NSIS和PHP的兼容方式来加密和解密字符串。

目前,我正在使用NSIS的Blowfish++ plugin和PHP的mcrypt库。问题是,我无法让它们都产生相同的输出。

让我们从NSIS Blowfish ++插件开始。基本上,API是:

; Second argument needs to be base64 encoded
; base64_encode("12345678") == "MTIzNDU2Nzg="

blowfish::encrypt "[email protected]***" "MTIzNDU2Nzg="
Pop $0 ; 0 on success, 1 on failure
Pop $1 ; encrypted message on success, error message on failure

没有提及它是CBC,ECB,CFB等,而且我对河豚鱼还不熟悉,无法通过阅读mostly undocumented source来分辨。我认为这是自PHP docs for mcrypt tells me that ECB doesn't need an IV以来的欧洲央行。

通过阅读源代码,我还了解到Blowfish ++插件将对Base64解码第二个参数进行加密(我不确定为什么)。它还返回Base64编码的字符串。

对于PHP而言,我基本上是使用以下代码进行加密:
$plainText = "[email protected]***";
$cipher = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_ECB, '');
$iv = '00000000';  // Show not be used anyway.
$key = "12345678";

$cipherText = "";
if (mcrypt_generic_init($cipher, $key, $iv) != -1)
{
    $cipherText = mcrypt_generic($cipher, $plainText);
    mcrypt_generic_deinit($cipher);
}

echo base64_encode($cipherText);

但是,如果我做所有这些事情,我将从每件事中获得以下输出:
NSIS: GyCyBcUE0s5gqVDshVUB8w==
PHP:  BQdlPd19zEkX5KT9tnF8Ng==

我究竟做错了什么? NSIS插件不使用ECB吗?如果没有,IV的用途是什么?

最佳答案

好的,我已经遍历了这段代码并复制了您的结果。问题不在于密码模式-NSIS正在使用ECB。问题在于,NSIS Blowfish代码在小字节序机器上只是破损的

Blowfish算法对两个32位无符号整数进行运算。为了在64位纯文本或密文块与这两个整数之间进行转换,应该将该块解释为两个Big Endian整数。 NSIS Blowfish插件而是按主机字节顺序解释它们-因此,它在低位优先主机(如x86)上无法正确执行操作。这意味着它将与自身进行互操作,但不会与真正的Blowfish实现(例如mcrypt)进行互操作。

我为您修补了Blowfish ++,以使其做正确的事-修改后的Blowfish::EncryptBlowfish::Decrypt在下面,而blowfish.cpp的新版本是here on Pastebin

void Blowfish::Encrypt(void *Ptr,unsigned int N_Bytes)
{
    unsigned int i;
    unsigned char *Work;

    if (N_Bytes%8)
    {
            return;
    }

    Work = (unsigned char *)Ptr;

    for (i=0;i<N_Bytes;i+=8)
    {
        Word word0, word1;

        word0.byte.zero = Work[i];
        word0.byte.one = Work[i+1];
        word0.byte.two = Work[i+2];
        word0.byte.three = Work[i+3];

        word1.byte.zero = Work[i+4];
        word1.byte.one = Work[i+5];
        word1.byte.two = Work[i+6];
        word1.byte.three = Work[i+7];

        BF_En(&word0, &word1);

        Work[i] = word0.byte.zero;
        Work[i+1] = word0.byte.one;
        Work[i+2] = word0.byte.two;
        Work[i+3] = word0.byte.three;

        Work[i+4] = word1.byte.zero;
        Work[i+5] = word1.byte.one;
        Work[i+6] = word1.byte.two;
        Work[i+7] = word1.byte.three;
    }

    Work = NULL;
}

void Blowfish::Decrypt(void *Ptr, unsigned int N_Bytes)
{
    unsigned int i;
    unsigned char *Work;

    if (N_Bytes%8)
    {
            return;
    }

    Work = (unsigned char *)Ptr;
    for (i=0;i<N_Bytes;i+=8)
    {
        Word word0, word1;

        word0.byte.zero = Work[i];
        word0.byte.one = Work[i+1];
        word0.byte.two = Work[i+2];
        word0.byte.three = Work[i+3];

        word1.byte.zero = Work[i+4];
        word1.byte.one = Work[i+5];
        word1.byte.two = Work[i+6];
        word1.byte.three = Work[i+7];

        BF_De(&word0, &word1);

        Work[i] = word0.byte.zero;
        Work[i+1] = word0.byte.one;
        Work[i+2] = word0.byte.two;
        Work[i+3] = word0.byte.three;

        Work[i+4] = word1.byte.zero;
        Work[i+5] = word1.byte.one;
        Work[i+6] = word1.byte.two;
        Work[i+7] = word1.byte.three;
    }

    Work = NULL;
}

关于php - NSIS和PHP之间的河豚加密消息,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2152017/

10-10 06:45