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

新浪微博登录,QQ登录网页javascript脚本实现RSA加密的原理

2014-01-10 16:40 726 查看
今天在原来的系统上增加网页操作的功能,原来系统是JAVA写的,数据传输用的是RSA加密,为了实现网页登录,研究了javascript的RSA加密方法。

这个系统是一个移动电话会议系统,是手机上就能发起电话会议的为数不多的几个系统之一。

以前开发系统的时候是参考这篇文章写的 http://alunblog.duapp.com/?p=50
前段时间在开发欣所罗门公司自动化营销系统的时候,研究过QQ网页登录方法,里面有RSA加密的脚本。

欣所罗门公司自动化营销系统是一套全自动建立营销数据库的系统。

打开QQ注册页面,把里面的http://4.url.cn/zc/chs/js/10062/rsa.js下载了下来,然后写了个HTA测试页面。

HTA相当于用网页技术实现的一个桌面程序,非常好用,能够实现绝大多数桌面程序的功能。

QQ注册RSA加密的相关代码是这样的:

function rsaEncrypt(txt){
var b=new RSAKey;
b.setPublic("C4D23C2DB0ECC904FE0CD0CBBCDC988C039D79E1BDA8ED4BFD4D43754EC9693460D15271AB43A59AD6D0F0EEE95424F70920F2C4A08DFDF03661300047CA3A6212E48204C1BE71A846E08DD2D9F1CBDDFF40CA00C10C62B1DD42486C70A09C454293BCA9ED4E7D6657E3F62076A14304943252A88EFA416770E0FBA270A141E7",
"10001");return b.encrypt(a)
}

rsaEncrypt($("password").value)

我们原来的密钥是通过OPENSSL命令行工具生成的,是一个PEM文件,打开后内容是这样的:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSipVLWBnTtIaLpSkvtmQTJNFl
INLKNmLufvgp9JIpGgFOYU6f1231QFDhbK2dEykNLwaDmCOVHLpR5fm0b/qhZeJ0
zWGgQ7hOyTISiwUM5PGqwAXlfJRS/ZQXe72l7/+ijBEdTZ3U/5okDQA5QTAVWo9Q
JGqKj1IVL0Hs9JwK8wIDAQAB
-----END PUBLIC KEY-----

开始的时候我是把这段内容去掉换行符连在一起做为公钥,代码像这样

<script language="JavaScript" type="text/javascript" src="rsa.js"></script>

<script type="text/javascript">
function rsaEncrypt(txt){
var b=new RSAKey;
b.setPublic("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSipVLWBnTtIaLpSkvtmQTJNFlINLKNmLufvgp9JIpGgFOYU6f1231QFDhbK2dEykNLwaDmCOVHLpR5fm0b/qhZeJ0zWGgQ7hOyTISiwUM5PGqwAXlfJRS/ZQXe72l7/+ijBEdTZ3U/5okDQA5QTAVWo9QJGqKj1IVL0Hs9JwK8wIDAQAB",
"10001");return b.encrypt(a)
}

}
</script>

加密完以后,一解密就出错,百思不得其解,于是把rsa.js的内容格式化了一下,发现javascript里的公钥是16进制的字符串,而我的公钥是BASE64的字符串,找到原因后就好做了。

把原来的JAVA里实现 的RSA加密函数改了一下,把BASE64的公钥转成16进制的字符串,心想这下应该没问题了吧,代码如下:

private static final String RSA_PUBLICE =
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSipVLWBnTtIaLpSkvtmQTJNFl\n" +
"INLKNmLufvgp9JIpGgFOYU6f1231QFDhbK2dEykNLwaDmCOVHLpR5fm0b/qhZeJ0\n" +
"zWGgQ7hOyTISiwUM5PGqwAXlfJRS/ZQXe72l7/+ijBEdTZ3U/5okDQA5QTAVWo9Q\n" +
"JGqKj1IVL0Hs9JwK8wIDAQAB";
private static final String ALGORITHM = "RSA";

/**
* 得到公钥
* @param algorithm
* @param bysKey
* @return
*/
private static PublicKey getPublicKeyFromX509(String algorithm,
String bysKey) throws NoSuchAlgorithmException, Exception {
byte[] decodedKey = Base64.decode(bysKey, Base64.DEFAULT);
X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);

KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePublic(x509);
}

public static String getPublicKey()
{
try {
PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, RSA_PUBLICE);
java.security.interfaces.RSAPublicKey pk = (java.security.interfaces.RSAPublicKey)pubkey;
return pk.getModulus().toString(16);
} catch (Exception e) {
return null;
}
}

