目标
java端采用DES/CBC/PKCS5Padding 加密,前端,小程序 js,如何进行加解密。
js解析库下载地址
二次开发版本
我用的是二次开发版本.
解决代码
先给结果!如下代码是核心代码,如果看不懂,可以继续往下看
详细步骤解决
。
java后台端代码
DES/CBC/PKCS5Padding代码如下(写的一个简便的,直接粘贴到 java ide上可运行):
import com.sun.org.apache.xml.internal.security.utils.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Des {
public static void main(String[] args) {
String result = encryptDES("123456","6eGicG6U");
System.out.println(result);
}
/**
* 加密 这个iv偏移量是数组!!
*/
private static byte[] iv = {1, 2, 3, 4, 5, 6, 7, 8};
public static String encryptDES(String encryptString, String encryptKey) {
try {
IvParameterSpec zeroIv = new IvParameterSpec(iv);
SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES");
System.out.println("key: "+encryptKey.getBytes().toString());
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
byte[] encryptedData = cipher.doFinal(encryptString.getBytes());
return Base64.encode(encryptedData);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
/**
* 解密
*/
public static String decryptDES(String decryptString, String decryptKey) {
try {
byte[] byteMi = Base64.decode(decryptString);
IvParameterSpec zeroIv = new IvParameterSpec(iv);
SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);
byte decryptedData[] = cipher.doFinal(byteMi);
return new String(decryptedData);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
小程序 CryptoJS
//CBC模式加密 utf8 to base64
function encryptByDESModeCBCUtf8to64(message) {
var key = '6eGicG6U'; //密钥
var iv = [1, 2, 3, 4, 5, 6, 7, 8];
var ivString = byteToString(iv)
var keyHex = CryptoJS.enc.Utf8.parse(key);
var ivHex = CryptoJS.enc.Utf8.parse(ivString);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
iv: ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}
function encryptByDESModeCBCUtf8to(message,key,iv) {
var message=CryptoJS.enc.Utf8.parse(message);
var keyHex = CryptoJS.enc.Utf8.parse(key);
var ivHex = CryptoJS.enc.Utf8.parse(iv);
encrypted = CryptoJS.DES.encrypt(message, keyHex, {
iv:ivHex,
mode: CryptoJS.mode.CBC,
padding:CryptoJS.pad.Pkcs7
}
);
//加密 成Base64
return encrypted.ciphertext.toString();
// CryptoJS.enc.Base64
}
//CBC模式解密
function decryptByDESModeCBC(ciphertext2,key,iv) {
var keyHex = CryptoJS.enc.Utf8.parse(key);
var ivHex = CryptoJS.enc.Utf8.parse(iv);
// CryptoJS.enc.Base64.parse(
// direct decrypt ciphertext
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(ciphertext2)
}, keyHex, {
iv:ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
//CBC模式解密
function decryptByDESModeCBCHex(ciphertext2,key,iv) {
var keyHex = CryptoJS.enc.Utf8.parse(key);
var ivHex = CryptoJS.enc.Utf8.parse(iv);
// direct decrypt ciphertext
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Hex.parse(ciphertext2)
}, keyHex, {
iv:ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
//DES ECB模式加密
function encryptByDESModeEBC(message){
var keyHex = CryptoJS.enc.Utf8.parse(key);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.ciphertext.toString();
}
//DES ECB模式解密
function decryptByDESModeEBC(ciphertext){
var keyHex = CryptoJS.enc.Utf8.parse(key);
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Hex.parse(ciphertext)
}, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
var result_value = decrypted.toString(CryptoJS.enc.Utf8);
return result_value;
}
注意!!:
如果是java端 iv偏移量是数组,需要 js byte[] 和string 相互转换 UTF-8。
function stringToByte(str) {
var bytes = new Array();
var len, c;
len = str.length;
for(var i = 0; i < len; i++) {
c = str.charCodeAt(i);
if(c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if(c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if(c >= 0x000080 && c <= 0x0007FF) {
bytes.push(((c >> 6) & 0x1F) | 0xC0);
bytes.push((c & 0x3F) | 0x80);
} else {
bytes.push(c & 0xFF);
}
}
return bytes;
}
function byteToString(arr) {
if(typeof arr === 'string') {
return arr;
}
var str = '',
_arr = arr;
for(var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if(v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for(var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(_arr[i]);
}
}
return str;
}
详细步骤解决
CryptoJs是google推出的一款前段解密类库.功能强大,包含很多的前段解密算法.
javascript解密库是用crypto-js。
小程序解决:
小程序需要引入CryptoJS github。
我用的是
二次开发版本
.
下载代码后:
将CryptoJS-master\rollups中的js添加到小程序中:
在 tripledes.js 下添加
module.exports = CryptoJS
在小程序中添加:
var CryptoJS = require('../../libs/CryptoJS/tripledes.js');
添加代码到页面。
//index.js
var CryptoJS = require('../../libs/CryptoJS/tripledes.js');
//获取应用实例
const app = getApp()
function byteToString(arr) {
if (typeof arr === 'string') {
return arr;
}
var str = '',
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(_arr[i]);
}
}
return str;
}
function encryptByDESModeCBCUtf8to64(message) {
var key = '6eGicG6U'; //密钥
var iv = [1, 2, 3, 4, 5, 6, 7, 8];
var ivString = byteToString(iv)
var keyHex = CryptoJS.enc.Utf8.parse(key);
var ivHex = CryptoJS.enc.Utf8.parse(ivString);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
iv: ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}
Page({
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo')
},
//事件处理函数
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function() {
var encryptData = encryptByDESModeCBCUtf8to64("123456");
console.log("encryptData " + encryptData);
},
})
ok完成。
为什么添加上面的代码就可以解密?
首先准备一份明文和秘钥:
var key = '6eGicG6U'; //一般key为一个字符串或者数组
var iv = [1, 2, 3, 4, 5, 6, 7, 8];//偏移量
加密过程中使用哪种加密方式取决于传入key的类型,否则就会按照AES-256的方式加密。
Java就是按照128bit给的,需要使用CryptoJS.enc.Utf8.parse方法才可以将key转为128bit的。
// key 和 偏移量 用之前需要用uft8先parse一下才能用
var keyHex = CryptoJS.enc.Utf8.parse(key);
var ivHex = CryptoJS.enc.Utf8.parse(ivString);
由于后端使用的是PKCS5Padding,CryptoJS的时候发现根本没有这个偏移。
但是Pkcs5是Pkcs7在块大小为8时特殊情况,本质上是一样的。Crypto-js默认padding是Pkcs7,可以直接使用。
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
iv: ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
由于CryptoJS生成的密文是一个对象,如果直接将其转为字符串是一个Base64编码过的,在encryptedData.ciphertext上的属性转为字符串才是后端需要的格式。
需要读取encryptedData上的ciphertext.toString()才能拿到跟Java一样的密文。
return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
到此,第一个方法讲解完了。
如果iv是byte数组,因为小程序 js无法表示byte需要将其转化方法。
function byteToString(arr) {...}
拓展
如果是AES只需使用CryptoJS.AES.encrypt,
需要引用的包改变一下,在aes.js中。
var encrypted = CryptoJS.AES.encrypt(message, keyHex, {
iv: ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
参考
一个在线加解密
如何使用CryptoJS的AES方法进行加密和解密
细说CryptoJs使用(微信小程序加密解密)