·起因
汉字编码技术在实际应用中总是会存在这样或者那样的问题,尤其是在一些热门NoSQL方面多少会遇到挑战。比方说Cassandra字符集还不直接支持GB2312,要想存储写汉字那可真是麻烦。当然这还不算什么,原来以为的CRYPTO值得欣喜,当字符集遇上加解密时会更加痛苦,下面笔者会例举几个文本来对此进行说明。
·原理
关于对称加密技术:NodeJS算是比较亲民的,官网给了很多模块,唯独缺少经典的RSA,给了一个对称加密。但严格说来不是一项安全的加密技术,如果秘钥落在别人手里基本完蛋,所以还是RSA的公私钥组合是王道。但这不是本文的重点。
关于汉字入库或加密:编码三贱客,GB2312(GBK)/Unicode/UTF-8。剪不清理还乱,再碰上SecureCRT、.vimrc、profile基本上一团浆糊。在实际的应用中最头痛的问题就是想把汉字入到Cassandra/MongoDB中.先用一张图简示三贱客的关系。 最大的特点在于2字节与3字节的解读。对于大多数的系统和开源软件来说UTF-8是首选,即便像Node这样的好平台,也只有ASCII,UTF-8,BINARY可选,这就导致了在LINUX环境下我们无论是直接将中文入库还是加解密必然会出现各种乱码或"锟斤拷"。不过好在还有ICONV或者NATIVE2ASCII这样的好工具可以助我们一臂之力,可惜的是直接使用这些工具涉及到磁盘读写,还需要各位在真正处理流计算时要自己加工一下。下面结合使用编码处理和加解密来重新剖析这一过程。
·实验开始
SecureCRT的Apperance的char encoding选default;
.vimrc的中增加配置项set fileencodings=ucs-bom,utf-8,cp936;
.bash_profile增加配置项export LANG=zh_CN.gb2312;
--->编辑文件code.txt,输入"abc我"。用Iconv开始转换
iconv -f gb2312 -t utf-8 code.txt > code.txt.utf-8
iconv -f gb2312 -t unicode code.txt > code.txt.unicode
mv code.txt code.txt.gb2312
--->查看这3个文件,由于编码不同已经出现了乱码。
---> 加密这3个文件,得到如下结果。
1
//NodeJS ENCRPT
2
var filename = process.argv[2];
3
var codetype = process.argv[3];
4
5
/**
6
* * Created by Administrator on 14-1-31.
7
* */
8
9
10
/**
11
* * Created by Administrator on 14-1-31.
12
* */
13
14
var fs=require('fs');
15
var cc=new Array();
16
17
var aa='';
18
var s = fs.ReadStream(filename,{encoding:'utf-8'});
19
20 s.on('data', function(d) {
21 aa+=d;
22
});
23
24 s.on('end',function(){
25 cc=aa.split("
");
26
//console.log(cc[0]);
27 pptxt=enp(cc[0]);
28
// dep(pptxt);
29
});
30
31
function enp(txt){
32
var crypto = require('crypto');
33
var fsf = require('fs');
34
35
var pem = fsf.readFileSync('server.pem');
36
var key = pem.toString('ascii');
37
var cipher = crypto.createCipher('aes-256-cbc',key);
38
var crymsg = cipher.update(txt,codetype,'hex');
39 crymsg += cipher.final('hex');
40
console.log(crymsg);
41
return crymsg;
42 }
aa041-cipher.js
1
//NodeJS DECRYPT
2
var filename = process.argv[2];
3
var codetype= process.argv[3];
4
5
/**
6
* * Created by Administrator on 14-1-31.
7
* */
8
9
10
/**
11
* * Created by Administrator on 14-1-31.
12
* */
13
14
var fs=require('fs');
15
var cc=new Array();
16
17
var aa='';
18
var s = fs.ReadStream(filename,{encoding:'utf-8'});
19
20 s.on('data', function(d) {
21 aa+=d;
22
});
23
24 s.on('end',function(){
25 cc=aa.split("
");
26
//console.log(cc[0]);
27 pptxt=dep(cc[0]);
28
// dep(pptxt);
29
});
30
/*
31
function enp(txt){
32
var crypto = require('crypto');
33
var fsf = require('fs');
34
35
var pem = fsf.readFileSync('server.pem');
36
var key = pem.toString('ascii');
37
var cipher = crypto.createCipher('aes-256-cbc',key);
38
var crymsg = cipher.update(txt,'utf-8','hex');
39
crymsg += cipher.final('hex');
40
console.log(crymsg);
41
return crymsg;
42
}
43
*/
44
45
function dep(entxt){
46
var crypto = require('crypto');
47
var fsf = require('fs');
48
49
var pem = fsf.readFileSync('server.pem');
50
var key = pem.toString('ascii');
51
var decipher = crypto.createDecipher('aes-256-cbc',key);
52
var decrymsg=decipher.update(entxt,'hex',codetype);
53
54 decrymsg+=decipher.final(codetype);
55
console.log(decrymsg);
56
return decrymsg;
57 }
aa042-decpher.js
node aa041-cipher.js code.txt.gb2312 binary或者utf-8 > code.txt.gb2312.enp
node aa041-cipher.js code.txt.unicode binary或者utf-8 > code.txt.unicode.enp
node aa041-cipher.js code.txt.utf-8 binary或者utf-8 > code.txt.utf-8.enp
看似成功的加密,其实却暗藏杀机。如果对称解密都不可逆,那更不谈RSA了。所以我们重新开始解密看看,能否还原,凡是能还原的一定支持各类NoSQL,凡是不能还原的必然是万年坑洞。同时我们也想NodeJS不会热情到帮开发根据系统环境自动转换编码。
--->解密这3个文件,查看下结果。发现gb2312和unicode都吃了"锟斤拷"的憋(编码不符合规则,被自动填充,再强匹配GB2312的结果),唯独utf-8屹立不倒。
node aa042-depher.js code.txt.gb2312.enp binary或者utf-8 > code.txt.gb2312.enp.dep
node aa042-depher.js code.txt.unicode.enp binary或者utf-8 > code.txt.unicode.enp.dep
node aa042-depher.js code.txt.utf-8.enp binary或者utf-8 > code.txt.utf-8.enp.dep
·结论
更多的时候,我们在处理流体时,需要注意判断转换下,目前看来用iconv从gb2312转utf8算是一个比较屌丝的百试百灵的方法,网上也有很多的这样的模块。眼下的国内的IT环境大多还在向温饱和房子奋斗,等哪天像美帝那样有闲情逸致了,出几个NB的产品,把UTF-8统统换掉,哈哈哈。