生成公钥后的javascript代码变成了这样:

<script language="JavaScript" type="text/javascript" src="rsa.js"></script>

<script type="text/javascript">
function rsaEncrypt(txt){
var b=new RSAKey;
b.setPublic("d28a954b5819d3b4868ba5292fb6641324d16520d2ca3662ee7ef829f492291a014e614e9fd76df54050e16cad9d13290d2f06839823951cba51e5f9b46ffaa165e274cd61a043b84ec932128b050ce4f1aac005e57c9452fd94177bbda5efffa28c111d4d9dd4ff9a240d00394130155a8f50246a8a8f52152f41ecf49c0af3",
"10001");return b.encrypt(a)
}
}
</script>

接下来,用这段代码加密了一段文本,然后尝试解密了一下,还是错误!


















当然,对于一个优秀的程序员来说,不达目的绝不罢休,于是又去翻JAVA的加密和解密代码。

终于,在看到加密函数最后一段的时候突然明白了,代码如下:

PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, RSA_PUBLICE);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubkey);
byte[] output = cipher.doFinal(plaintext);
String s = new String(Base64.encode(output, Base64.NO_WRAP));

原来的加密结果是用BASE64编码的,但是javascript加密出来的字符串感觉明显不是BASE64的,哈哈,胜利在望!

翻看了rsa.js的代码,果然,加密结果转换成了16进制的字符串。

于是百度了一下把BigInteger进行base64编码的方法,找到一个网站http://www-cs-students.stanford.edu/~tjw/jsbn/











上面除了RSA加密代码外,还同时支持输出16进制和BASE64的结果,而且提供了测试页面http://www-cs-students.stanford.edu/~tjw/jsbn/rsa.html

在测试页面输入16进制的公钥后,生成base64的密文,然后用服务器的解密函数尝试解了一下,结果是预料之中的!解密成功!

问题解决,也懒得去折腾qq的rsa.js了,直接把测试页面的所有js下载下来,照着写了一个页面:

文件rsa.hta内容

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>RSA加密</title>
<HTA:Application ID="oHTA"
Applicationname="rsaApp"
border="thin"
borderstyle="normal"
caption="yes"
icon="filename.ico"
maximizebutton="no"
minimizebutton="yes"
showintaskbar="yes"
singleinstance="yes"
sysmenu="yes"
version="1.0"
windowstate="normal"
scroll="no">
</head>
<body>

<script language="JavaScript" type="text/javascript" src="jsbn.js"></script>
<script language="JavaScript" type="text/javascript" src="prng4.js"></script>
<script language="JavaScript" type="text/javascript" src="rng.js"></script>
<script language="JavaScript" type="text/javascript" src="rsa.js"></script>
<script language="JavaScript" type="text/javascript" src="base64.js"></script>

<script type="text/javascript">
function rsaEncrypt(txt){

var rsa = new RSAKey();
rsa.setPublic("d28a954b5819d3b4868ba5292fb6641324d16520d2ca3662ee7ef829f492291a014e614e9fd76df54050e16cad9d13290d2f06839823951cba51e5f9b46ffaa165e274cd61a043b84ec932128b050ce4f1aac005e57c9452fd94177bbda5efffa28c111d4d9dd4ff9a240d00394130155a8f50246a8a8f52152f41ecf49c0af3", "10001");
var res = rsa.encrypt(txt);
if(res) {
//linebrk(res, 64); 16进制字符串
return linebrk(hex2b64(res), 64);
}
return "";
}
</script>

<center>
<br />
<br />
<input type="text" id="txtMing" size="52" />
<br />
<br />
<textarea rows="10" cols="40" id="txtMi"></textarea>
<br />
<br />
<button onclick="document.getElementById('txtMi').value=rsaEncrypt(document.getElementById('txtMing').value)">加密</button>
</center>

<SCRIPT Language="VBScript">
Sub Window_Onload
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")
For Each objItem in colItems
intHorizontal = objItem.ScreenWidth
intVertical = objItem.ScreenHeight
Next
intLeft = (intHorizontal - 450) / 2
intTop = (intVertical - 400) / 2
window.resizeTo 450,400
window.moveTo intLeft, intTop
End Sub
</SCRIPT>
</body>
</html>

我是位流先锋,我的QQ是 2720574276,微信是 bit0001,欢迎加我为好友交流!

如果你热衷编程技术,欢迎加入我们的交流群:341313960
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息