我们知道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(/\bgzip\b/)){ //:,都叫边界res.setHeader('Content-Encoding','gzip');let gzip = zlib.createGzip();fs.createReadStream(p).pipe(gzip).pipe(res);} else if (encoding.match(/\bdeflate\b/)){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
// ------------ 加盐算法
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字节的秘钥,字节越多越安全
// 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中解释