buttercup / buttercup-core

:tophat: The mighty NodeJS password vault
http://buttercup.pw/
MIT License
467 stars 57 forks source link

How to Decrypt Vault _Without_ Buttercup? #308

Closed zicklag closed 2 years ago

zicklag commented 2 years ago

To make me more comfortable with the fact that I will be able to decrypt the buttercup vaultm even if, for whatever reason, I didn't have access to buttercup itself, I would like to know the exact format used currently for the buttercup vault, and what steps I'd take to decrypt it manually, probably in another programming language ( i.e. Rust ) or just with CLI tools if such tools exist that will do the decryption necessary.

For instance, it appears the file is basically a header of some sort followed by encrypted, base64 encoded JSON, but what is the exact format, and maybe what is the pseudo code for decrypting the data using only the master password?

I can go comb the source code if necessary, but I appreciate any guidance to make that a little bit easier if it's not too much trouble. Thanks!

perry-mitchell commented 2 years ago

Hi @zicklag - Good question. I understand that you want the piece of mind of being able to tear it apart yourself, though I honestly doubt that it's worth the trouble implementing the entire Buttercup format/parsing logic in another language. Using the following code in NodeJS (v14 or newer) will allow you to output a JSON blob of your entire vault:

const {
    Credentials,
    FileDatasource,
    Vault,
    createVaultFacade,
    init
} = require("buttercup");

const VAULT = "/Users/perry/Desktop/test.bcup";
const PASSWORD = "test";

(async function() {
    init();
    const fds = new FileDatasource(Credentials.fromDatasource({
        path: VAULT
    }, PASSWORD));
    const {
        Format,
        history
    } = await fds.load(Credentials.fromPassword(PASSWORD));
    const vault = Vault.createFromHistory(history, Format);
    console.log(createVaultFacade(vault));
})();

You'll get something like this:

{
  _tag: '79f2bec7-2bdc-4a80-8815-64ebda747354',
  _ver: 2,
  type: 'vault',
  id: '67350ce2-f33d-43f3-a9cc-2770a97fa305',
  attributes: {
    BC_ATTACHMENTS_KEY: 'mSM92dof%!KgoQ6O4k!_f$:97oP9#<PdS>eSY.D^=6t;&=z:'
  },
  groups: [
    {
      type: 'group',
      id: 'f8d35257-f91f-4e3c-9bab-103904cb7124',
      title: 'General',
      attributes: {},
      parentID: '0'
    },
    {
      type: 'group',
      id: 'fdacfab8-78be-4eba-b3a9-a990f3036b26',
      title: 'Sub1',
      attributes: {},
      parentID: 'f8d35257-f91f-4e3c-9bab-103904cb7124'
    },
    {
      type: 'group',
      id: 'c2cdb51c-1603-4b82-8554-54623b17a1a2',
      title: 'Trash',
      attributes: [Object],
      parentID: '0'
    },
    {
      type: 'group',
      id: 'd80c8731-3056-4a66-9c06-d9864f280d3b',
      title: 'This could break',
      attributes: {},
      parentID: 'c2cdb51c-1603-4b82-8554-54623b17a1a2'
    }
  ],
  entries: [
    {
      id: 'd425c187-bec2-4502-8920-55566922dd14',
      type: 'login',
      fields: [Array],
      parentID: 'f8d35257-f91f-4e3c-9bab-103904cb7124',
      _history: [],
      _changes: [Array]
    },
    {
      id: '58578c02-7561-4961-a7ad-1569e60fbc42',
      type: 'login',
      fields: [Array],
      parentID: 'f8d35257-f91f-4e3c-9bab-103904cb7124',
      _history: [],
      _changes: [Array]
    }
}

This is not an exact representation of what's inside your vault, however.. a facade in Buttercup terms is just an intermediary format for working with UIs. Buttercup uses 2 different vault formats, A and B currently. Yours is most likely in format A, which is a series of commands that make up your vault (history). It's be difficult to implement the parsing logic yourself. You can read more about both formats here

perry-mitchell commented 2 years ago

The vault format, whatever it is, is converted to a string (either commands in format A, or JSON in format B) and then gzipped + encrypted in AES CBC mode, using 256 keys and HMAC. Encryption is standard but how it's packaged is entirely custom. Running this through standard AES decryption programs will not work.

My own library iocane is used for encryption and decryption, including that of binary files when being used as attachments.

I hope this answers your query - Please let me know if there's any further information I can share :)

zicklag commented 2 years ago

OK, cool, thanks for the info, I'll come back here if I have any other question, but I think that's enough.

For what it's worth, I don't really care to be able to fully parse the buttercup database, I just want to be able to get a dump of the raw, decrypted data so that I can read it, just in case I get on a system where I for some-reason can't install electron or NodeJS or something and I want to be able to dump the buttercup data raw so I can get to my secrets.

It's really super paranoia, as NodeJS is rather portable, but still I thought it a worthy investigation. :)

fkasler commented 1 year ago

@zicklag you should check out this buttercup dump utility: https://github.com/fkasler/butterbrute/blob/main/dump_vault.mjs

It's part of a project that might help if you also forgot your password ;)