java - 在 Node js 中通过 AES/GCM/NoPadding 算法使用 key 和 iv 加密有效负载并在 java 中解密

标签 java node.js encryption cryptography aes-gcm

我使用node.js加密文件并在JAVA中解密。解密是在 JAVA 中使用“AES/GCM/Nopadding”算法完成的,它是第三方应用程序,因此我看不到 JAVA 代码。 我使用“aes-128-gcm”算法对node.js 中的有效负载进行加密。 为此,我尝试模仿工作的java加密代码

我尝试过使用 crypto 和 node-forge。 我正在获取输出,但在提交有效负载时收到错误“加密错误 - 有效负载未正确加密”。

请帮我找出我在这段代码中做错的地方。

java 中的工作代码

public void encrypt(@NonNull final byte[] payload, @NonNull final byte[] key) throws GeneralSecurityException
{
    SecretKeySpec codingKey = new SecretKeySpec(key, AES);
    Cipher cipher = AEC_GCM_THREAD_CIPHER.get();
    byte[] iv = new byte[cipher.getBlockSize()];
    RANDOM.nextBytes(iv);

    cipher.init(Cipher.ENCRYPT_MODE, codingKey, new IvParameterSpec(iv));
    final byte[] encryptedPayload = cipher.doFinal(payload);
    byte[] encryptMerchantKey = encryptMerchantKey(key);

    String payloadFinal = encodeToUrlString(encryptedPayload);    // final payload
    String ivFinal =  encodeToUrlString(iv);                  // final iv
    String keyFinal =  encodeToUrlString(encryptMerchantKey);  // final key

    System.out.println("Payload");
    System.out.println(payloadFinal);
    System.out.println("iv");
    System.out.println(ivFinal);
    System.out.println("key");
    System.out.println(keyFinal);
}

代码我在node js中尝试过

function encrypt(payload) {

    let key = forge.random.getBytesSync(16);
    let iv = forge.random.getBytesSync(16);

    let cipher = forge.cipher.createCipher("AES-GCM", key);
    cipher.start({ iv: iv});
    cipher.update(forge.util.createBuffer(payload));
    cipher.finish();

    let encrypted = forge.util.encode64(cipher.output.getBytes());
    let tag = forge.util.encode64(cipher.mode.tag.getBytes());
    let iv64 = forge.util.encode64(iv);

    let encryptedPayload = encrypted+tag;

    //RSA Encryption
    encryptedkey = RSAencrypt(forge.util.encode64(key));

     return {
     "payload" : base64url.fromBase64(encryptedPayload) ,
     "iv" : base64url.fromBase64(iv64).length,
     "key" : base64url.fromBase64(encryptedkey)
     };
}

Rsa 描述工作正常,能够解密 key 。 aes 加密存在一些问题。正如代码所示,我将身份验证标签和加密数据添加在一起,但没有用。

最佳答案

我有 Angular 和 Java 中加密和解密的完整示例,您可以按原样使用此示例并根据您的情况进行更改。
使用命令“npm install node-forge”安装node-forge。

encrypt(msg, pass) {
    const key = CryptoJS.lib.WordArray.random(8).toString();
    const iv =  CryptoJS.lib.WordArray.random(8).toString();

    // encrypt some bytes using GCM mode
    const cipher = forge.cipher.createCipher('AES-GCM', key);
    cipher.start({
        iv: iv, 
         additionalData: 'nvn', // optional
         tagLength: 128 // optional, defaults to 128 bits
    }); 
    cipher.update(forge.util.createBuffer(msg));
    cipher.finish();
    const encrypted = cipher.output;
    const encodedB64 = forge.util.encode64(encrypted.data);
    const tag = cipher.mode.tag; 
    const tagB64 = forge.util.encode64(tag.data);
    // outputs encrypted hex

    const trasmitmsg = key+iv+tagB64+encodedB64;
    return trasmitmsg
}

我使用 CryptoJS 生成随机字符串,因为 Node 伪造的随机数给出了不可转移的字符串。

解密此trasmitmsg的java代码是

public String getDecrypt(String transmsg) throws Exception {
    String keyString = transmsg.substring(0, 16);
    String ivString = transmsg.substring(16, 32);
    String additionalString = transmsg.substring(32, 56);
    String cipherString = transmsg.substring(56);

    byte[] keyBytes = keyString.getBytes();
    SecretKey key = new SecretKeySpec(keyBytes, "AES");
    byte[] ivBytes = ivString.getBytes();

    byte[] one = Base64.getDecoder().decode(cipherString);
    byte[] two = Base64.getDecoder().decode(additionalString);
    byte[] cipherText = ArrayUtils.addAll(one, two);
    return decrypt(cipherText, key, ivBytes);
}

public static String decrypt(byte[] cipherText, SecretKey key, byte[] IV) throws Exception {
    // Get Cipher Instance
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

    // Create SecretKeySpec
    SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");

    // Create GCMParameterSpec
    GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH , IV);

    // Initialize Cipher for DECRYPT_MODE
    cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);

    cipher.updateAAD("nvn".getBytes());
    byte[] decryptedText = cipher.doFinal(cipherText);

    return new String(decryptedText);
}

干杯!!!

关于java - 在 Node js 中通过 AES/GCM/NoPadding 算法使用 key 和 iv 加密有效负载并在 java 中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57611999/

相关文章:

java - 用将元素映射到元素集合来替换多重映射

javascript - 捕捉 webhook node.js

c - EVP 加密核心已转储

node.js - Node/ express : Session Expire Event?

apache-spark - Google Dataproc 集群内加密

php - 两个字符串之间的 sha256 哈希冲突

Java Web 服务,xsd 日期而不是 dateTime

java - 替换测试中的静态变量

java - getResourceStream 无法在 eclipse 中加载新创建的文件

javascript - Node JS - 使用路由器添加更多页面(ejs 模板)