Store sensitive information inside keepass database from c#
Asked Answered
B

3

20

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?

Britanybritches answered 13/1, 2011 at 13:1 Comment(3)
Can you try rewriting this a little more clearly? What are you trying to accomplish or avoid?Warms
I'm trying to open a keepass database from a winform application to use sensitive informations without leave them uncrypted.Britanybritches
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..Hitch
S
44

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();
Specialism answered 27/1, 2012 at 2:56 Comment(10)
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.Pili
KeePassLib.Keys & KeePassLib.SerializationSpecialism
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 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.Caloric
how secure safe masterpw value ? in app.config ?Crone
@Crone You can store your masterpw in a secured database.Fishtail
@Fishtail 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.Specialism
any sample using DPAPI for store the key?Crone
@Crone 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.Specialism
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<<anonymous type: string Group, string Title, string Username, string Password>>' does not contain a definition for 'Dump' and no accessible extension method 'Dump' accepting a first argument of type 'IEnumerable<<anonymous type: string Group, string Title, string Username, string Password>>' could be found (are you missing a using directive or an assembly reference?) Any solution?Turgent
Unfortunately this only works with .NET Framework, not .Net Core. The missing library is System.Security.Cryptography.ProtectedMemory which exists in .Net Framework only.Crookes
A
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++;
        }
    }
Aurea answered 13/8, 2018 at 11:25 Comment(0)
L
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

Lunik answered 13/1, 2011 at 13:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.