对AES加密、解密这里不做介绍,不清楚的可以网上查询相关介绍。
这里只记录下AES解密过程,在有限的加密信息下,耗时两天,尝试出来的解密过程。解的怀疑人生。
背景
为了数据的安全性,后端将数据进行了加密,前端需求解密得到正确的JSON。
给到前端的信息
1、AES加密
2、后端加密的一个类文件(java)
3、秘钥KEY
解密过程
解读得到信息:
1、解密模式:ECB (只有一个秘钥KEY值)
2、填充方式:默认Pkcs7
3、后端加密采用了 AES、base64、SHA1、字符串转字节处理
思路:
1、先整理后台的加密规则(看不明白后端代码,只能调试一步,对比结果)
2、按加密的规则进行解密
3、借助第三方解密插件
解密规则
加密内容处理
1.base64 解密 得到字符串
2.字符串转成byte []类型的字节 (注意:字节长度需要/2)
3.将字节转成words对象
4、words对象转 base64的字符串
秘钥key处理
1、字符串转byte []类型的字节(注意:字节长度不需要/2)
2、用sha1加密2次 字节,并转成数组格式
3、截取前16位数组
4、将字节转成words对象(int8parse)
AES解密
模式:EBC
填充方式:PKcs7
数据转字符串
字符串转json对象
实现代码
// 解密方法
const decrypt = (word) => {
const base64 = decodeURIComponent(escape(window.atob(word)))
const bytes = onHex(base64)
console.log('base64', base64)
console.log('bytes', bytes)
const keyByte = stringToByte(key)
console.log('keyByte', keyByte)
// const bytes = CryptoJS.enc.Utf8.parse(base64)
const keyByteSha1 = sha1.array(keyByte)
console.log('keyByteSha1', keyByteSha1)
const keyByteSha2 = sha1.array(keyByteSha1).slice(0, 16)
console.log('keyByteSha2', keyByteSha2)
const keyAes = aesKeyBytes(keyByteSha2)
console.log('keyAes', keyAes)
const wordArray = int8parse(bytes)
console.log('wordArray', wordArray)
const base64Str = CryptoJS.enc.Base64.stringify(wordArray)
console.log('base64Str', base64Str)
const decrypt = CryptoJS.AES.decrypt(base64Str, keyAes, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
console.log('decrypt', decrypt)
return JSON.parse(decrypt.toString(CryptoJS.enc.Utf8))
}
// 加解密用到的密钥
function aesKeyBytes(a) {
const key_Int = new Int8Array(a)
const keyBytes = int8parse(key_Int)
return keyBytes
}
// 构建WordArray对象
function int8parse(u8arr) {
const len = u8arr.length
const words = []
for (let i = 0; i < len; i++) {
words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8)
}
return CryptoJS.lib.WordArray.create(words, len)
}
// 字符串转字节 长度需要/2
function onHex(hex) {
const buffer = new ArrayBuffer((hex.length) / 2)
const byteStream = new Uint8Array(buffer)
let i = 0
while (hex.length >= 2) {
const x = parseInt(hex.substring(0, 2), 16)
hex = hex.substring(2, hex.length)
byteStream[i++] = x
}
return byteStream
}
// 字符串转字节 长度不需要/2
export function stringToByte(str) {
const bytes = []
let c
const len = str.length
for (let 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
}
依赖:
crypto-js
js-sha1
解密过程结果
base64
D8061382C771D2525CDAA715BEE1483CB5D19F4003E5352D5495404A0AF9644B2B162184C35FD11B0D254784CEDB3D75B4383AB7BF27321568C2B28DC7D8F3781DF24C021DFCD89053FB6C89990B37C16CD893A3DF38F48AA626944C76F33B970AD4981122306AF636105B5C78A7816480BE93A27541CE1EF048007BA8BCF9E1BC1B2B22DBC84216AF945F5681EE15349EEDE7E8324420BF03C9A002CB6FD3EF6170A5491024861CE7914A7EB31FBC3ED70E81535100D9074EF0951AE98232124600AEC31412D0C4ACD78A19502FE4AFA56FA8C85555DCD5C543F91516C407CB2931E33BF9FE7007764E8C6529C9AFD2D763AC912A4EA3ADBA79738F773DBA2BCB9DF69A6E3124F61110D3D88645DC023F0A030AD53BB8756F498FFA0301B1C65115A9F4FC41F762FA3EDB53DAA91E9075A5F04B2A933EF9422A908105888CCA93F9CE215C31835C76F93AAC0C3BA8539C96CC6B6432662A0FE93D9F2136E483C30CC133C647C505ACFE4D01FEFBA4E634D839EF3302AF91378DFF0D28381D4A186109E754AD6C790C63013159BC5CE7615AF16A0350AA947D1BC42BEC45D66AEC8CE8E2CA7ADA1B7B
bytes
Uint8Array(432) [216, 6, 19, 130, 199, 113, 210, 82, 92, 218, 167, 21, 190, 225, 72, 60, 181, 209, 159, 64, 3, 229, 53, 45, 84, 149, 64, 74, 10, 249, 100, 75, 43, 22, 33, 132, 195, 95, 209, 27, 13, 37, 71, 132, 206, 219, 61, 117, 180, 56, 58, 183, 191, 39, 50, 21, 104, 194, 178, 141, 199, 216, 243, 120, 29, 242, 76, 2, 29, 252, 216, 144, 83, 251, 108, 137, 153, 11, 55, 193, 108, 216, 147, 163, 223, 56, 244, 138, 166, 38, 148, 76, 118, 243, 59, 151, 10, 212, 152, 17, …]
keyByte
(36) [102, 49, 48, 97, 48, 97, 52, 49, 45, 55, 55, 99, 54, 45, 52, 98, 97, 54, 45, 52, 51, 50, 51, 45, 101, 51, 102, 98, 50, 48, 53, 97, 97, 99, 102, 97]
keyByteSha1
(20) [153, 230, 38, 236, 52, 96, 86, 81, 14, 242, 159, 85, 99, 71, 149, 16, 12, 194, 88, 103]
keyByteSha2
(16) [35, 102, 148, 128, 131, 179, 185, 148, 176, 189, 182, 110, 139, 192, 150, 104]
keyAes
{$super: {…}, words: Array(4), sigBytes: 16, init: ƒ}
wordArray
{$super: {…}, words: Array(108), sigBytes: 432, init: ƒ}
base64Str 2AYTgsdx0lJc2qcVvuFIPLXRn0AD5TUtVJVASgr5ZEsrFiGEw1/RGw0lR4TO2z11tDg6t78nMhVowrKNx9jzeB3yTAId/NiQU/tsiZkLN8Fs2JOj3zj0iqYmlEx28zuXCtSYESIwavY2EFtceKeBZIC+k6J1Qc4e8EgAe6i8+eG8Gysi28hCFq+UX1aB7hU0nu3n6DJEIL8DyaACy2/T72FwpUkQJIYc55FKfrMfvD7XDoFTUQDZB07wlRrpgjISRgCuwxQS0MSs14oZUC/kr6VvqMhVVdzVxUP5FRbEB8spMeM7+f5wB3ZOjGUpya/S12OskSpOo626eXOPdz26K8ud9ppuMST2ERDT2IZF3AI/CgMK1Tu4dW9Jj/oDAbHGURWp9PxB92L6PttT2qkekHWl8Esqkz75QiqQgQWIjMqT+c4hXDGDXHb5OqwMO6hTnJbMa2QyZioP6T2fITbkg8MMwTPGR8UFrP5NAf77pOY02DnvMwKvkTeN/w0oOB1KGGEJ51StbHkMYwExWbxc52Fa8WoDUKqUfRvEK+xF1mrsj
decrypt
WordArray.init {words: Array(108), sigBytes: 423}
ossData
{accessid: 'LT5tK7vA32Gguxu5n6', policy: 'eyJleHBpcmF0aW9o0MzoxOC4yNT…wMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJjc20vIl1dfQ==', signature: 'sd2p/uQtVe1maCPkr4BxF9TU=', …}
后续在记录一篇前后端项目统一加解密的处理流程,封装SDK,对外只提供接口