Home > Blockchain >  Java code not able to decrypt the encrypted string of node js
Java code not able to decrypt the encrypted string of node js

Time:10-11

const forge = require('node-forge');

    const json = { number: '9246753466',
            lob:'Prepaid',
            firstName:'Mr. XYZ',
            leadId:'yLWJjN2YtYWVlM2',
            address:
            {
                addressLine1: 'address line 1',
                addressLine2: 'address line 2 ',
                city: 'Delhi',
                pincode: '123456',
            },
        };
    let pk = 'SEC_PRV_KEY';
         let iv = forge.random.getBytesSync(16);
    
    // // (other modes include: ECB, CFB, OFB, CTR, and GCM)
    // // Note: CBC and ECB modes use PKCS#7 padding as default
        const AES_PADDING = "AES/CBC/PKCS5Padding";
        let cipher = forge.cipher.createCipher('AES-CBC', pk.toString('utf-8'));
        cipher.start({ iv });
        //cipher.update(forge.util.createBuffer(AES_PADDING));
        cipher.update(forge.util.createBuffer(JSON.stringify(json), 'utf-8'));
        cipher.finish();
        let encrypted = cipher.output;
    // outputs encrypted hex
        console.log(forge.util.encode64(Buffer.from(cipher.output.data).toString('utf-8')));
        console.log('done');

The above code is for the encryption logic. Below is the decryption logic in java :-

public static final String UTF8 = "UTF-8";
    private static final String AES_PADDING = "AES/CBC/PKCS5Padding";
    public static final String AES = "AES";
    public static String decrypt(String encryptedString, String privateKey) {
            try {
                Cipher cipher = Cipher.getInstance(AES_PADDING);
                cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(privateKey.getBytes(StandardCharsets.
                                UTF_8), AES),
                        new IvParameterSpec(new byte[16]));
                byte[] decryptedText = cipher.doFinal(Base64.decodeBase64(encryptedString));
                return new String(decryptedText);
            } catch (NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException |
                    NoSuchAlgorithmException
                    | InvalidKeyException | InvalidAlgorithmParameterException e) {
                System.out.println(e.getMessage());
                return null;
            }
        }

The first few characters of the decrypted string are not matching with initial input. Can anyone help me figure out what is wrong ? I can't change the java code, but I can change the node js code.

CodePudding user response:

IV stands for "initialization vector", and it's more or less a salt feature: It's not a secret (it doesn't generally matter if others know it. If it did matter, we would call it a 'key' instead). For some crypto algorithms it really doesn't matter, for others, it is crucial that this is unique and random, for example if you're using GCM mode (which has quite a few advantages over CBC).

For AES/CBC it probably doesn't matter, but it's crypto. If I'm wrong, you probably won't know until you're hacked.

At any rate, the usual approach for IVs is as follows:

  • The sender randoms up an IV.
  • The sender sends it, plain text, to the receiver.
  • The communication commences with both parties applying said IV.

If you had done that with keys, that's obviously idiotic (you send the key in plain text first? Yeah, there goes your security), but IVs do not need to be secret.

In your case, the java code just straight up uses all zeroes as IV: new byte[16] creates a new 16-sized byte array with all zeroes and that's passed as an IV.

If you can change the node code only, replicate it: Your node code should also use an all-zeroes IV. Your node code currently randomizes up an IV.

  • Related