您的位置:首页 > Web前端 > JavaScript

erlang大坑——加密和字符串处理

2016-03-22 21:56 459 查看

1、问题描述

因业务要求,需要对指定的http请求内容进行RSA签名,并且将签名结果和请求内容用json格式打包。这里包括两个需要处理的点:1、用RSA私钥签名;2、把http请求json化。

2、处理签名

目前项目使用的erlang版本是17.0,这个版本有专门针对RSA的库即public_key,但是查看public_key相关描述
sign(Msg, DigestType, Key) -> binary()

Types:

Msg = binary() | {digest,binary()}
The msg is either the binary "plain text" data to be signed or it is the hashed value of "plain text" i.e. the digest.
DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()
Key = rsa_private_key() | dsa_private_key() | ec_private_key()
Creates a digital signature.

明显,参数需要rsa_private_key()类型参数,参数定义

-record('RSAPrivateKey',{
version, modulus, publicExponent, privateExponent, prime1, prime2, exponent1, exponent2, coefficient, otherPrimeInfos = asn1_NOVALUE}).
对于只有privatekey而没有生成key的两个素数的应用场景来说,这个库就是渣,感觉并没有什么卵用。其他方案?java和c++应该是有对应的库的,erlang中也存在调用java和c++库的方法,两种方案区别如下:

1、java。erlang中有jinterface用来调用java,对于erlang来说,jinterface类似于启动一个新的节点,erlang连接该节点之后可以向该节点发送和接受消息,以此来请求RSA签名和接受签名结果。优点:可以使用庞大的java库。缺点:慢,毕竟需要跨节点通信;麻烦,新增一个节点,特别对于分布式环境,还要防止节点之间自动连接等等。

2、c++。erlang中有nif机制对应调用C++,C++方法可以单独运行在一个节点,也可以和erlang在同一个节点,但是一般不会单独分开一个节点,因为单独在一个节点会遇到和jinterface一样的困难——慢,麻烦。优点:快,顺序运算速度是erlang的7倍。缺点:不安全,发生异常会直接导致节点挂掉,并且没有任何征兆。

综上,结合应用场景,由于不需要大量请求签名,使用方案1虽然比较慢应该也不会卡住主流程,并且解密方是使用java解密,用java可以省去很多编码之类的问题。jinterface使用流程参考http://erlang.org/doc/apps/jinterface/jinterface_users_guide.html,以下为java代码

OtpNode node = new OtpNode("g35_java@127.0.0.1", "g35_java"); //启动节点
OtpMbox mbox = node.createMbox();        //创建消息队列
mbox.registerName("java");            //注册名称
int flag = 1;
while (flag == 1) {
try {
OtpErlangObject o;
OtpErlangTuple msg;
OtpErlangPid from;
o = mbox.receive();       //收取请求
if (o instanceof OtpErlangTuple) {
msg = (OtpErlangTuple)o;
from = (OtpErlangPid)(msg.elementAt(0));      //
//字符片段1
OtpErlangString content = (OtpErlangString)msg.elementAt(1);
String contentString = convertErlangString(content);      //字符串转换
String sign = RSASignature.sign(signString);        //数字签名
OtpErlangObject returnSign = new OtpErlangString(sign);        //返回结果
mbox.send(from, returnSign);
}
需要注意的是,erlang的String在java中是OtpErlangString,这个结构直接使用是错误的,需要经过转换。

3、erlang转换json

erlang转换成json已经有很强大的库,例如mochijson之类,然而对于字符串处理能力奇差的erlang来说,转换json还是存在很多坑。例如
(db_20001_1@127.0.0.1)9> io:format("~ts", [common_json2:to_json([{name, "123"}, {age, 24}])]).
{"name":"123","age":24}ok
看起来是符合json规范的,但是如果用这个字符串进行网络传输就不行了,原因如下
(db_20001_1@127.0.0.1)11> io:format("~w", [common_json2:to_json([{name, "123"}, {age, 24}])]).
[123,[34,[110,97,109,101],34],58,[34,<<49,50,51>>,34],44,[34,[97,103,101],34],58,[50,52],125]ok
即实际得出的json串是各种类型的erlang数据拼凑起来的,实际可以用于传输的应该是
(db_20001_1@127.0.0.1)12> [123,34,110,97,109,101,34,58,34,49,50,51,34,44,34,97,103,101,34,58,50,52,125].
"{\"name\":\"123\",\"age\":24}"
这里需要做的操作就是
F = fun(Element) ->
case is_binary(Element) of
true ->
binary_to_list(Element);
false ->
Element
end
end,
Param3 = lists:map(F, lists:flatten(Param22)),
Param4 = lists:flatten(Param3),
特别的,如果有中文字符串,那需要处理的更复杂一点,例如
(db_20001_1@127.0.0.1)15> common_json2:to_json([{name, "你妹子"}, {age, 24}]).
** exception error: bad argument
in function  list_to_binary/1
called as list_to_binary([20320,22969,23376])
in call from common_json2:prepare_for_json/1 (e:/G35Server/src/common/common_json2.erl, line 32)
in call from common_json2:proplist_to_json/2 (e:/G35Server/src/common/common_json2.erl, line 52)
in call from common_json2:list_to_json/2 (e:/G35Server/src/common/common_json2.erl, line 46)
in call from common_json2:to_json/1 (e:/G35Server/src/common/common_json2.erl, line 16)
(db_20001_1@127.0.0.1)16> io:format("~w", [common_json2:to_json([{name, xmerl_ucs:to_utf8("你妹子")}, {age, 24}])]).
[123,[34,[110,97,109,101],34],58,[34,[92,117,52,102,54,48],[92,117,53,57,98,57],[92,117,53,98,53,48],34],44,[34,[97,103,101],34],58,[50,52],125]ok
如上,直接使用中文字符串会异常,必须转换成utf-8。关于json传输,查看http://whathellk.lofter.com/post/1cc5e53b_4481518

4、总结

1、适当使用jinterface和nif等工具来拓展erlang功能;
2、字符串操作不光是要查看内容,更要查看字符串原始list,选择合适类型的字符串(io:format("~w", [String])查看原始list)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  rsa 加密 json erlang