1. 程式人生 > >node.js AES/ECB/PKCS5Padding 與其他語言的加密解密通用

node.js AES/ECB/PKCS5Padding 與其他語言的加密解密通用

轉載:http://yijiebuyi.com/blog/13e2ae33082ac12ba4946b033be04bb5.html


關於什麼是AES? 需要自己goole瞭解一下,今天就是簡單和大家分享node.js下使用 AES/ECB/PKCS5Padding 如何與其他語言通用加密解密.

就像你的介面是node.js提供服務,而第三方平臺是其他伺服器端語言開發,比如php ,在第三方平臺請求你的介面可能需要sign驗證,假設我們使用了AES/ECB/PKCS5Padding  加密.

AES/ECB/PKCS5Padding  斜線分隔的3部分分別是 演算法/模式/填充量

AES加密包括不同的模式,已經後面是否有填充量(為什麼有填充量,就像我們引用的圖片,一個AES塊是16個位元組,如果不滿16的時候要不要填充?)

演算法/模式/填充                16位元組加密後資料長度        不滿16位元組加密後長度

AES/CBC/NoPadding             16                                  不支援

AES/CBC/PKCS5Padding          32                                  16

AES/CBC/ISO10126Padding       32                              16

AES/CFB/NoPadding             16                              原始資料長度

AES/CFB/PKCS5Padding          32                                  16

AES/CFB/ISO10126Padding       32                              16

AES/ECB/NoPadding             16                                  不支援

AES/ECB/PKCS5Padding          32                              16

AES/ECB/ISO10126Padding       32                              16

AES/OFB/NoPadding             16                              原始資料長度

AES/OFB/PKCS5Padding          32                              16

AES/OFB/ISO10126Padding       32                              16

AES/PCBC/NoPadding            16                              不支援

AES/PCBC/PKCS5Padding         32                              16

AES/PCBC/ISO10126Padding      32                          16

看上面的列表可以知道aes加密後要麼16要麼32位(前提是大於16位元組)

有先模式是不支援對於不滿16位元組字串的加密,見上面列表最後一列 (不支援)

如果不滿16位元組且支援加密的模式,一定是有填充量的,就是不滿16的位元組用一個預設值來填充,直到它滿16位後再加密.

這個填充量你可以指定,大部分語言預設有一種預設補充量,但是node.js是沒有的,就是說當你不足16位時,自己又沒有指定填充量,那麼node.js語言本身預設不補全填充量.

AES/ECB/PKCS5Padding,我們用這個模式來說一下.

node.js自帶加密解密模組 

var crypto = require('crypto');

可以看出此模組暴露了很多方法(下面還有一部分未被截圖的)

如果你已經google找了半天關於node.js aes加密和其他語言不通用的時候.

第一檢查你是不是用了下面的加密函式.

createCipher加密函式不支援填充量,你需要的是 createCipheriv

直觀的你可以看到多了一個 iv ,沒錯,這個方法與上一個不同的就是支援填充量 iv

直接見下面程式碼:

//data 是準備加密的字串,key是你的金鑰
function encryption(data, key) {
    var iv = "";
    var clearEncoding = 'utf8';
    var cipherEncoding = 'base64';
    var cipherChunks = [];
    var cipher = crypto.createCipheriv('aes-128-ecb', key, iv);
    cipher.setAutoPadding(true);

    cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
    cipherChunks.push(cipher.final(cipherEncoding));

    return cipherChunks.join('');
}
//data 是你的準備解密的字串,key是你的金鑰
function decryption(data, key) {
    var iv = "";
    var clearEncoding = 'utf8';
    var cipherEncoding = 'base64';
    var cipherChunks = [];
    var decipher = crypto.createDecipheriv('aes-128-ecb', key, iv);
    decipher.setAutoPadding(true);

    cipherChunks.push(decipher.update(data, cipherEncoding, clearEncoding));
    cipherChunks.push(decipher.final(clearEncoding));

    return cipherChunks.join('');
}

上面的加密,解密函式 createCipheriv ,createDecipheriv 支援3個引數,最後一個引數iv就是填充量,我們使用了空字串.

這樣加密後和其他語言此模式下的加密串一直,相互解密也是沒有問題的.

給檔案AES加密,以及base64字串轉化為檔案

//傳檔案路徑和 加密 key, 返回加密base64字串.
function encryption_file(file_path, key) {
    var iv = "";
    var clearEncoding = 'binary';
    var cipherEncoding = 'base64';
    var cipherChunks = [];
    var cipher = crypto.createCipheriv('aes-128-ecb', key, iv);
    cipher.setAutoPadding(true);

    var buf = fs.readFileSync(file_path);
    cipherChunks.push(cipher.update(buf, clearEncoding, cipherEncoding));
    cipherChunks.push(cipher.final(cipherEncoding));
    return cipherChunks.join('');
}

//傳base64加密串和加密key ,返回直接陣列,將位元組陣列轉化為檔案儲存即可
function decryption_file(file_base64, key) {
    var iv = "";
    var clearEncoding = 'binary';
    var cipherEncoding = 'base64';
    var cipherChunks = [];
    var cipher = crypto.createCipheriv('aes-128-ecb', key, iv);
    cipher.setAutoPadding(true);

    cipherChunks.push(cipher.update(file_base64, cipherEncoding,clearEncoding));
    cipherChunks.push(cipher.final(clearEncoding));

    return cipherChunks;
}