-1

我正在尝试在 aes 算法(gcm 模式)中使用 sjcl.js 加密库解密密码内容。这是我的代码:

//encrypted data and key
let key = "8mUzwnewfaBFKiGW/rO5Xw=="
let cipherText ="Oz9IH7sElYzEyLCQoHJZJgH6z4J3INJtJyrpQzFQg3dRbEFIla4r4ox0ktA/Sh077fvCnnaMrCKu9PiYOQiRN7bS7EAXKgdiMN/zL98j4HyeVB9nRrH2PVXGKL+TcjM3F+kScl0DyCHJxHiXb+rKhXlYc/3T2ulBV8xIwk+S0IdV5TwjIfLIY7lxWcvZt9Mi2JEt9C54RFU3nFQIexSPIpoLtwnonbguSlx/KsNYgpObhlhRsC9W/Ix2m4n6eDxfQWCuhQp5614OiizBzgKBD1dKkjpGvUajZqhVwW4/AY6BwqucflasjAq9IPPcu5/+s4ittsXiDlKV66xHzTlKOcOBsVUEofzOQpN/zutktG9KG1zBsdhP6btM/c/5pehHJMX4gnZJfXVx/pVxzFG/eQysvGJ2F8dxKggfdJN7wd/QYJDaaJySW5cduL7bWoo7yXssAWobXnCedji+SwCprDmtGQEpyeOq03/7hyQbMe6m4iFbw2bsJGsAXHtnVVxFBoIp8wEGxKY5ji+p7jUe20vPomJ5VvAqEegV+nRq99O66MbbK9/s1+/6gILl7P80Sq5jNUA="

//tag, adata, iv lengths in bits
const GCM_TAG_LENGTH = 16 * 8
const GCM_AAD_LENGTH = 16 * 8
const GCM_NONCE_LENGTH = 12 * 8

let bkey = sjcl.codec.base64.toBits(key)
let bdata = sjcl.codec.base64.toBits(cipherText)
let cipher = new sjcl.cipher.aes(bkey)

let aad = sjcl.bitArray.bitSlice(bdata, 0, GCM_AAD_LENGTH)
let iv = sjcl.bitArray.bitSlice(aad, GCM_NONCE_LENGTH * -1)
let tag = sjcl.bitArray.bitSlice(bdata, GCM_TAG_LENGTH * -1)
let data = sjcl.bitArray.bitSlice(bdata, GCM_AAD_LENGTH, GCM_TAG_LENGTH * -1)
let decryptedContent = ''

let decbits = sjcl.mode.gcm.decrypt(cipher,data,iv,aad,tag)
decryptedContent = sjcl.codec.utf8String.fromBits(decbits)
console.log('decryptedContent', decryptedContent) // empty

key并且cipherText已经在 python (aes-gcm, 128bitkey) 中加密。有人知道如何解密吗?有没有 sjcl.js 的替代品和文档?谢谢!

注意:我已经使用 NodeJS Crypto lib 对其进行了解密,但 Crypto lib 与浏览器不兼容。浏览它会产生一个繁重的脚本,所以我正在寻找与浏览器兼容的轻量级 javascript lib。这是我使用 NodeJs 的代码:

function decrypt(key, content) {
  return new Promise((resolve, reject) => {
    let keyBuffer = new Buffer(key, 'base64')

    const AES_KEY_SIZE = keyBuffer.length * 8
    const GCM_TAG_LENGTH = 16
    const GCM_AAD_LENGTH = 16
    const GCM_NONCE_LENGTH = 12

    let contentBuffer = new Buffer(content, 'base64')
    let aad = contentBuffer.slice(0, GCM_AAD_LENGTH)
    let iv = aad.slice(GCM_NONCE_LENGTH * -1)
    let tag = contentBuffer.slice(GCM_TAG_LENGTH * -1)
    let cipherText = contentBuffer.slice(GCM_AAD_LENGTH, GCM_TAG_LENGTH * -1)
    let decryptedContent = ''

    try {
        let decipher = crypto.createDecipheriv(`aes-${AES_KEY_SIZE}-gcm`, keyBuffer, iv)
        decipher.setAAD(aad)
        decipher.setAuthTag(tag)
        decryptedContent = decipher.update(cipherText, 'binary', 'utf8') + decipher.final('utf8')
        return resolve(decryptedContent)
    } catch (e) {
        reject(e.message || e)
    }
})}
4

1 回答 1

0

最后我找到了原因,马腾你是对的。sjcl.js尝试从解密的内容中提取标签,但我已经提取了标签,所以这就是问题所在。换行:

let data = sjcl.bitArray.bitSlice(bdata, GCM_AAD_LENGTH, GCM_TAG_LENGTH * -1)

用这条线:

let data = sjcl.bitArray.bitSlice(bdata, GCM_AAD_LENGTH)

并解决了这个问题。这是最终(工作)版本:

let key = "[base64 key]"
let cipherText ="[base64 encrypted data]"
const GCM_TAG_LENGTH = 16 *8
const GCM_AAD_LENGTH = 16 *8
const GCM_NONCE_LENGTH = 12 *8

let bkey = sjcl.codec.base64.toBits(key)
let bdata = sjcl.codec.base64.toBits(cipherText)
let cipher = new sjcl.cipher.aes(bkey)


let aad =sjcl.bitArray.bitSlice(bdata, 0, GCM_AAD_LENGTH)
let iv = sjcl.bitArray.bitSlice(aad, GCM_NONCE_LENGTH * -1)
let tag =sjcl.bitArray.bitSlice(bdata, GCM_TAG_LENGTH * -1)
let data = sjcl.bitArray.bitSlice(bdata, GCM_AAD_LENGTH)
let decryptedContent = ''

let decbits = sjcl.mode.gcm.decrypt(cipher, data, iv, aad, GCM_TAG_LENGTH)
decryptedContent = sjcl.codec.utf8String.fromBits(decbits)
console.log('decryptedContent', decryptedContent)
于 2018-04-11T11:56:52.593 回答