简体   繁体   English

NSIS和PHP之间的河豚加密消息

[英]Blowfish-encrypted messages between NSIS and PHP

For a project I'm working on, I need to encrypt and decrypt a string using Blowfish in a compatible way across NSIS and PHP. 对于我正在从事的项目,我需要在整个NSIS和PHP中以兼容的方式使用Blowfish加密和解密字符串。

At the moment I'm using the Blowfish++ plugin for NSIS and the mcrypt library with PHP. 目前,我正在为NSIS使用Blowfish ++插件 ,并在PHP中使用mcrypt库。 The problem is, I can't get them both to produce the same output. 问题是,我无法让它们都产生相同的输出。

Let's start with the NSIS Blowfish++ plugin. 让我们从NSIS Blowfish ++插件开始。 Basically the API is: 基本上,API是:

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

blowfish::encrypt "test@test.com***" "MTIzNDU2Nzg="
Pop $0 ; 0 on success, 1 on failure
Pop $1 ; encrypted message on success, error message on failure

There's no mention of whether it's CBC, ECB, CFB, etc. and I'm not familiar enough with Blowfish to be able to tell by reading the mostly undocumented source . 没有提及它是CBC,ECB,CFB等,而且我对Blowfish还不熟悉,无法通过阅读大部分未记录在案的资料来辨别。 I assume it's ECB since the PHP docs for mcrypt tells me that ECB doesn't need an IV . 我认为这是ECB,因为mcryptPHP文档告诉我ECB不需要IV

I've also learned by reading the source code that the Blowfish++ plugin will Base64 decode the second argument to encrypt (I'm not sure why). 通过阅读源代码,我还了解到Blowfish ++插件将Base64解码第二个参数以进行加密(我不确定为什么)。 It also returns a Base64 encoded string. 它还返回Base64编码的字符串。

For the PHP side of things, I'm basically using this code to encrypt: 对于PHP方面,我基本上使用以下代码进行加密:

$plainText = "test@test.com***";
$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);

However, if I do all these things, I get the following output from each: 但是,如果我做所有这些事情,我将从每件事中获得以下输出:

NSIS: GyCyBcUE0s5gqVDshVUB8w==
PHP:  BQdlPd19zEkX5KT9tnF8Ng==

What am I doing wrong? 我究竟做错了什么? Is the NSIS plugin not using ECB? NSIS插件不使用ECB吗? If not, what is it using for it's IV? 如果没有,IV的用途是什么?

OK, I've gone through that code and reproduced your results. 好的,我已经遍历了这段代码并复制了您的结果。 The problem isn't the cipher mode - NSIS is using ECB. 问题不在于密码模式-NSIS 正在使用ECB。 The problem is that the NSIS Blowfish code is simply broken on little-endian machines. 问题在于,NSIS Blowfish代码在小字节序计算机上只是被破坏了。

The Blowfish algorithm operates on two 32-bit unsigned integers. Blowfish算法对两个32位无符号整数进行运算。 To convert between a 64 bit plaintext or ciphertext block and these two integers, the block is supposed to be interpreted as two Big Endian integers. 为了在64位纯文本或密文块与这两个整数之间进行转换,应该将该块解释为两个Big Endian整数。 The NSIS Blowfish plugin is instead interpreting them in host byte order - so it fails to do the right thing on little-endian hosts (like x86). NSIS Blowfish插件反而以主机字节顺序解释它们-因此,它在小字节序主机(如x86)上无法正确执行操作。 This means it'll interoperate with itself, but not with genuine Blowfish implementations (like mcrypt ). 这意味着它将与自身进行互操作,但不会与真正的Blowfish实现(例如mcrypt )进行互操作。

I've patched Blowfish++ for you to make it do the right thing - the modified Blowfish::Encrypt and Blowfish::Decrypt are below, and the new version of blowfish.cpp is here on Pastebin . 我为您修补了Blowfish ++,以使其做正确的事-修改后的Blowfish::EncryptBlowfish::Decrypt在下面,而新版本的blowfish.cpp 在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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM