Created
June 13, 2024 08:12
-
-
Save herrdommel/0537362176073fa0daab0f5bd213848f to your computer and use it in GitHub Desktop.
Ansible vault decryption in NodeJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const crypto = require('crypto'); | |
const password = "password"; | |
const vault = `$ANSIBLE_VAULT;1.1;AES256 | |
33343835306666636239373663396363643766613363343837646633343933376633323964663030 | |
3134616235646661306436643134383333633730376233650a663466323032343633383061336461 | |
36393261363338616337613039363435313631343437323164386661326633313339396238396236 | |
3462393338636632650a653036663266373533343232393838343161396564333963643632653932 | |
30386135636131656130346537356637396139323134386162306431376564346537633566666532 | |
6331323061373237336639356165393563613765663864366231`; | |
const splitInput = (vault) => { | |
const vaultNoHeader = vault.split("\n").slice(1).join(""); | |
const [salt, hmac, payload] = vaultNoHeader.split("0a").map(e => Buffer.from(e, "hex")); | |
return [salt.toString(), hmac.toString(), payload.toString()]; | |
} | |
const deriveKey = (password, salt, iterations = 10000, keyLen = 80, algo = "sha256") => { | |
const saltBuffer = Buffer.from(salt.toString(), "hex") | |
const derivedKey = crypto.pbkdf2Sync(password, saltBuffer, iterations, keyLen, algo); | |
return derivedKey.toString("hex"); | |
} | |
const checkHmac = (key, verify, algo = "sha256") => { | |
const hmac = crypto.createHmac(algo, Buffer.from(key, "hex")); | |
hmac.update(Buffer.from(payload, "hex")); | |
const digest = hmac.digest().toString("hex") | |
if (digest !== verify) { | |
throw new Error("HMac invalid"); | |
} | |
} | |
const convert = (key, nonce, algo = 'aes-256-ctr') => { | |
const decipher = crypto.createDecipheriv(algo, Buffer.from(key, "hex"), Buffer.from(nonce, "hex")); | |
let decrypted = decipher.update(Buffer.from(payload, "hex")); | |
decrypted = Buffer.concat([decrypted, decipher.final()]); | |
return decrypted.toString("utf-8"); | |
} | |
const [salt, hmac, payload] = splitInput(vault); | |
const derivedKey = deriveKey(password, salt); | |
const hmacKey = derivedKey.slice(64, 128); | |
const aesKey = derivedKey.slice(0, 64); | |
const nonce = derivedKey.slice(128); | |
checkHmac(hmacKey, hmac); | |
console.log(convert(aesKey, nonce)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is basically a NodeJS version of what is described here: https://www.bloggingforlogging.com/2018/05/20/decrypting-the-secrets-of-ansible-vault-in-powershell/