一 场景
公司项目在页面和服务器交互使用ajax方式,但是浏览器中是可以看到请求的参数结构:接口、请求和返回参数;这种方式容易被别人通过browser F12查看并模拟攻击接口,由此展开了数据传输两端加密的学习之路;
为了做到request&response的数据全部都加密处理,并希望密钥能够变化生成;
留下脚印,也分享给其他攻城师们参考;
二 使用技术
页面上使用CryptoJS一个插件(https://github.com/brix/crypto-js),要使用CryptoJS.pad.ZeroPadding模式;
CryptoJS (crypto.js) 为 JavaScript 提供了各种各样的加密算法。目前已支持的算法包括:
-
MD5
-
SHA-1
-
SHA-256
-
AES
-
Rabbit
-
MARC4
-
HMAC
-
HMAC-MD5
-
HMAC-SHA1
-
HMAC-SHA256
-
-
PBKDF2
java使用Cipher,值得注意的是要使用"AES/CBC/NoPadding"模式;
两表的key和iv都有16位的长度;
这三点是调通代码的前提,我也是慢慢调试出来,希望后面的大家少走弯路;以下代码可以直接使用哦!
三 代码直接展示
1)前段js代码
var xxx = {
key : CryptoJS.enc.Latin1.parse('123456abc2345678'),
iv : CryptoJS.enc.Latin1.parse('1234567abc345678'),
encrypt: function(data){
var encrypted = CryptoJS.AES.encrypt(data,this.key,{iv:this.iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.ZeroPadding});
return encrypted.toString();
},
decrypt: function(data){
try{
var decrypted = CryptoJS.AES.decrypt(data,this.key,{iv:this.iv,padding:CryptoJS.pad.ZeroPadding});
return decrypted.toString(CryptoJS.enc.Utf8);
}catch(e){
return data;
}
}
}
return xxx;
2)java端代码
/**
* AES java-javascript 只支持部填充摸索
*/
public static final String format = "AES/CBC/NoPadding";
/**
* AES 加密key,必须为16位
*/
public static String key = "123456abc2345678";
/**
* AES 偏移量,必须为16位
*/
public static String iv = "123456abc2345678";
/**
* 使用AES加密
* @since 0.0.11
*/
public static String encrypt(String data){
if(StringUtils.isEmpty(data)){
return null;
}
try {
Cipher cipher = Cipher.getInstance(format);
int blockSize = cipher.getBlockSize();
byte[] dataBytes = data.getBytes();
int plaintextLength = dataBytes.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return new sun.misc.BASE64Encoder().encode(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 使用AES解密
* @since 0.0.11
*/
public static String decrypt(String data){
if(StringUtils.isEmpty(data)){
return null;
}
try
{
byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
Cipher cipher = Cipher.getInstance(format);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original);
return originalString;
}
catch (Exception e) {
e.printStackTrace();
return data;
}
}
3)加密策略
加密算法偏移(eg.iv),服务器每次启动都会随机生成;
加密算法密钥(key),使用结合用户id随机生成;
四 心得体会
做完这个后发现,这段代码的使用场景还是很丰富的;可以使用传统的pc网站,移动端的页面;web和java端的数据交互以后放心多了;
在实际项目中,我的key和iv都是采用服务端启动时自动生成,再加载给页面保证安全性;