Skip to content

Instantly share code, notes, and snippets.

@jordanbtucker

jordanbtucker/test1.js

Last active Mar 9, 2017
Embed
What would you like to do?
odrive decrypt testing
// The following code attempts to decrypt a filename encrypted by odrive. It
// fails when attempting to remove PKCS#7 padding from the plaintext.
const crypto = require('crypto')
// The original filename is `test.txt`. It was encrypted with odrive using the
// following password.
const password = 'password123'
const filename = 'MaUi8C8YFNhN5dzbjNtqgXx3Cm-PwyUYxR1Rl4JauHHrjrTMo0k9poE='
// Information gathered from https://forum.odrive.com/t/encryption-questions-key-storage-decryption-process-and-others/2094/2
const VERSION_SIZE = 1
const SALT_SIZE = 64 / 8
const BLOCK_SIZE = 128 / 8
const HEADER_SIZE = VERSION_SIZE + SALT_SIZE + BLOCK_SIZE
const KDF_ITER = 5000
const KEY_SIZE = 256 / 8
const KDF_DIGEST = 'sha256'
const ENC_ALG = 'aes-256-cbc'
// Convert the URL-safe Base64 string to Base64.
const filenameBase64 = filename.replace(/-/g, '+').replace(/_/g, '/')
// Decode the Base64 string.
const data = Buffer.from(filenameBase64, 'base64')
console.log('data', data.toString('hex'))
// The first byte is an internal version number.
const version = data.slice(0, VERSION_SIZE)
// The next eight bytes is the salt.
const salt = data.slice(VERSION_SIZE, VERSION_SIZE + SALT_SIZE)
console.log('salt', salt.toString('hex'))
// The next eight bytes is the IV.
const iv = data.slice(VERSION_SIZE + SALT_SIZE, HEADER_SIZE)
console.log('iv', iv.toString('hex'))
// The remaining bytes is the ciphertext.
const ciphertext = data.slice(HEADER_SIZE, data.length)
console.log('ciphertext', ciphertext.toString('hex'))
// Use PBKDF2 with the password and salt to derive and encryption key.
const key = crypto.pbkdf2Sync(password, salt, KDF_ITER, KEY_SIZE, KDF_DIGEST)
console.log('key', key.toString('hex'))
// Use the key and IV to create an AES-256-CBC decryptor.
const decipher = crypto.createDecipheriv(ENC_ALG, key, iv)
// For testing, we've set the padding to false. Normally you'd set this to true
// or just leave this line out.
decipher.setAutoPadding(false)
// Decrypting the ciphertext.
const plaintext1 = decipher.update(ciphertext)
const plaintext2 = decipher.final()
const plaintext = Buffer.concat([plaintext1, plaintext2])
console.log('plaintext', plaintext.toString('hex'))
// The plaintext should start with 0x00000000 and end with 0x04040404, but it
// doesn't in this case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment