简体   繁体   English

NodeJs 中的 AES/CBC/PKCS5Padding

[英]AES/CBC/PKCS5Padding in NodeJs

I am trying to convert my java code to NodeJs code.我正在尝试将我的 java 代码转换为 NodeJs 代码。
Facing some issues on the encryptions.面临一些关于加密的问题。
Here is my java code: compiled code这是我的 java 代码:编译代码

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.Base64;

public class AESCBCPKCS5Encryption {
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    public static String encrypt(String message, String key) throws GeneralSecurityException, UnsupportedEncodingException {
        if (message == null || key == null) {
            throw new IllegalArgumentException("text to be encrypted and key should not be null");
        }
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        byte[] messageArr = message.getBytes();
        SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
        byte[] ivParams = new byte[16];
        byte[] encoded = new byte[messageArr.length + 16];
        System.arraycopy(ivParams, 0, encoded, 0, 16);
        System.arraycopy(messageArr, 0, encoded, 16, messageArr.length);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivParams));
        byte[] encryptedBytes = cipher.doFinal(encoded);
        encryptedBytes = Base64.getEncoder().encode(encryptedBytes);
        return new String(encryptedBytes);
    }

    public static String decrypt(String encryptedStr, String key) throws GeneralSecurityException, UnsupportedEncodingException {
        if (encryptedStr == null || key == null) {
            throw new IllegalArgumentException("text to be decrypted and key should not be null");
        }
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        SecretKeySpec keySpec = new
                SecretKeySpec(Base64.getDecoder().decode(key), "AES");
        byte[] encoded = encryptedStr.getBytes();
        encoded = Base64.getDecoder().decode(encoded);
        byte[] decodedEncrypted = new byte[encoded.length - 16];
        System.arraycopy(encoded, 16, decodedEncrypted, 0, encoded.length - 16);
        byte[] ivParams = new byte[16];
        System.arraycopy(encoded, 0, ivParams, 0, ivParams.length);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivParams));
        byte[] decryptedBytes = cipher.doFinal(decodedEncrypted);
        return new String(decryptedBytes);
    }

    public static void main(String[] args) throws GeneralSecurityException, UnsupportedEncodingException {
        String str = "<Request xmlns=\"http://www.kotak.com/schemas/CorpCCPaymentsOTP/CorpCCPaymentsOTP.xsd\" ><username>ENKASH</username><password>Corp@123</password><SrcAppCd>ENKA SH</SrcAppCd><RefNo>Ref1111111111</RefNo><CardNo>4280933990002698</CardNo ><OTP>12345</OTP></Request>";
        String key = "e3a74e3c7599f3ab4601d587bd2cc768";
        String enc = encrypt(str, key);
        System.out.println(enc);
        String dec = decrypt(enc, key);
        System.out.println(dec);
    }
}

Here is my javascript code:这是我的 javascript 代码:

var crypto = require('crypto');

function getAlgorithm(keyBase64) {

    var key = Buffer.from(keyBase64, 'base64');
    switch (key.length) {
        case 16:
            return 'aes-128-cbc';
        case 32:
            return 'aes-256-cbc';

    }

    throw new Error('Invalid key length: ' + key.length);
}


function encrypt(plainText, keyBase64, ivBase64) {

    const key = Buffer.from(keyBase64, 'base64');
    const iv  = Buffer.from(ivBase64, 'base64');

    const cipher  = crypto.createCipheriv(getAlgorithm(keyBase64), key, iv);
    let encrypted = cipher.update(plainText, 'utf8', 'base64');
    encrypted += cipher.final('base64');
    return encrypted;
}

function decrypt(messagebase64, keyBase64, ivBase64) {

    const key = Buffer.from(keyBase64, 'base64');
    const iv  = Buffer.from(ivBase64, 'base64');

    const decipher = crypto.createDecipheriv(getAlgorithm(keyBase64), key, iv);
    let decrypted  = decipher.update(messagebase64, 'base64');
    decrypted += decipher.final();
    return decrypted;
}


