Nodejs和java的aes-128-ecb加密结果不一样

Nodejs和java的aes-128-ecb加密结果不一样

nodejs代码如下:

encryptUtils.aesEncrypt = function(data, secretKey) { var cipher = crypto.createCipher(‘aes-128-ecb’,secretKey); return cipher.update(data,‘utf8’,‘hex’) + cipher.final(‘hex’); }

java代码:

public static String encryptAESBy128ECB(String content, String password) throws Exception { Cipher cipher = Cipher.getInstance(“AES/ECB/PKCS5Padding”); byte[] raw = password.getBytes(“utf-8”); SecretKeySpec skeySpec = new SecretKeySpec(raw, “AES”); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(content.getBytes(“utf-8”)); return bytesToHexString(encrypted); } 经测试两个结果不一样,有谁遇到过吗,目前的业务需求是nodejs和android之间的加解密通讯,然后遇到了这个问题


2 回复

标题:Node.js 和 Java 的 AES-128-ECB 加密结果不一样

内容:

在实现 Node.js 和 Java 之间的 AES-128-ECB 加密时,经常会遇到加密结果不一致的问题。这是因为两者在处理加密过程中的某些细节有所不同。下面我们将通过具体的代码示例来解释这一现象,并提供解决方案。

Node.js 代码示例

const crypto = require('crypto');

function aesEncrypt(data, secretKey) {
    const cipher = crypto.createCipher('aes-128-ecb', secretKey);
    return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
}

// 示例调用
const data = "HelloWorld";
const secretKey = "0123456789abcdef"; // 16字节密钥
console.log(aesEncrypt(data, secretKey));

Java 代码示例

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class AesUtil {

    public static String encryptAESBy128ECB(String content, String password) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        byte[] raw = password.getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(content.getBytes("utf-8"));
        return bytesToHexString(encrypted);
    }

    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    // 示例调用
    public static void main(String[] args) throws Exception {
        String data = "HelloWorld";
        String secretKey = "0123456789abcdef"; // 16字节密钥
        System.out.println(encryptAESBy128ECB(data, secretKey));
    }
}

解释

  1. 填充模式不同

    • Node.js 默认使用 aes-128-ecb,这通常意味着没有填充(即 ECB 模式下的原始数据长度必须是块大小的倍数)。
    • Java 使用的是 AES/ECB/PKCS5Padding,这意味着数据会自动进行 PKCS5 填充以确保其长度为块大小的倍数。
  2. 密钥长度

    • 在 Node.js 中,密钥长度必须恰好为 16 字节(128 位)。
    • 在 Java 中,密钥长度同样需要为 16 字节(128 位),但 Java 会自动将字符串转换为字节数组。

解决方案

为了使 Node.js 和 Java 的加密结果一致,可以在 Node.js 中显式地添加 PKCS5 填充:

function aesEncryptWithPadding(data, secretKey) {
    const blockSize = 16;
    const paddingLength = blockSize - (data.length % blockSize);
    const paddedData = data + String.fromCharCode(paddingLength).repeat(paddingLength);

    const cipher = crypto.createCipheriv('aes-128-ecb', secretKey, null);
    return cipher.update(paddedData, 'utf8', 'hex') + cipher.final('hex');
}

这样可以确保 Node.js 和 Java 的加密结果一致。


在 Node.js 和 Java 中使用 AES-128-ECB 加密时,可能会因为不同的默认设置导致加密结果不同。具体来说,Node.js 默认可能没有填充数据,而 Java 使用了 PKCS5Padding。

以下是调整后的 Node.js 和 Java 示例代码:

Node.js 示例代码

const crypto = require('crypto');

function aesEncrypt(data, secretKey) {
    const cipher = crypto.createCipheriv('aes-128-ecb', secretKey, null);
    cipher.setAutoPadding(true); // 确保处理填充
    return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
}

console.log(aesEncrypt('Hello World!', 'your_secret_key'));

Java 示例代码

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class AesEncryption {

    public static String encryptAESBy128ECB(String content, String password) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        byte[] raw = password.getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(content.getBytes("utf-8"));
        return bytesToHexString(encrypted);
    }

    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        System.out.println(encryptAESBy128ECB("Hello World!", "your_secret_key"));
    }
}

解释

  • Node.js: 使用 createCipheriv 创建 Cipher 对象,并显式指定 setAutoPadding(true) 来确保填充。
  • Java: 使用 "AES/ECB/PKCS5Padding" 来确保使用相同的填充方式。

通过上述修改,你应该能够获得一致的加密结果。

回到顶部