前端jsp登录密码加密为des3加密方法

JavaScript07

前端jsp登录密码加密为des3加密方法,第1张

*_*?我是谁

原创

关注

0点赞·757人阅读

<%@ page contentType="text/htmlcharset=GBK"%>

<%@ page language="java" import="java.util.regex.*,

com.excellence.common.OAConstant,

com.excellence.common.UserInfo,

java.util.*,

java.text.SimpleDateFormat," %>

<html>

<head>

<title>XX系统</title>

<meta http-equiv="Content-Type" content="text/htmlcharset=gb2312">

<link rel="stylesheet" href="/common/styles/default/default.css" type="text/css">

</head>

<script language="javascript">

</script>

<script language="JavaScript" src="/oa/javascripts/crypto-js.js"></script>

<body bgcolor="#FFFFFF" text="#000000" leftmargin="0" topmargin="0">

<center>

</center>

</body>

<script type="text/vbscript">

Function str2asc(strstr)

str2asc = hex(asc(strstr))

End Function

Function asc2str(ascasc)

asc2str = chr(ascasc)

End Function

</script>

<script>

<%

UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo ")

String account=""

//获取用户账号

if(userInfo.getAccount()!=null&&!"".equals(userInfo.getAccount()))

account=userInfo.getAccount()

//有效期:格式:yyyy-MM-dd HH:mm:ss 有效期不能设置超过10分钟

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

Date now = new Date()

Date date = new Date(now .getTime() + 600000)

String time = df.format(date)

%>

//sessionid = base64(DES(用户账号&有效期))

//DES key:67HT4WrP

var sessionId = "<%=account%>" + "&" + "<%=time%>"

var mykey = "67HT4WrP"

// DES加密模式:CBC模式/ECB模式

// CBC模式加密

function encryptCBC(text, textKey) {

// 密钥转成16进制的字符串

var key = CryptoJS.enc.Utf8.parse(textKey)

// 加密过程

var encrypted = CryptoJS.DES.encrypt(text, key, {

// iv偏移量为key值

iv: key,

// 模式为CBC

mode: CryptoJS.mode.CBC,

// DES加密padding为Pkcs7

padding: CryptoJS.pad.Pkcs7

})

// 加密返回为字符串密文(加密经过一次base64加密,结果可看结果)

return encrypted.toString()

}

//对字符串中的特殊字符进行UrlEncode转码

function UrlEncode(str){

var ret=""

var strSpecial="!\"#$%&'()*+,/:<=>?[]^`{|}~%"

var tt= ""

for(var i=0i<str.lengthi++){

var chr = str.charAt(i)

var c=str2asc(chr)

tt += chr+":"+c+"n"

if(parseInt("0x"+c) >0x7f){

ret+="%"+c.slice(0,2)+"%"+c.slice(-2)

}else{

if(chr==" ")

ret+="+"

else if(strSpecial.indexOf(chr)!=-1)

ret+="%"+c.toString(16)

else

ret+=chr

}

}

return ret

}

//对sessionid进行加密

var desPass=encryptCBC(sessionId,mykey)

//对加密的sessionid中的特殊字符转码

var desPassEncode=UrlEncode(desPass)

//URL格式:http://xxxxxxxxxxxx?sessionid=&appid=5t7i9e260w6f41b71rt7fd07h9qo9800&redirectUrl=~/Portals/Views/Test/index.html

var url="http://xxxxxxxxxxxx?sessionid="+desPassEncode+"&appid=5t7i9e260w6f41b71rt7fd07h9qo9800&redirectUrl=~/Portals/Views/Test/index.html"

window.close()

window.open(url)

</script>

</html>

登录后复制

注意事项:

1、crypto-js.js使用到了这个js,要记得引入,很多地方可以下载的,除了这里面能用到des加密,也可以从网上找其他的des加密脚本,但是因为des加密模式的问题,要注意调用函数时参数的使用,确定自己要使用的是哪种des加密方法。

2、因为这里实现的是自动登录,涉及到了url的处理,由于使用了加密,密文中会含有特殊字符,直接通过url转跳,要把url中含有的特殊字符进行UrlEncode转码。

3、注意这里des的加密方式,这样进行转跳,跳进去的网站是.net实现的,因为des的加密模式有几种,java,.net等默认的des加密模式有可能不一致,就会导致加密后的密文不一样,所以要确定自己使用哪种模式,或者直接输出加密密文来进行比较。

4、使用js比较方便的地方是因为我这里用的jsp页面,所以对处理的数据可以任意写,而且不会影响后台的使用,我觉得这是js的好处,特别是进行像这种进行类似单点登录,自己系统用的java实现,而别人用的.net,直接用脚本,可以节省时间,不会对自己系统造成什么影响。

5、有一个地方要注意,这里对url进行转码时,使用到了VB脚本的一些函数,这种脚本已经很少有人会用了,而且有些浏览器已经不支持了,百度显示ie11不支持,但是我自己的电脑就是ie11,可以使用,所以这个也不是绝对的,有可能和使用到的函数有关。

6、除了des加密,还有md5,单独的base64加密,这些常用的加密方式,都可以直接用js脚本实现。

