简体   繁体   中英

Encrypt payload using a key and iv by AES/GCM/NoPadding algorithm in node js and decrypt in java

I have encrypt the file using node.js and decrypt in JAVA. Decryption is done in JAVA using "AES/GCM/Nopadding" algorithm and it is third party app hence I cannot see the JAVA code. I am encrypting the payload in node.js using "aes-128-gcm" algorithm. for this, I am try mimicking a working java encryption code

I have tried with crypto and node-forge. iam getting the output but am getting an error "Bad encryption - payload is not encrypted properly" when submitting payload.

pleas help me to find what I did wrong in this code.

working code in 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);
}

code iam tried in 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 description is working fine abling to decrypt the key. some problem with aes encryption. as see the code, I added auth tag and encrypted data together but no use.

I have complete example of encryption and decryption in angular and java you can take this example as it is and make changes according to you.
Install node-forge with command "npm install 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
}

I have used CryptoJS to generate random string because random of node-forge giving nontransferable strings.

java code to decrypt this trasmitmsg is

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);
}

Cheers!!!

The problem was with forge buffer it need to convert to node buffer this code is working now. thanks, @Maarten Bodewes for the advice.

function encrypt(payload) {

    //initialize forge random buffer
    var key = forge.random.getBytesSync(16);
    var 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 = cipher.output.data;
    let tag = cipher.mode.tag.data;
    let encryptedLoad = encrypted+tag;

    // node buffer and forge buffer differ, so the forge buffer must be converted to node Buffer            
    iv = Buffer.from(iv, "binary");
    encryptedLoad = Buffer.from(encryptedLoad, "binary");

    //Calling RSA Encryption
    encryptedKey = RSAencrypt(key);

    return {
     "payload" : base64url(encryptedLoad) ,
     "iv" : base64url(iv),
     "key" : base64url.fromBase64(encryptedKey)
     };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM