1

私が取り組んでいるプロジェクトでは、NSIS と PHP の間で互換性のある方法で Blowfish を使用して文字列を暗号化および復号化する必要があります。

現時点では、NSIS 用のBlowfish++ プラグインmcryptと PHP のライブラリを使用しています。問題は、両方で同じ出力を生成できないことです。

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

それが CBC、ECB、CFB などであるかどうかについての言及はありません。私は、ほとんど文書化されていないソースを読んでもわかるほど Blowfish に精通していません。ECB は IV を必要としないとPHPmcryptのドキュメントに書かれているので、ECB だと思います。

また、ソース コードを読んで、Blowfish++ プラグインが 2 番目の引数を 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);

ただし、これらすべてを実行すると、それぞれから次の出力が得られます。

NSIS: GyCyBcUE0s5gqVDshVUB8w==
PHP:  BQdlPd19zEkX5KT9tnF8Ng==

私は何を間違っていますか?NSIS プラグインは ECB を使用していませんか? そうでない場合、それは IV に何を使用していますか?

4

1 に答える 1

11

OK、そのコードを調べて、結果を再現しました。問題は暗号モードではありません - NSISECB を使用しています。問題は、NSIS Blowfish コードがリトル エンディアン マシンで単純に壊れていることです。

Blowfish アルゴリズムは、2 つの 32 ビット符号なし整数で動作します。64 ビットの平文または暗号文ブロックとこれら 2 つの整数の間で変換するには、ブロックを 2 つのビッグ エンディアン整数として解釈する必要があります。NSIS Blowfish プラグインは代わりにホストのバイト順で解釈するため、リトル エンディアンのホスト (x86 など) では正しく動作しません。これは、それ自体と相互運用できることを意味しますが、本物の Blowfish 実装 ( などmcrypt) とは相互運用できません。

Blowfish++ にパッチを適用して、正しいことを実行できるようにしました。変更されたものBlowfish::EncryptBlowfish::Decrypt以下にあり、の新しいバージョンはPastebinblowfish.cppにあります。

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;
}
于 2010-01-28T11:26:07.587 に答える