7、这里只有des的一种加密模式,还有其他的,crypto-js.js中都有,可以百度下其他加密方法的使用!

最近需要对数据进行加密/解密, 因此选用了CryptoJS库, 对数据做DES算法的加密/解密

首选查看官方示例, 将密文进行Base64编码, 掉进一个大坑

<script src="htt p:/ /crypto-js.googlecod e.c om/svn/tags/3.1.2/build/rollups/tripledes.js"></script>

<script>

var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase")

// ciphertext changed every time you run it

// 加密的结果不应该每次都是一样的吗?

console.log(encrypted.toString(), encrypted.ciphertext.toString(CryptoJS.enc.Base64))

var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase")

console.log(decrypted.toString(CryptoJS.enc.Utf8))

</script>

对这些加密算法不了解, 只能求助Google

des encrypion: js encrypted value does not match the java encrypted value

In cryptoJS you have to convert the key to hex and useit as word just like above (otherwise it will be considered as passphrase)

For the key, when you pass a string, it's treated as a passphrase and used to derive an actual key and IV. Or you can pass a WordArray that represents the actual key.

原来是我指定key的方式不对, 直接将字符串做为参数, 想当然的以为这就是key, 其实不然, CryptoJS会根据这个字符串算出真正的key和IV(各种新鲜名词不解释, 问我也没用, 我也不懂 -_-")

那么我们只需要将key和iv对应的字符串转成CryptoJS的WordArray类型, 在DES加密时做为参数传入即可, 这样对Message这个字符串加密, 每次得到的密文都是YOa3le0I+dI=

var keyHex = CryptoJS.enc.Utf8.parse('abcd1234')

var ivHex = CryptoJS.enc.Utf8.parse('inputvec')

var encrypted = CryptoJS.DES.encrypt('Message', keyHex, { iv: ivHex })

这样是不是就万事OK了? 哪有, 谁知道这坑是一个接一个啊.

我们再试试Java这边的DES加密是不是和这个结果一样, 具体实现请参考Simple Java Class to DES Encrypt Strings

果真掉坑里了, Java通过DES加密Message这个字符串得到的结果是8dKft9vkZ4I=和CryptoJS算出来的不一样啊...亲

继续求助Google

C# and Java DES Encryption value are not identical

SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES.(JCA Doc)

This means that in the case of the SunJCE provider,

Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding")

and

Cipher c1 = Cipher.getInstance("DES")

are equivalent statements.

原来是CryptoJS进行DES加密时, 默认的模式和padding方式和Java默认的不一样造成的, 必须使用ECB mode和PKCS5Padding, 但是CryptoJS中只有Pkcs7, 不管了, 试试看...

<script src="htt p:/ /crypto-js.googleco de.c om/svn/tags/3.1.2/build/rollups/tripledes.js"></script>

<script src="ht tp:/ /crypto-js.googleco de.c om/svn/tags/3.1.2/build/components/mode-ecb.js"></script>

<script>

var keyHex = CryptoJS.enc.Utf8.parse('abcd1234')

var encrypted = CryptoJS.DES.encrypt('Message', keyHex, {

mode: CryptoJS.mode.ECB,

padding: CryptoJS.pad.Pkcs7

})

console.log(encrypted.toString(), encrypted.ciphertext.toString(CryptoJS.enc.Base64))

</script>

咦...使用Pkcs7能得到和Java DES一样的结果了, 哇塞...好神奇

那我们试试统一Java也改成Cipher.getInstance("DES/ECB/PKCS7Padding")试试, 结果得到一个大大的错误

Error:java.security.NoSuchAlgorithmException: Cannot find any provider supporting DES/ECB/PKCS7Padding

没办法, 继续Google

java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/ECB/PKCS7PADDING

I will point out that PKCS#5 and PKCS#7 actually specify exactly the same type of padding (they are the same!), but it's called #5 when used in this context. :)

这位大侠给出的解释是: PKCS#5和PKCS#7是一样的padding方式, 对加密算法一知半解, 我也只能暂且认可这个解释了.

忙完了DES的加密, 接下来就是使用CryptoJS来解密了. 我们需要直接解密DES加密后的base64密文字符串. CryptoJS好像没有提供直接解密DES密文字符串的方法啊, 他的整个加密/解密过程都是内部自己在玩, 解密时需要用到加密的结果对象, 这不是坑我吗?

只好研究下CryptoJS DES加密后返回的对象, 发现有一个属性ciphertext, 就是密文的WordArray, 那么解密的时候, 我们是不是只要提供这个就行了呢?

var keyHex = CryptoJS.enc.Utf8.parse('abcd1234')

// direct decrypt ciphertext

var decrypted = CryptoJS.DES.decrypt({

ciphertext: CryptoJS.enc.Base64.parse('8dKft9vkZ4I=')

}, keyHex, {

mode: CryptoJS.mode.ECB,

padding: CryptoJS.pad.Pkcs7

})

console.log(decrypted.toString(CryptoJS.enc.Utf8))

果不其然, 到此为止, 问题全部解决, 豁然开朗...

完整代码请参考CryptoJS-DES.html

Use CryptoJS encrypt message by DES and direct decrypt ciphertext, compatible with Java Cipher.getInstance("DES")