cdm*_*kay 1 php c++ encryption blowfish nsis
对于我正在进行的项目,我需要使用Blowfish以跨NSIS和PHP的兼容方式加密和解密字符串.
目前我正在使用NSIS 的Blowfish ++插件和mcryptPHP 的库.问题是,我不能让他们两个产生相同的输出.
让我们从NSIS Blowfish ++插件开始.基本上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
Run Code Online (Sandbox Code Playgroud)
没有提到它是CBC,ECB,CFB等,而且我对Blowfish不够熟悉,无法通过阅读大部分未记录的来源来讲述.我认为它是ECB,因为PHP文档mcrypt告诉我ECB不需要IV.
我还通过阅读源代码了解到Blowfish ++插件将Base64解码第二个加密参数(我不知道为什么).它还返回Base64编码的字符串.
对于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);
Run Code Online (Sandbox Code Playgroud)
但是,如果我做了所有这些事情,我会得到以下每个输出:
NSIS: GyCyBcUE0s5gqVDshVUB8w==
PHP: BQdlPd19zEkX5KT9tnF8Ng==
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?NSIS插件不使用ECB吗?如果不是,那它用于IV的是什么?
caf*_*caf 11
好的,我已经完成了代码并重现了你的结果.问题不在于密码模式 - NSIS 正在使用ECB.问题是NSIS Blowfish代码只是在小端机器上被破坏了.
Blowfish算法在两个32位无符号整数上运行.要在64位明文或密文块与这两个整数之间进行转换,该块应该被解释为两个Big Endian整数.相反,NSIS Blowfish插件以主机字节顺序解释它们 - 因此它无法在小端主机(如x86)上做正确的事情.这意味着它将与自身互操作,但不能与真正的Blowfish实现(如mcrypt).
我为你修补了Blowfish ++以使它做正确的事 - 修改后的Blowfish::Encrypt以及Blowfish::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;
}
Run Code Online (Sandbox Code Playgroud)