簡體   English   中英

使用node.js中的crypto進行aes-128-cbc加密/解密不會產生與Java代碼相似的結果

[英]aes-128-cbc encrytion/decryption using crypto in node.js not giving same result as similar to java code

我正在使用第三方API,在該API中,我必須以aes-128加密形式發送數據。 為了幫助您進行加密/解密,他們給了我Java代碼。 我試圖在Node.js中復制它,但是我無法應用與普通Java代碼相同的加密,因此我遇到了錯誤。

Java中的工作代碼是-

public class AesCryptUtil {
    Cipher ecipher;
    /**
     * Input a string that will be md5 hashed to create the key.
     * 
     * @return void, cipher initialized
     */
    public AesCryptUtil() {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128);
            this.setupCrypto(kgen.generateKey());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public AesCryptUtil(String key) {
        SecretKeySpec skey = new SecretKeySpec(getMD5(key), "AES");
        this.setupCrypto(skey);
    }

    private void setupCrypto(SecretKey key) {
        // Create an 8-byte initialization vector
        byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
        try {
            ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            // CBC requires an initialization vector
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Buffer used to transport the bytes from one stream to another
    byte[] buf = new byte[1024];

    public void encrypt(InputStream in, OutputStream out) {
        try {
            // Bytes written to out will be encrypted
            out = new CipherOutputStream(out, ecipher);

            // Read in the cleartext bytes and write to out to encrypt
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
/**
     * Input is a string to encrypt.
     * 
     * @return a Hex string of the byte array
     */
    public String encrypt(String plaintext) {
        try {
            byte[] ciphertext = ecipher.doFinal(plaintext.getBytes("UTF-8"));
            return this.byteToHex(ciphertext);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }


    /**
     * Input encrypted String represented in HEX
     **/

    private static byte[] getMD5(String input) {
        try {
            byte[] bytesOfMessage = input.getBytes("UTF-8");
            MessageDigest md = MessageDigest.getInstance("MD5");
            return md.digest(bytesOfMessage);
        } catch (Exception e) {
            return null;
        }
    }

    static final String HEXES = "0123456789ABCDEF";

    public static String byteToHex(byte[] raw) {
        if (raw == null) {
            return null;
        }
        String result = "";
        for (int i = 0; i < raw.length; i++) {
            result += Integer.toString((raw[i] & 0xff) + 0x100, 16).substring(1);
        return result;
    }

    public static byte[] hexToByte(String hexString) {
        int len = hexString.length();
        byte[] ba = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            ba[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return ba;
    }

    public static void main(String args[]) {
        String result = null;
        String err = null;
        String key = "DEEA29E294D8B2241FB41EF254AAB86F";
        String data = "<?xml version=" + "1.0" + " encoding=" + "UTF-8" + "?><xmltagopen></xmltagclose>";
        String action = "enc";

        if (key == null)
            err = "error: no key";
        else if (key.length() < 32)
            err = "error: key length less than 32 bytes";
        else if (data == null || action == null)
            err = "error: no data";
        else if (action == null)
            err = "error: no action";
        else if (!action.equals("enc") && !action.equals("dec"))
            err = "error: invalid action";

        if (err == null) {
            try {
                AesCryptUtil encrypter = new AesCryptUtil(key);

                if (action.equals("enc"))
                    result = encrypter.encrypt(data);
                else
                    result = encrypter.decrypt(data);
            } catch (Exception e) {
                err = "error : Exception in performing the requested operation : " + e;
            }
        }
        if (result != null)
            System.out.println(result);
        else
            System.out.println(err);
    }

}

我試圖在node.js中做類似的操作,但是它不起作用,並且我從api中收到錯誤消息,提示加密不正確-

const xml = '<?xml version="1.0" encoding="UTF-8"?><xmltagopen</xmltagclose>';
    let key = 'DEEA29E294D8B2241FB41EF254AAB86F';
    let encodeKey = crypto.createHash('md5').update(key, 'utf8').digest("hex");
    console.log(encodeKey);
    let ivBuffer = new Buffer.from([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]);
    let iv = ivBuffer.toString('hex');

    let cipher = crypto.createCipher('aes-128-cbc', encodeKey, iv);
    let encText = cipher.update(xml, 'utf8', 'hex');
    encText += cipher.final('hex');
    console.log(encText);

如API文檔中所述,已棄用的crypto.createCipher函數從提供的密碼中獲取加密密鑰:

crypto.createCipher()的實現使用OpenSSL函數EVP_BytesToKey來導出密鑰,且摘要算法設置為MD5,一次迭代,並且沒有salt 缺少鹽會使字典受到攻擊,因為相同的密碼始終會創建相同的密鑰。 低迭代次數和非加密安全的哈希算法可以非常快速地測試密碼。

請改用crypto.createCipheriv

例如這樣:

var crypto  = require( 'crypto' );
var encryptionKey = Buffer.from('DEEA29E294D8B2241FB41EF254AAB86F', 'hex');
var iv = Buffer.from([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]);
// better: var iv = crypto.randomBytes(16);
var cipher  = crypto.createCipheriv( 'aes-128-cbc', encryptionKey, iv );
var buf1 = cipher.update( Buffer.from(data) );
var buf2 = cipher.final();
var encrypted = Buffer.concat([buf1, buf2]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM