使用sjcl.js做正确的方法是什么?

时间:2018-04-09 14:27:01

标签: encryption cryptography aes aes-gcm sjcl

我试图用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

keycipherText已经在python中加密(aes-gcm,128bitkey)。有人知道怎么解密吗?有文档的sjcl.js有什么替代品吗?谢谢!

注意:我已经用NodeJS Crypto lib解密了它,但是Crypto lib与浏览器无法兼容。浏览它会产生沉重的脚本,所以我正在寻找兼容轻量级的javascript lib.This是我的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)
    }
})}

1 个答案:

答案 0 :(得分:0)

最后,我找到了原因,Maarten你是最严格的。 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)