-1

I am trying to decrypt cipher content with sjcl.js crypto library in aes algorithm(gcm mode). This is my code:

//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 and cipherText are already encrypted in python (aes-gcm, 128bitkey). Does anybody know how to decrypt it? Are there any alternatives to sjcl.js with documentation? Thanks!

NOTE: I have already decrypted it with NodeJS Crypto lib but Crypto lib is not compatable with browser. Browserifying it makes a heavy script so i am looking for broswer compatible, lightweight javascript lib.This is my code with 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)
    }
})}
William Chong
  • 2,107
  • 13
  • 24
  • Well? Does it run? How was the GCM data encrypted? We don't know if the tag size etc. is correct and we don't get any error description. Note that normally the IV is not part of the AAD data because it is already part of the calculation of the authentication tag. – Maarten Bodewes Apr 09 '18 at 19:07
  • Hi Maarten, iv, aad, tag etc is ok. I have added working nodejs version for additional info. – Ismayil Niftaliyev Apr 10 '18 at 08:09
  • Did you check the values of iv, aad, tag etc. in the code you're trying to run? Debugging crypto is often getting to know the binary input parameters of the functions. If those are OK then the result should be OK as well. – Maarten Bodewes Apr 10 '18 at 11:34

1 Answers1

0

At the end I found the reason and Maarten you were rigth. sjcl.js tries to extract tag from decrypted content but I already extracted tag so that was the issue. Replaced the line:

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

with this line:

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

And solved the issue.This is final(working) version:

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)
William Chong
  • 2,107
  • 13
  • 24