var keyBase64 = "DWIzFkO22qfVMgx2fIsxOXnwz10pRuZfFJBvf4RS3eY=";
var ivBase64  = 'e3a74e3c7599f3ab4601d587bd2cc768';
var plainText = '<Request xmlns="http://www.kotak.com/schemas/CorpCCPaymentsOTP/CorpCCPaymentsOTP.xsd"><username>ENKASH</username><password>Corp@123</password><SrcAppCd>ENKA SH</SrcAppCd><RefNo>Ref1111111111</RefNo><CardNo>4280933990002698</CardNo ><OTP>12345</OTP></Request>';

var cipherText          = encrypt(plainText, keyBase64, ivBase64);
var decryptedCipherText = decrypt(cipherText, keyBase64, ivBase64);

console.log('Algorithm: ' + getAlgorithm(keyBase64));
console.log('Plaintext: ' + plainText);
console.log('Ciphertext: ' + cipherText);
console.log('Decoded Ciphertext: ' + decryptedCipherText);

Encryptions throwing errors,加密抛出错误,
What I am doing wrong here?我在这里做错了什么?

Initialization vector length of AES in CBC mode is 16 Bytes, code in JAVA takes first 16 bytes of IV however for node.js code it uses all 24 bytes of IV, hence an error. CBC模式下AES初始化向量长度为​​ 16 字节,JAVA 中的代码占用IV前 16 个字节,但是对于 node.js 代码,它使用 IV 的所有 24 个字节,因此出现错误。 try this code试试这个代码

var crypto = require('crypto');

function getAlgorithm(keyBase64) {

    var key = Buffer.from(keyBase64, 'base64');
    switch (key.length) {
        case 16:
            return 'aes-128-cbc';
        case 32:
            return 'aes-256-cbc';

    }

    throw new Error('Invalid key length: ' + key.length);
}


function encrypt(plainText, keyBase64, ivBase64) {

    const key = Buffer.from(keyBase64, 'base64');
    const iv  = Buffer.from(ivBase64, 'base64');

    const cipher  = crypto.createCipheriv(getAlgorithm(keyBase64), key, iv.slice(0, 16));
    let encrypted = cipher.update(plainText, 'utf8', 'base64');
    encrypted += cipher.final('base64');
    return encrypted;
}

function decrypt(messagebase64, keyBase64, ivBase64) {

    const key = Buffer.from(keyBase64, 'base64');
    const iv  = Buffer.from(ivBase64, 'base64');

    const decipher = crypto.createDecipheriv(getAlgorithm(keyBase64), key, iv.slice(0, 16));
    let decrypted  = decipher.update(messagebase64, 'base64');
    decrypted += decipher.final();
    return decrypted;
}


var keyBase64 = "DWIzFkO22qfVMgx2fIsxOXnwz10pRuZfFJBvf4RS3eY=";
var ivBase64  = 'e3a74e3c7599f3ab4601d587bd2cc768';
var plainText = '<Request xmlns="http://www.kotak.com/schemas/CorpCCPaymentsOTP/CorpCCPaymentsOTP.xsd"><username>ENKASH</username><password>Corp@123</password><SrcAppCd>ENKA SH</SrcAppCd><RefNo>Ref1111111111</RefNo><CardNo>4280933990002698</CardNo ><OTP>12345</OTP></Request>';

var cipherText          = encrypt(plainText, keyBase64, ivBase64);
var decryptedCipherText = decrypt(cipherText, keyBase64, ivBase64);

console.log('Algorithm: ' + getAlgorithm(keyBase64));
console.log('Plaintext: ' + plainText);
console.log('Ciphertext: ' + cipherText);
console.log('Decoded Ciphertext: ' + decryptedCipherText);

in java key converted in 16 byte so 'AES/CBC/PKCS5Padding' algo applied while in nodejs this is convered into 24 byte so we need to apply 'aes-192-cbc'.在 Java 中,密钥转换为 16 字节,因此应用了“AES/CBC/PKCS5Padding”算法,而在 nodejs 中,这被转换为 24 字节,因此我们需要应用“aes-192-cbc”。

