AES 256 GCM encryption decryption in nodejs










0














I am implementing a basic encryption/decryption set of functions in nodejs and I keep getting the following error in the decryption part:
Error: Unsupported state or unable to authenticate data



This is my code so far:



import crypto from 'crypto'
import logger from './logger'

const ALGORITHM = 'aes-256-gcm'

export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
// iv stands for "initialization vector"
const iv = Buffer.from(crypto.randomBytes(12), 'utf8')
logger.debug('iv: ', iv)
const encryptor = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
logger.debug('encryptor: ', encryptor)
logger.debug('dataBuffer: ', dataBuffer)
return Buffer.concat([iv, encryptor.update(dataBuffer, 'utf8'), encryptor.final()])


export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
const iv = dataBuffer.slice(0, 96)

const decryptor = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
return Buffer.concat([decryptor.update(dataBuffer.slice(96), 'utf8'), decryptor.final()])



My error happens in the last line of the decrypt function. I am storing the iv as part of the dataBuffer.



Thanks in advance!










share|improve this question













migrated from security.stackexchange.com Nov 12 '18 at 19:49


This question came from our site for information security professionals.










  • 1




    I might be wrong on this, but isn't the slice specifying the number of bytes (not bits)? If that is the case, then you should be slicing 12 bytes, not 96.
    – TheGreatContini
    Nov 12 '18 at 20:59















0














I am implementing a basic encryption/decryption set of functions in nodejs and I keep getting the following error in the decryption part:
Error: Unsupported state or unable to authenticate data



This is my code so far:



import crypto from 'crypto'
import logger from './logger'

const ALGORITHM = 'aes-256-gcm'

export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
// iv stands for "initialization vector"
const iv = Buffer.from(crypto.randomBytes(12), 'utf8')
logger.debug('iv: ', iv)
const encryptor = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
logger.debug('encryptor: ', encryptor)
logger.debug('dataBuffer: ', dataBuffer)
return Buffer.concat([iv, encryptor.update(dataBuffer, 'utf8'), encryptor.final()])


export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
const iv = dataBuffer.slice(0, 96)

const decryptor = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
return Buffer.concat([decryptor.update(dataBuffer.slice(96), 'utf8'), decryptor.final()])



My error happens in the last line of the decrypt function. I am storing the iv as part of the dataBuffer.



Thanks in advance!










share|improve this question













migrated from security.stackexchange.com Nov 12 '18 at 19:49


This question came from our site for information security professionals.










  • 1




    I might be wrong on this, but isn't the slice specifying the number of bytes (not bits)? If that is the case, then you should be slicing 12 bytes, not 96.
    – TheGreatContini
    Nov 12 '18 at 20:59













0












0








0







I am implementing a basic encryption/decryption set of functions in nodejs and I keep getting the following error in the decryption part:
Error: Unsupported state or unable to authenticate data



This is my code so far:



import crypto from 'crypto'
import logger from './logger'

const ALGORITHM = 'aes-256-gcm'

export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
// iv stands for "initialization vector"
const iv = Buffer.from(crypto.randomBytes(12), 'utf8')
logger.debug('iv: ', iv)
const encryptor = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
logger.debug('encryptor: ', encryptor)
logger.debug('dataBuffer: ', dataBuffer)
return Buffer.concat([iv, encryptor.update(dataBuffer, 'utf8'), encryptor.final()])


export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
const iv = dataBuffer.slice(0, 96)

const decryptor = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
return Buffer.concat([decryptor.update(dataBuffer.slice(96), 'utf8'), decryptor.final()])



My error happens in the last line of the decrypt function. I am storing the iv as part of the dataBuffer.



Thanks in advance!










share|improve this question













I am implementing a basic encryption/decryption set of functions in nodejs and I keep getting the following error in the decryption part:
Error: Unsupported state or unable to authenticate data



This is my code so far:



import crypto from 'crypto'
import logger from './logger'

const ALGORITHM = 'aes-256-gcm'

export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
// iv stands for "initialization vector"
const iv = Buffer.from(crypto.randomBytes(12), 'utf8')
logger.debug('iv: ', iv)
const encryptor = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
logger.debug('encryptor: ', encryptor)
logger.debug('dataBuffer: ', dataBuffer)
return Buffer.concat([iv, encryptor.update(dataBuffer, 'utf8'), encryptor.final()])


