Reputation: 43
I am currently working on a Node.js script, which logs me into a website and automatically opens the browser with me being logged in. I have been trying to add a cookie (gathered from the login POST-request) to the "cookie" database of chrome, but I am failing at getting the encryption right. The Stackoverflow thread, I came along regarding the encryption of Cookies was this one: Chrome 80 how to decode cookies But that thread was about decrypting a cookie and not encrypting it.
function encryptCookie(cookie, key){
const iv = crypto.randomBytes(16);
let cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(cookie);
encrypted = Buffer.concat([Buffer.from('v10'), encrypted, cipher.final()]);
console.log(`Encrypted: ${encrypted}`);
return encrypted;
}
As for the "key" I am using the decrypted Key from Local State. (I decrypted the key using a DPAPI module.) I know that the encrypted cookie always starts with v10 so i added it as a prefix, but the encrypted Cookie is still too short.
I know I could work with a webscraper or just safe my password on the page, but I wanted to interact with the cookie Database and HTTP-requests.
Upvotes: 4
Views: 3167
Reputation: 49251
In the linked answer the structure of the data is described as follows:
The encrypted data start with the ASCII encoding of v10 (i.e. 0x763130), followed by the 12 bytes nonce, the actual ciphertext and finally the 16 bytes authentication tag.
I. e. the data is structured as follows:
The length is: 3 + 12 + ciphertextlength + 16. Furthermore, since no padding is used in GCM mode, the length of the ciphertext is the same as that of the plaintext.
Among other things, the posted code uses a wrong IV length, does not concatenate the IV and does not take the authentication tag into account.
One possible implementation of encryption/decryption is:
var crypto = require('crypto');
function encryptCookie(cookie, key){
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
const encryptedCookie = Buffer.concat(
[
Buffer.from('v10'), // prefix
iv, // 12 bytes nonce
cipher.update(cookie), // cookie data
cipher.final(),
cipher.getAuthTag() // 16 bytes authentication
]);
return encryptedCookie;
}
function decryptCookie(encryptedCookie, key){
const prefix = encryptedCookie.slice(0, 3); // prefix
const iv = encryptedCookie.slice(3, 3 + 12); // 12 bytes nonce
const ciphertext = encryptedCookie.slice(3 + 12, encryptedCookie.length - 16); // encrypted cookie
const authTag = encryptedCookie.slice(encryptedCookie.length - 16); // 12 bytes authentication tag
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
const decryptedCookie = Buffer.concat(
[
decipher.update(ciphertext), // encrypted cookie
decipher.final(),
]);
return decryptedCookie;
}
// Encryption
const cookie = Buffer.from('The test cookie with some data');
const key = Buffer.from('01234567890123456789012345678901');
const encryptedCookie = encryptCookie(cookie, key);
console.log(encryptedCookie);
console.log(encryptedCookie.length);
// Decryption
const decryptedCookie = decryptCookie(encryptedCookie, key);
console.log(decryptedCookie.toString('utf8'));
For the sample cookie with a length of 30 bytes the encrypted data has a length of 3 + 12 + 30 + 16 = 61 bytes.
Upvotes: 3