keeweb/kdbxweb

How to load data?

Raptor399 opened this issue ยท 4 comments

Hi @antelle! First of all, thanks for your excellent work in the KeePass space! I'm a happy KeeWeb user and was excited to find this kdbxweb library!

However, I'm not able to open a password only .kdbx file created with KeeWeb. I'm using code like this:

var dataAsArrayBuffer = require('fs').readFileSync('example.kdbx', 'base64');
var credentials = new kdbxweb.Credentials(kdbxweb.ProtectedValue.fromString('examplePass'));
kdbxweb.Kdbx.load(dataAsArrayBuffer, credentials).then(db => ...);

But it throws an error like this:

{ [KdbxError: Error InvalidArg: data]
  name: 'KdbxError',
  code: 'InvalidArg',
  message: 'Error InvalidArg: data' }

The README instructions skip this bit and I haven't been able to figure this one out based on the KeeWeb or test code.

Could you add a line to the loading example under Usage to demonstrate how to correctly open a database?

Thanks for your continued support and keep up the good work!

Hi!
You should remove 'base64' from readFileSync and pass buffer to kdbxweb:

var dataAsArrayBuffer = require('fs').readFileSync('demo.kdbx').buffer;

Thanks! That was helpful.
For posterity: turns out that it still will not work with readFileSync(), but it does work with readFile() like so:

var dbFilename = "test.kdbx";
var dbPassword = "test";

fs.readFile(dbFilename, null, (err, dataAsArrayBuffer) => {
    var credentials = new kdbxweb.Credentials(kdbxweb.ProtectedValue.fromString(dbPassword));

    kdbxweb.Kdbx.load(dataAsArrayBuffer.buffer, credentials).then(db => {
        ...

        db.save().then(data => {
            fs.writeFileSync(dbFilename, new Buffer(data));
        });
    })
});

Here's a script that may probably save you an hour if you're a newby (like me an hour ago) with this library and if you're trying to load a kdbx file using async-await and a kdbx file protected only by a keyfile and not a password.

const kdbxweb = require('kdbxweb')
const fs = require('fs')
const path = require("path")
const util = require('util')
fs.readFileAsync = util.promisify(fs.readFile)

const read = async () => {
  const keyFileArrayBuffer = await fs.readFileAsync(path.join(__dirname, '../envs', 'keyfile'));
  const dataAsArrayBuffer = await fs.readFileAsync(path.join(__dirname, '../envs', 'env.kdbx'));

  const credentials = new kdbxweb.Credentials(
    kdbxweb.ProtectedValue.fromString(''), // keyfile only kdbx file
    keyFileArrayBuffer.buffer
  );

  const db = await kdbxweb.Kdbx.load(dataAsArrayBuffer.buffer, credentials)

  const entry = db.getDefaultGroup().entries[0]

  return entry
}

read()
.then((result) => {
  console.log('result', result)
})
.catch((err) => {
  console.log('err', err)
})

await version, without promisify

const kdbxweb = require("kdbxweb");
const fs = require("fs");
const argon2 = require("./argon2");
kdbxweb.CryptoEngine.setArgon2Impl(argon2.argon2);

function readFileAsync(filename, encoding) {
  return new Promise((resolve, reject) => {
    fs.readFile(filename, encoding, function (err, data) {
      if (err) reject(err);
      resolve(data);
    });
  });
}
const read = async () => {
  const creds = new kdbxweb.KdbxCredentials(
    kdbxweb.ProtectedValue.fromString("test")
  );
  const data = await readFileAsync("/tmp/testkdbx.kdbx", null);
  console.log(data);
  console.log(data.buffer);
  const db = await kdbxweb.Kdbx.load(data.buffer, creds);
  console.log(`db version: ${db.versionMajor}`);
  return res.status(200).send();
};```