export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
const iv = dataBuffer.slice(0, 96)

const decryptor = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
return Buffer.concat([decryptor.update(dataBuffer.slice(96), 'utf8'), decryptor.final()])



My error happens in the last line of the decrypt function. I am storing the iv as part of the dataBuffer.



Thanks in advance!







encryption aes node.js






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 '18 at 19:01









vanvasquezvanvasquez

3651410




3651410




migrated from security.stackexchange.com Nov 12 '18 at 19:49


This question came from our site for information security professionals.






migrated from security.stackexchange.com Nov 12 '18 at 19:49


This question came from our site for information security professionals.









  • 1




    I might be wrong on this, but isn't the slice specifying the number of bytes (not bits)? If that is the case, then you should be slicing 12 bytes, not 96.
    – TheGreatContini
    Nov 12 '18 at 20:59












  • 1




    I might be wrong on this, but isn't the slice specifying the number of bytes (not bits)? If that is the case, then you should be slicing 12 bytes, not 96.
    – TheGreatContini
    Nov 12 '18 at 20:59







1




1




I might be wrong on this, but isn't the slice specifying the number of bytes (not bits)? If that is the case, then you should be slicing 12 bytes, not 96.
– TheGreatContini
Nov 12 '18 at 20:59




I might be wrong on this, but isn't the slice specifying the number of bytes (not bits)? If that is the case, then you should be slicing 12 bytes, not 96.
– TheGreatContini
Nov 12 '18 at 20:59












1 Answer
1






active

oldest

votes


















0














I realized I had made a couple of mistakes with the original code that I posted, one of them as @TheGreatContini remarked was the size of the slicing which was being done in bits instead of bytes as it should be. Still, the biggest piece that I was missing was the authTag which always should be included in the decipher function setup.



Here is my working code for anybody interested for future references:



import crypto from 'crypto'
import logger from './logger'

const ALGORITHM = 'aes-256-gcm'

export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
// iv stands for "initialization vector"
const iv = crypto.randomBytes(12)
const cipher = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
const encryptedBuffer = Buffer.concat([cipher.update(dataBuffer), cipher.final()])
const authTag = cipher.getAuthTag()
let bufferLength = Buffer.alloc(1)
bufferLength.writeUInt8(iv.length, 0)
return Buffer.concat([bufferLength, iv, authTag, encryptedBuffer])


export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
const ivSize = dataBuffer.readUInt8(0)
const iv = dataBuffer.slice(1, ivSize + 1)
// The authTag is by default 16 bytes in AES-GCM
const authTag = dataBuffer.slice(ivSize + 1, ivSize + 17)
const decipher = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
decipher.setAuthTag(authTag)
return Buffer.concat([decipher.update(dataBuffer.slice(ivSize + 17)), decipher.final()])






