1

nodejsに変換する必要があるこのPythonコードを取得しました。Python コードは、暗号化から pycrypto を使用します。nodejs 側では、ネイティブの crypto モジュールを使用しています。暗号化された文字列間に不一致があるようです。

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import json

raw_key = [0x58, 0x86, 0x17, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x28, 0xa4, 0x5a]
key = str(bytearray(raw_key))

raw_iv =  [0x34, 0x2e, 0x17, 0x99, 0x6d, 0x19, 0x3d, 0x28, 0xdd, 0xb3, 0xa2, 0x69, 0x5a, 0x2e, 0x6f, 0x1b]
iv = str(bytearray(raw_iv))

text = json.dumps({ "a": 1, "b": 2 })

cryptor = AES.new(key, AES.MODE_CBC, iv)
length = 16
count = len(text)
add = length - (count % length)
text = text + ('\0' * add)
encrypted = cryptor.encrypt(text);
print b2a_hex(encrypted)

上記の python コードの出力

5c72b1a394654b6dab9ea8fdd90fe56b92141d74cb32ac65ede4d3154801bb57

一方、以下のnodejsコード

const crypto = require('crypto');

const KEY = Buffer.from([0x58, 0x86, 0x17, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x28, 0xa4, 0x5a]);
const IV = Buffer.from([0x34, 0x2e, 0x17, 0x99, 0x6d, 0x19, 0x3d, 0x28, 0xdd, 0xb3, 0xa2, 0x69, 0x5a, 0x2e, 0x6f, 0x1b]);

const text = JSON.stringify({ a: 1, b: 2 });

const cipher = crypto.createCipheriv('aes-128-cbc', KEY, IV);
cipher.setAutoPadding(true);
const encrypted = Buffer.concat([cipher.update(text, 'utf-8'), cipher.final()]);
console.log(encrypted.toString('hex'));

出力

d6a0dbc6df2a1038036e4db985f9ca10

なぜ一致しないのですか?私は何か間違ったことをしていますか?

4

1 に答える 1

2

ここには 2 つの問題があります。

  1. ノードの自動パディングは PKCS パディングです。あなたの python コードは、代わりにパディングに null バイトを使用していますが、これは別の形式です。ノードのドキュメントでは、null バイトのパディングを使用するために自動パディングを無効にすることについても明示的に言及しています。

  2. JSON の形式は、ノードと python の間でわずかに異なります。JavascriptJSON.stringify()は不要な空白をすべて削除しますが、Python は一部の空白を残します (たとえば、配列/オブジェクトの要素間)。separatorsこれに対する最も簡単な解決策は、明示的なオプション:を指定するように Python コードを変更することでしょう。これは、この方法でフォーマットを変更する場合json.dumps({ "a": 1, "b": 2 }, separators=(',', ':'))、javascriptJSON.stringify()はそれほど柔軟ではないためです。

以下のノード コードは、JSON 出力を一致させ、適切なパディングを使用することで、Python と同じ 16 進出力が得られることを示しています。

const crypto = require('crypto');

const KEY = Buffer.from([0x58, 0x86, 0x17, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x28, 0xa4, 0x5a]);
const IV = Buffer.from([0x34, 0x2e, 0x17, 0x99, 0x6d, 0x19, 0x3d, 0x28, 0xdd, 0xb3, 0xa2, 0x69, 0x5a, 0x2e, 0x6f, 0x1b]);

var text = '{"a": 1, "b": 2}';

const cipher = crypto.createCipheriv('aes-128-cbc', KEY, IV);
cipher.setAutoPadding(false);

var length = 16;
var count = Buffer.byteLength(text);
var add = length - (count % length);
if (add > 0)
  text += '\0'.repeat(add);

const encrypted = Buffer.concat([cipher.update(text, 'utf-8'), cipher.final()]);
console.log(encrypted.toString('hex'));
于 2017-07-21T04:26:34.203 に答える