18

I have a project where I have to handle sensitive data.

How do I open a keepass database from C# to use the data?

I have downloaded the source. I will look in it to get what I need. Any other idea?

Dale K
  • 25,246
  • 15
  • 42
  • 71
hotips
  • 2,575
  • 7
  • 42
  • 59
  • 1
    Can you try rewriting this a little more clearly? What are you trying to accomplish or avoid? – Randy Minder Jan 13 '11 at 13:06
  • I'm trying to open a keepass database from a winform application to use sensitive informations without leave them uncrypted. – hotips Jan 13 '11 at 13:09
  • i ve never used keepass database.. but i think storing encrypted data in MSSQL Databases are also safe... and easy to implement. However if you are using a 3rd party solution they must have an api to deal with their data.. – Shekhar_Pro Jan 13 '11 at 13:10

3 Answers3

42

I thought about reading a KeyPass 2 database so I added a reference to KeyPass.exe in Linqpad and started to experiment. To my surprise and without any outside help (a testament to a good API), I was reading the database after only a few minutes. Here's how I did it:

var dbpath = @"C:\path\to\passwords.kdbx";
var masterpw = "Your$uper$tr0ngMst3rP@ssw0rd";

var ioConnInfo = new IOConnectionInfo { Path = dbpath };
var compKey = new CompositeKey();
compKey.AddUserKey(new KcpPassword(masterpw));

var db = new KeePassLib.PwDatabase();
db.Open(ioConnInfo, compKey, null);

var kpdata = from entry in db.RootGroup.GetEntries(true)
                select new
                {
                    Group = entry.ParentGroup.Name,
                    Title = entry.Strings.ReadSafe("Title"),
                    Username = entry.Strings.ReadSafe("UserName"),
                    Password = entry.Strings.ReadSafe("Password"),
                    URL = entry.Strings.ReadSafe("URL"),
                    Notes = entry.Strings.ReadSafe("Notes")

                };                                                                                  

kpdata.Dump(); // this is how Linqpad outputs stuff
db.Close();
Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346
  • What namespaces did you have to include? I'm using C# in SSIS and added the reference to KeePass.exe, then include KeePassLib.Keys, KeePass.Collections, etc, but it's not liking the db.RootGroup.GetEntries(true) line. – jared Jan 22 '13 at 20:34
  • KeePassLib.Keys & KeePassLib.Serialization – Ronnie Overby Feb 09 '13 at 19:54
  • 2
    **Hint:** You can let LinqPad store the master password in your demo code via the **Password manager** menu item in the **File** menu, then retrieving it via `var masterpw = Util.GetPassword("KeePassMaster");` as described [here](http://stackoverflow.com/a/12006038/1016343) in more detail. This way, it is being stored by using CryptoAPI and you can safely give away the demo code without having to take care about removing the password. – Matt Jan 13 '16 at 09:35
  • how secure safe masterpw value ? in app.config ? – Kiquenet Sep 10 '16 at 16:14
  • @Kiquenet You can store your masterpw in a secured database. – hypnagogia Nov 09 '18 at 18:32
  • 1
    @hypnagogia It's not really that simple: how does one secure a database? What does "secure" mean? Key storage isn't easy to do correctly. I recommend storing your key using technology that is designed for that purpose. DPAPI is a popular means on Windows computers. – Ronnie Overby Nov 10 '18 at 17:35
  • any sample using ***DPAPI*** for _store the key_? – Kiquenet Nov 12 '18 at 08:52
  • @Kiquenet It's also worth mentioning that `CompositeKey.AddUserKey(new KcpUserAccount())` may meet your needs, too. That uses DPAPI to protected a user specific key in an app data folder. Saving/Loading the key is managed by Keepass. – Ronnie Overby Nov 14 '18 at 15:07
  • I know its an old thread, but im trying to use that code in NET5.0 Currently im getting a red underline at `dump` and the message says: `CS1061'IEnumerable<>' does not contain a definition for 'Dump' and no accessible extension method 'Dump' accepting a first argument of type 'IEnumerable<>' could be found (are you missing a using directive or an assembly reference?)` Any solution? – Beardy Aug 17 '21 at 09:19
1

Here is an extension of the original answer from Ronnie - walking the keepass tree recursively. This outputs a format that jsTree can use by the way.

    public static void JsonData() {
        var dbpath = Web.MapPath(@"your-password-file.kdbx");
        var masterpw = "Your$uper$tr0ngMst3rP@ssw0rd";
        var ioConnInfo = new IOConnectionInfo { Path = dbpath };
        var compKey = new CompositeKey();
        compKey.AddUserKey(new KcpPassword(masterpw));
        var db = new KeePassLib.PwDatabase();
        db.Open(ioConnInfo, compKey, null);

        //get everything
        var kpdata = from entry in db.RootGroup.GetEntries(true)
                                 select new {
                                     Group = entry.ParentGroup.Name,
                                     Title = entry.Strings.ReadSafe("Title"),
                                     Username = entry.Strings.ReadSafe("UserName"),
                                     Password = entry.Strings.ReadSafe("Password"),
                                     URL = entry.Strings.ReadSafe("URL"),
                                     Notes = entry.Strings.ReadSafe("Notes")
                                 };
        var kproot = db.RootGroup.Groups;
        string lastGroup = "#";
        uint sc = 0;
        int depth = 0;
        var parent = "#"; //root is # parent
        foreach (var entry in kproot) {
            PwGroup pwGroup = db.RootGroup.Groups.GetAt(sc);
            Web.Write(" { \"id\" : \"" + (sc) + "\", \"parent\" : \"" + parent + "\", \"text\" : \"" + pwGroup.Name.HtmlEncode() + "\" },\n");

            WriteChildren(pwGroup,sc+"", depth + 1);
            sc++;
        }
        db.Close();
    }

    public static void WriteChildren(PwGroup pwGroup, string parentID,int depth) {
        uint sc = 0;
        //if(depth>3)return;  //used to prevent too much recursion
        foreach (var entry in pwGroup.Groups) {
            var subGroup = pwGroup.Groups.GetAt(sc);
            var curID = (parentID+"_"+sc);
            Web.Write(" { \"id\" : \"" + curID + "\", \"parent\" : \"" + parentID + "\", \"text\" : \"" + subGroup.Name.JsEncode() + "\"},\n");
            WriteChildren(subGroup, curID, depth+1);
            WriteLeaves(subGroup, curID, depth);
            sc++;
        }
    }
    public static void WriteLeaves(PwGroup pwGroup, string parentID,int depth) {
        uint sc = 0;
        //if(depth>3)return;
        var entryList = pwGroup.GetEntries(false);
        foreach (var entry in entryList) {
            var curID = (parentID+"_"+sc);
            Web.Write(" { \"id\" : \"" + curID + "\", \"parent\" : \"" + parentID + "\", \"text\" : \"" + entry.Strings.ReadSafe("Title").JsEncode() + "\", \"password\" : \"" + entry.Strings.ReadSafe("Password").JsEncode() + "\", \"type\" : \"file\"},\n");
            sc++;
        }
    }
0

Check : KeePass Password Safe (For how keepass works)

Rather use the C# System.Cryptography classes and store you data enrypted in a database or txt file...

There is a KeePass-2.05-Alpha-Source.zip,The latest version of KeePass. C# source code,1919KB

abmv
  • 7,042
  • 17
  • 62
  • 100