为什么node.js的encryption模块给出的结果与Java的AESencryption的Cipher类不同?

我试图理解为什么使用Java或Node.jsencryption它时encryption数据发生了变化,我需要修改node.js代码以使它返回与我在Java上相同的encryption数据。 (请注意,我不能修改java片段)

Node.js实现:

var crypto = require('crypto'); console.log("\n\n============"); var cKey = new Buffer("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "utf-8"); var cIv = new Buffer("1111111111111111", "utf-8"); var cData = "x"; console.log(cKey); console.log(cIv); console.log("UTF-8 Data: " + cData); var cipher = crypto.createCipheriv("aes-256-cbc", cKey, cIv); var cipherText = cipher.update(cData, 'utf8', 'hex') + cipher.final('hex'); console.log("Our data: " + cipherText); 

以前的代码将打印出以下结果:

 <Buffer 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41> <Buffer 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31> UTF-8 Data: x Our data: 0eddfe1857248c7057904455d189cf31 

Java实现:

 byte[] key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes(); byte[] data = "x".getBytes(); byte[] iv = "1111111111111111".getBytes(); Cipher cipher = Cipher.getInstance("AES"); IvParameterSpec ivspec = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), ivspec); byte[] result = cipher.doFinal(data); _print(result); 

该片段将打印:

 17b0ccd594229baa6dabd5e850e07fdf 

请注意,我比较了数据的字节数,iv和key,这些数字完全相同。

我怎样才能修改节点的片段,使其返回相同的Java字节?

您需要使用相同的操作模式。 您的java代码将密码string指定为“AES”。 这是不完全限定的,所以默认的JCE提供者将select自己的默认值“AES / AES / ECB / PKCS5Padding”(在你的情况下),因为它是最基本的,也是不安全的模式。

您需要在node.js中使用相同的操作模式。 唯一需要改变的两件事是IV尺寸(ECB不使用IV!)和密码string:

 var cIv = new Buffer(0); var cipher = crypto.createCipheriv("aes-256-ecb", cKey, cIv); 

请注意,ECB模式本身在语义上并不安全。 另外,密文还没有通过authentication,因此您应该使用HMAC-SHA256的encryption – 然后MACscheme或GCM或EAX等authentication模式。

你的node.js代码看起来好像在做它声称的那样,下面的unit testing成功了:

 @Test public void testAes() throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { byte[] key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes(); byte[] data = "x".getBytes(); byte[] iv = "1111111111111111".getBytes(); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); IvParameterSpec ivspec = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), ivspec); byte[] result = cipher.doFinal(data); assertEquals("0eddfe1857248c7057904455d189cf31", DatatypeConverter.printHexBinary(result).toLowerCase()); } 

我怀疑你的Java代码没有做它声称做的事情。