AES 256 GCM encryption decryption in nodejs
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
migrated from security.stackexchange.com Nov 12 '18 at 19:49
This question came from our site for information security professionals.
add a comment |
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
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
add a comment |
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
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
encryption aes node.js
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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()])
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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()])
add a comment |
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()])
add a comment |
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()])
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()])
answered Nov 13 '18 at 2:03
vanvasquezvanvasquez
3651410
3651410
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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