5

これまで私を避けてきた素早いもの(長い夜)。PHP と Java で AES256 を比較していて、相違点に気付きました。簡単にするために、ASCII キーとヌル IV は無視してください。これらは本番環境で置き換えられます。しかし、私は最初にこれを乗り越える必要があり、どこが間違っているのかわかりません:

PHP:

echo base64_encode(
    mcrypt_encrypt(
        MCRYPT_RIJNDAEL_128,
        "1234567890ABCDEF1234567890ABCDEF",
        "This is a test",
        MCRYPT_MODE_CBC,
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
    )
);

ジャワ

byte[] key = "1234567890ABCDEF1234567890ABCDEF".getBytes("UTF-8");
byte[] iv  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
SecretKeySpec newKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
byte[] results = cipher.doFinal("This is a test".getBytes("UTF-8"));

return Base64.encodeToString(results,Base64.DEFAULT);

PHP 出力: 0KwK+eubMErzDaPU1+mwTQ==

Java 出力:DEKGJDo3JPtk48tPgCVN3Q==

私が期待していたものとはまったく違います o_O !

MCRYPT_MODE_CBCMCRYPT_MODE_CFBMCRYPT_MODE_ECB、なども試しましたMCRYPT_MODE_NOFB。どれも Java 文字列を生成しませんでした。

4

1 に答える 1

1

PHP は入力バイトを でパディングし\0て、ブロック サイズの倍数にします。Java で同等のものは次のようになります (暗号化したい文字列が にあると仮定しますdata):

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();

byte[] inputBytes = data.getBytes();
int byteLength = inputBytes.length;
if (byteLength % blockSize != 0) {
    byteLength = byteLength + (blockSize - (byteLength % blockSize));
}

byte[] paddedBytes = new byte[byteLength];

System.arraycopy(inputBytes, 0, paddedBytes, 0, inputBytes.length);

cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
byte[] results = cipher.doFinal(paddedBytes);

これに対する警告として、ゼロベースのパディングは望ましくありません。\0文字列の末尾の文字と実際のパディングの違いを判断する方法はありません。代わりに PKCS5Padding を使用することをお勧めしますが、PHP では異なる結果が得られます。このような暗号化クロスプラットフォームが必要かどうか自問してください。

于 2013-02-13T03:09:39.593 に答える