share|improve this answer




















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53269132%2faes-256-gcm-encryption-decryption-in-nodejs%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    I realized I had made a couple of mistakes with the original code that I posted, one of them as @TheGreatContini remarked was the size of the slicing which was being done in bits instead of bytes as it should be. Still, the biggest piece that I was missing was the authTag which always should be included in the decipher function setup.



    Here is my working code for anybody interested for future references:



    import crypto from 'crypto'
    import logger from './logger'

    const ALGORITHM = 'aes-256-gcm'

    export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
    // iv stands for "initialization vector"
    const iv = crypto.randomBytes(12)
    const cipher = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
    const encryptedBuffer = Buffer.concat([cipher.update(dataBuffer), cipher.final()])
    const authTag = cipher.getAuthTag()
    let bufferLength = Buffer.alloc(1)
    bufferLength.writeUInt8(iv.length, 0)
    return Buffer.concat([bufferLength, iv, authTag, encryptedBuffer])


    export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
    const ivSize = dataBuffer.readUInt8(0)
    const iv = dataBuffer.slice(1, ivSize + 1)
    // The authTag is by default 16 bytes in AES-GCM
    const authTag = dataBuffer.slice(ivSize + 1, ivSize + 17)
    const decipher = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
    decipher.setAuthTag(authTag)
    return Buffer.concat([decipher.update(dataBuffer.slice(ivSize + 17)), decipher.final()])






    share|improve this answer

























      0














      I realized I had made a couple of mistakes with the original code that I posted, one of them as @TheGreatContini remarked was the size of the slicing which was being done in bits instead of bytes as it should be. Still, the biggest piece that I was missing was the authTag which always should be included in the decipher function setup.



      Here is my working code for anybody interested for future references:



      import crypto from 'crypto'
      import logger from './logger'

      const ALGORITHM = 'aes-256-gcm'

      export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
      // iv stands for "initialization vector"
      const iv = crypto.randomBytes(12)
      const cipher = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
      const encryptedBuffer = Buffer.concat([cipher.update(dataBuffer), cipher.final()])
      const authTag = cipher.getAuthTag()
      let bufferLength = Buffer.alloc(1)
      bufferLength.writeUInt8(iv.length, 0)
      return Buffer.concat([bufferLength, iv, authTag, encryptedBuffer])


      export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
      const ivSize = dataBuffer.readUInt8(0)
      const iv = dataBuffer.slice(1, ivSize + 1)
      // The authTag is by default 16 bytes in AES-GCM
      const authTag = dataBuffer.slice(ivSize + 1, ivSize + 17)
      const decipher = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
      decipher.setAuthTag(authTag)
      return Buffer.concat([decipher.update(dataBuffer.slice(ivSize + 17)), decipher.final()])






      share|improve this answer























        0












        0








        0






        I realized I had made a couple of mistakes with the original code that I posted, one of them as @TheGreatContini remarked was the size of the slicing which was being done in bits instead of bytes as it should be. Still, the biggest piece that I was missing was the authTag which always should be included in the decipher function setup.



        Here is my working code for anybody interested for future references:



        import crypto from 'crypto'
        import logger from './logger'

        const ALGORITHM = 'aes-256-gcm'

        export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
        // iv stands for "initialization vector"
        const iv = crypto.randomBytes(12)
        const cipher = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
        const encryptedBuffer = Buffer.concat([cipher.update(dataBuffer), cipher.final()])
        const authTag = cipher.getAuthTag()
        let bufferLength = Buffer.alloc(1)
        bufferLength.writeUInt8(iv.length, 0)
        return Buffer.concat([bufferLength, iv, authTag, encryptedBuffer])


        export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
        const ivSize = dataBuffer.readUInt8(0)
        const iv = dataBuffer.slice(1, ivSize + 1)
        // The authTag is by default 16 bytes in AES-GCM
        const authTag = dataBuffer.slice(ivSize + 1, ivSize + 17)
        const decipher = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
        decipher.setAuthTag(authTag)
        return Buffer.concat([decipher.update(dataBuffer.slice(ivSize + 17)), decipher.final()])






        share|improve this answer












        I realized I had made a couple of mistakes with the original code that I posted, one of them as @TheGreatContini remarked was the size of the slicing which was being done in bits instead of bytes as it should be. Still, the biggest piece that I was missing was the authTag which always should be included in the decipher function setup.



        Here is my working code for anybody interested for future references:



        import crypto from 'crypto'
        import logger from './logger'

        const ALGORITHM = 'aes-256-gcm'

        export const encrypt = (keyBuffer, dataBuffer, aadBuffer) =>
        // iv stands for "initialization vector"
        const iv = crypto.randomBytes(12)
        const cipher = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
        const encryptedBuffer = Buffer.concat([cipher.update(dataBuffer), cipher.final()])
        const authTag = cipher.getAuthTag()
        let bufferLength = Buffer.alloc(1)
        bufferLength.writeUInt8(iv.length, 0)
        return Buffer.concat([bufferLength, iv, authTag, encryptedBuffer])


        export const decrypt = (keyBuffer, dataBuffer, aadBuffer) =>
        const ivSize = dataBuffer.readUInt8(0)
        const iv = dataBuffer.slice(1, ivSize + 1)
        // The authTag is by default 16 bytes in AES-GCM
        const authTag = dataBuffer.slice(ivSize + 1, ivSize + 17)
        const decipher = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
        decipher.setAuthTag(authTag)
        return Buffer.concat([decipher.update(dataBuffer.slice(ivSize + 17)), decipher.final()])







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 13 '18 at 2:03









        vanvasquezvanvasquez

        3651410




        3651410



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53269132%2faes-256-gcm-encryption-decryption-in-nodejs%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Barbados

            How to read a connectionString WITH PROVIDER in .NET Core?

            Node.js Script on GitHub Pages or Amazon S3