node ~ zip壓縮 && 檔案加密

渣渣的生存之道發表於2019-03-04

我們知道zip壓縮,檔案加密都是基於http的,下面我用用node實現著幾個功能

zip壓縮/解壓

let zlib = require(`zlib`); // 核心
let path = require(`path`);
let fs = require(`fs`);

// 壓縮流 將1.txt壓縮成1.txt.gz
function gzip(source){ //source檔案目錄
    let gzip = zlib.createGzip(); // 轉化流 可讀可寫
    fs.createReadStream(source).pipe(gzip).pipe(fs.createWriteStream(source+`.gz`)); //讀=>壓縮=>寫新的
}
//gzip(path.join(__dirname, `1.txt`));
//解壓
function ungzip(source) {
    let ungz = zlib.createGunzip();
    fs.createReadStream(source).pipe(ungz).pipe(fs.createWriteStream(path.join(__dirname,path.basename(source,`.gz`))));
}
ungzip(path.join(__dirname, `1.txt.gz`))
複製程式碼

傳送請求的時候會有欄位Accept-Encoding: gzip, deflate, br 支援哪種壓縮方式,
在寫伺服器的時候,瀏覽器會有個欄位,響應頭有Content-Encoding: gzip,瀏覽器會自動以這種方式解壓,下面我們來實現下壓縮功能

let http = require(`http`);
let url=  require(`url`);
let path = require(`path`);
let fs = require(`fs`);
let zlib = require(`zlib`);
let server = http.createServer(function (req,res) {
    let {pathname} = url.parse(req.url,true);
    if(pathname === `/` || pathname === `\`) pathname = `index.html`;
    let p = path.join(__dirname,pathname);
    fs.stat(p,function (err,stat) {
        if(!err){
            let encoding = req.headers[`accept-encoding`];
            if (encoding.match(/gzip/)){   //:,都叫邊界
                res.setHeader(`Content-Encoding`,`gzip`);
                let gzip = zlib.createGzip();
                fs.createReadStream(p).pipe(gzip).pipe(res);
            } else if (encoding.match(/deflate/)){
                res.setHeader(`Content-Encoding`, `bdeflate`);
                let deflate = zlib.createDeflate();
                fs.createReadStream(p).pipe(deflate).pipe(res);
            }else{
                fs.createReadStream(p).pipe(res);//不支援就原封不動的返還給客戶端
            }
        }else{
          res.end();
        }
    })
})
server.listen(3000);
複製程式碼

檔案加密

加密的過程是可逆的,但是MD5是不可逆的,加密有很多演算法,例如對稱加密,非對稱加密(https),簽名等,這種演算法一般都是node內建的(crypto),這裡我們只說用法

crypto crypto是node.js中實現加密和解密的模組 在node.js中,使用OpenSSL類庫作為內部實現加密解密的手段 OpenSSL是一個經過嚴格測試的可靠的加密與解密演算法的實現工具

雜湊(雜湊)演算法 加鹽演算法

雜湊演算法也叫雜湊演算法,用來把任意長度的輸入變換成固定長度的輸出,常見的有md5,sha1等

let crypto = require(`crypto`); // 常見的加密模組
// console.log(crypto.getHashes());
//1)md5 其實不叫加密 ,叫摘要演算法, 特點不可逆,輸出結果長度相等,內容不同輸出的結果就不同,反之相同

let md5 = crypto.createHash(`md5`) // 建立一個演算法,經常用這種方式傳檔案
md5.update(`123456`); // update加密 把哪段文字加密
let result1 = md5.digest(`hex`);//base64/hex16進位制
let md52 = crypto.createHash(`md5`) // 建立一個演算法,經常用這種方式傳檔案
md52.update(`1234567`); // update加密 把哪段文字加密
let result = md52.digest(`base64`);//base64/hex16進位制
// 如果存的是密碼 多次加密。 拖庫
複製程式碼
//缺點  加密檔案,會把檔案讀取到記憶體中,在檔案很大的時候一般分段讀,
let fs = require(`fs`);
let str = fs.readFileSync(__dirname+`/index.html`,`utf8`);
let md53 = crypto.createHash(`md5`);
md53.update(str);
let result2 = md53.digest(`hex`);
console.log(result2);

//客戶端第二次請求檔案,伺服器會先判斷加密是否一致,如果一致會返回304從快取中讀取,
let md54 = crypto.createHash(`md5`);
let rs = fs.createReadStream(__dirname + `/index.html`,{highWaterMark:3});
rs.on(`data`,function (data) {
      md54.update(data); // update可以呼叫多次 data是buffer
});
rs.on(`end`, function (data) {
    console.log(md54.digest(`hex`));
})
複製程式碼

HMAC演算法

可用的摘要演算法,例如 sha1、md5、sha256

node ~ zip壓縮 && 檔案加密
// ------------ 加鹽演算法
let crypto = require(`crypto`);
let hmac = crypto.createHmac(`sha1`, `zdl`); //加zdl的味道zdl為一個字串,用於指定一個PEM格式的金鑰,PEM不同生成的祕鑰也不同
hmac.update(`123456`);
let result = hmac.digest(`hex`);
console.log(result);
複製程式碼

但是以上客戶端傳送給乙方的時候還是會不安全,在傳送的過程中有可能被劫持,我們可以用openssl genrsa -out rsa_private.key 1024
生成1024位元組的祕鑰,位元組越多越安全

node ~ zip壓縮 && 檔案加密
// PEM是OpenSSL的標準格式,OpenSSL使用PEM檔案格式儲存證照和金鑰,是基於Base64編碼的證照。
let fs = require(`fs`);
let pem  = fs.readFileSync(__dirname+`/rsa_private.key`);
let key = pem.toString(`ascii`);
let hmac = crypto.createHmac(`sha1`, key);
hmac.update(`zdl`);
let result = hmac.digest(`hex`);
console.log(result);
複製程式碼

對稱加密

blowfish演算法是一種對稱的加密演算法,對稱的意思就是加密和解密使用的是同一個金鑰。

缺點:對,名字有限制,最多接受14個字元

let crypto = require(`crypto`);
let fs = require(`fs`);
let key = fs.readFileSync(__dirname + `/rsa_private.key`)
let cipher = crypto.createCipher(`blowfish`, key);
cipher.update(`zdl`);
let result = cipher.final(`hex`);
console.log(result);

//解密
let deciper = crypto.createDecipher(`blowfish`, key);
// 告訴他剛才加密的是hex
deciper.update(result,`hex`);
let r = deciper.final(`utf8`);
console.log(r);
複製程式碼

非對稱加密

公鑰加密私鑰解密

算公鑰 openssl rsa -in rsa_private.key -pubout -out rsa_public.key

// 非對稱加密
let crypto = require(`crypto`);
let fs = require(`fs`);
let public = fs.readFileSync(__dirname+`/rsa_public.key`,`utf8`);
let private = fs.readFileSync(__dirname +`/rsa_private.key`,`utf8`);
let result = crypto.publicEncrypt(public, Buffer.from(`hello`));
let r = crypto.privateDecrypt(private, result);
console.log(r.toString());
複製程式碼

相對安全,如果客戶端給服務端加個憑證,這種情況需要加密後傳送,,之前可能寫個演算法,把當前字串前幾個後幾個取出來中間做排序,然後拼回去,每段時間換一次~~~

簽名會在cookie中解釋

相關文章