var crypto = require('crypto');

const encrypt = (plainText, keyBase64) =>{

    const textBuffer = Buffer.from(plainText);
    const key = Buffer.from(keyBase64, 'base64');
    var iv = Buffer.from([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
    var encoded = Buffer.concat([iv,textBuffer]);
    const cipher = crypto.createCipheriv('aes-192-cbc', key, iv);
    let encrypted = cipher.update(encoded, 'binary', 'base64')
    encrypted += cipher.final('base64');
    return encrypted;
};

const decrypt =  (messagebase64, keyBase64) =>{

    const key = Buffer.from(keyBase64, 'base64');
    const encoded = Buffer.from(messagebase64, 'base64');
    var iv = encoded.slice(0, 16);
    var decoded = encoded.slice(16,encoded.length);
    const decipher = crypto.createDecipheriv('aes-192-cbc', key, iv);
    let decrypted = decipher.update(decoded, 'binary','utf-8');
    decrypted += decipher.final();
    return decrypted;
}



 String str = "<Request xmlns=\"http://www.kotak.com/schemas/CorpCCPaymentsOTP/CorpCCPaymentsOTP.xsd\" ><username>ENKASH</username><password>Corp@123</password><SrcAppCd>ENKA SH</SrcAppCd><RefNo>Ref1111111111</RefNo><CardNo>4280933990002698</CardNo ><OTP>12345</OTP></Request>";

String key = "e3a74e3c7599f3ab4601d587bd2cc768";

console.log("input:   "+str);
const hash = encrypt(str,key);
console.log("encrypted:::   " + hash);
const text = decrypt(hash,key);
console.log("output:   "+text); 

This is the solution for the above issue.这是上述问题的解决方案。 I was getting the decryption error whenever I encrypt using the above code.每当我使用上面的代码加密时,我都会收到解密错误。 I made a small update in the code by adding 16 characters at the start of plain text while encrypting.我通过在加密时在纯文本开头添加 16 个字符对代码进行了小幅更新。

 var crypto = require('crypto'); function getAlgorithm(keyBase64) { var key = Buffer.from(keyBase64, 'base64'); switch (key.length) { case 16: return 'aes-128-cbc'; case 32: return 'aes-256-cbc'; } throw new Error('Invalid key length: ' + key.length); } function encrypt(plainText, keyBase64, ivBase64) { const key = Buffer.from(keyBase64, 'base64'); const iv = Buffer.from(ivBase64, 'base64'); const cipher = crypto.createCipheriv(getAlgorithm(keyBase64), key, iv); let encrypted = cipher.update(iv.subarray(0, 16) + plainText, 'utf8', 'base64') encrypted += cipher.final('base64'); return encrypted; }; function decrypt(messagebase64, keyBase64, ivBase64) { const key = Buffer.from(keyBase64, 'base64'); const iv = Buffer.from(ivBase64, 'base64'); const decipher = crypto.createDecipheriv(getAlgorithm(keyBase64), key, iv); let decrypted = decipher.update(messagebase64, 'base64'); decrypted += decipher.final(); return decrypted; } var keyBase64 = "DWIzFkO22qfVMgx2fIsxOXnwz10pRuZfFJBvf4RS3eY="; var ivBase64 = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).toString('base64');; var plainText = '<Request xmlns="http://www.kotak.com/schemas/CorpCCPaymentsOTP/CorpCCPaymentsOTP.xsd"><username>ENKASH</username><password>Corp@123</password><SrcAppCd>ENKA SH</SrcAppCd><RefNo>Ref1111111111</RefNo><CardNo>4280933990002698</CardNo ><OTP>12345</OTP></Request>'; var cipherText = encrypt(plainText, keyBase64, ivBase64); var decryptedCipherText = decrypt(cipherText, keyBase64, ivBase64); console.log('Algorithm: ' + getAlgorithm(keyBase64)); console.log('Plaintext: ' + plainText); console.log('Ciphertext: ' + cipherText); console.log('Decoded Ciphertext: ' + decryptedCipherText);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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