Command line password manager using AES symmetric key encryption, Argon2 KDF, Key-Agent and Keepass importer

321 views
Skip to first unread message

Matthias Schmidt

unread,
Oct 14, 2018, 11:49:04 AM10/14/18
to golang-nuts

Hi Gophers,


I’ve created a command line password manager in the style of the “pass” utility by Jason A. Donenfeld (https://www.passwordstore.org/) in Go.

It uses symmetric AES encryption, Argon2 key-derivation and key-agent similar to SSH.


I would love to get your opinions on the code, the architecture, the security concept and perhaps more users on the codebase to find possible errors.


Any comments, help and pull requests are welcome.


https://github.com/ms140569/loki


Cheers,


Matthias Schmidt


EricR

unread,
Oct 15, 2018, 6:09:32 AM10/15/18
to golang-nuts
Since you're looking for opinions on the security concept, two questions spring immediately to my mind:

1. Does the daemon keep the sensitive data in locked memory that cannot be paged out? If so, how cross-platform is this?

2. How does the client communicate securely with the daemon? Which encryption protocol/handshake is used for this? (If it just uses a socket, what would prevent another process from reading out the master password?)

Regards,

Eric

Matthias Schmidt

unread,
Oct 15, 2018, 4:27:48 PM10/15/18
to golang-nuts
Hi Eric,

thanks *a lot* for your valuable feedback! I really appreciate it. See comments inline:


Am Montag, 15. Oktober 2018 12:09:32 UTC+2 schrieb EricR:
Since you're looking for opinions on the security concept, two questions spring immediately to my mind:

1. Does the daemon keep the sensitive data in locked memory that cannot be paged out? If so, how cross-platform is this?

No it doesn't. As of now i consider the root-user a good guy ;-) 
He's the only one who could access the pagefiles anyway.

So is this really an issue? If yes i could use this cross-platform solution to pin the key:


 

2. How does the client communicate securely with the daemon? Which encryption protocol/handshake is used for this? (If it just uses a socket, what would prevent another process from reading out the master password?)

It's in fact a unix domain socket file which is only accessible for the owner of the key. ( Thanks for bringing this up, i forgot to flag the file correctly - it's now fixed).
Relying on the file permissions in unix shouldn't be a problem, right?

cheers & again - many thanks,

Matthias

Christopher Nielsen

unread,
Oct 15, 2018, 5:13:32 PM10/15/18
to matthias...@gmail.com, golang-nuts
You seem to be putting a lot of trust in facilities that are trivially
exploitable to a determined attacker. For software like a password
manager, assuming the kernel is secure is a poor security model. In
addition to the existing attack surface, we live in a world where
side-channel attacks are becoming more common, e.g., Spectre and
Meltdown, so it isn't safe to assume the kernel or hardware are
secure. A password manager needs to have a robust security model that
has a minimal trust model if it is to be more than a toy.

Just my $0.02

--
Christopher Nielsen
"They who can give up essential liberty for temporary safety, deserve
neither liberty nor safety." --Benjamin Franklin
"The tree of liberty must be refreshed from time to time with the
blood of patriots & tyrants." --Thomas Jefferson

robert engels

unread,
Oct 15, 2018, 5:18:18 PM10/15/18
to m4dh...@gmail.com, matthias...@gmail.com, golang-nuts
As long as the passwords are not stored in plain text in memory - meaning they are only temporarily decoded in order to be provided (and then the memory wiped) - there is no difference than the underlying security of the file encryption on disk, no ?
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

EricR

unread,
Oct 15, 2018, 5:54:38 PM10/15/18
to golang-nuts
If the memory in which the master key resides is not locked, then it may be written to the page file. An attacker may thus boot the machine from an external disk, mount the disk, read the page file, obtain the master key from the page file, and then decrypt the password database. The attack requires physical access but also works with a cloned disk, so the user need not even realize it has happened.

It's a standard attack. It's also not far-fetched to assume that an attacker could create memory pressure, for example by running a trojan process as an ordinary that uses as much available memory as possible, in order to ensure the master key is paged to disk.

Whether you want to safeguard against this scenario or not is another question, it always depends on the threat model. I don't know how good this memguard is, but if it does what it promises, then it would likely make the application more secure.

Christopher Nielsen

unread,
Oct 15, 2018, 5:58:32 PM10/15/18
to ren...@ix.netcom.com, matthias...@gmail.com, golang-nuts
Not sure how you expect the password to not be stored in memory in
plaintext at some point. Without a secure hardware coprocessor with
secure memory, the system is still susceptible to at least
side-channel and potentially timing attacks.

robert engels

unread,
Oct 15, 2018, 6:05:46 PM10/15/18
to EricR, golang-nuts
If the user has the ability to read the page file - i.e. root - then he also has the ability to use the debugger to inspect the live memory as well - so as the OP pointed out - if root is compromised - nothing is secure.

robert engels

unread,
Oct 15, 2018, 6:11:17 PM10/15/18
to m4dh...@gmail.com, matthias...@gmail.com, golang-nuts
Exactly - and systems do not typically have this - yet are considered secure. If the plain text is ever available - and it almost always is (in the original input component, etc.) it is always subject to attack/hack - and as far as I am aware without hardware support (dongle, etc.) this is a limitation of all security implementations.

You don’t always need the plain text though, you can store the one way hash (as in Http Digest security), and use that, so if the store is compromised the users known passwords are not discovered - but it doesn’t mean access won’t be granted.

As far as I know - even ‘keychain access’ in osx (used in millions of systems) would be subject to similar hack to if root was available and memory could be scanned.

Christopher Nielsen

unread,
Oct 15, 2018, 7:05:06 PM10/15/18
to ren...@ix.netcom.com, Matthias Schmidt, golang-nuts
On Mon, Oct 15, 2018 at 3:10 PM robert engels <ren...@ix.netcom.com> wrote:
>
> Exactly - and systems do not typically have this - yet are considered secure. If the plain text is ever available - and it almost always is (in the original input component, etc.) it is always subject to attack/hack - and as far as I am aware without hardware support (dongle, etc.) this is a limitation of all security implementations.

Considered secure by whom? Maybe "secure enough" by most. At the end
of the day, you have to look at your threat model, attack surface,
potential attackers, and value of what you want to protect. A password
manager is a high-value target for obvious reasons. It should have a
well-defined and vetted security model. Personally, I use a hardware
security token to secure mine because I don't trust software.

> You don’t always need the plain text though, you can store the one way hash (as in Http Digest security), and use that, so if the store is compromised the users known passwords are not discovered - but it doesn’t mean access won’t be granted.

Sure. It depends what you're doing, of course.

> As far as I know - even ‘keychain access’ in osx (used in millions of systems) would be subject to similar hack to if root was available and memory could be scanned.

It does not follow that because something is used by millions that it
is secure. Again, maybe "secure enough" for most. I also use a
hardware token with keychain.

We seem to have wandered pretty far afield of the topic of this forum.

robert engels

unread,
Oct 15, 2018, 7:26:02 PM10/15/18
to m4dh...@gmail.com, Matthias Schmidt, golang-nuts
Maybe, but still, if they have root access to your machine, they can just as easily alter the accessing binary to send the decoded password elsewhere after it has decoded it…

Which is why applications on osx are “signed” (to prohibit tampering) (although if you have root access - you could probably also add the bogus singing cert to the certificate store). As far as I know Linux and its variants don’t enforced signed binaries.

I only point this out because you give the impression that because you “use a hardware device” it is secure - this is not really the case.

Security is always a trade-off.

robert engels

unread,
Oct 15, 2018, 7:33:39 PM10/15/18
to m4dh...@gmail.com, Matthias Schmidt, golang-nuts
To clarify, this is for a hardware device that protects a local resource - a network based protocol that challenges the device for access is a different story, and yes, when properly implemented is secure (unless someone steals your device! - which is why it is usually password + device, and then you are back to the same problem of compromising passwords when root access has been compromised).

Christopher Nielsen

unread,
Oct 15, 2018, 8:09:03 PM10/15/18
to ren...@ix.netcom.com, Matthias Schmidt, golang-nuts
On Mon, Oct 15, 2018 at 4:25 PM robert engels <ren...@ix.netcom.com> wrote:
>
> Maybe, but still, if they have root access to your machine, they can just as easily alter the accessing binary to send the decoded password elsewhere after it has decoded it…

Which is why you disable remote root access on hosts that run security
services...
If someone has physical access, all bets are off anyway.

> Which is why applications on osx are “signed” (to prohibit tampering) (although if you have root access - you could probably also add the bogus singing cert to the certificate store). As far as I know Linux and its variants don’t enforced signed binaries.

I am aware of why macos, iOS, android, etc. sign apps. Thanks.

Adding a bogus signing cert to the app store would be a rather
sophisticated attack, and I am relatively certain having root access
on a client system would not grant that ability. Also, doing that in
an undetectable way would also be a sophisticated attack.

I don't know of a linux distribution that enforces signed binaries,
but packages are signed. Not the same, of course, but close. There is
also apparmor and SElinux to enforce isolation.

> I only point this out because you give the impression that because you “use a hardware device” it is secure - this is not really the case.

I don't think I gave that impression at all. Absolute security that is
in any way functional doesn't exist. Without question, using a
hardware security device is more secure than the alternatives. Saying
"that is not really the case" isn't correct.

> Security is always a trade-off.

Though I didn't state that explicitly, I feel it was implicit in my
comments about threat modeling.

Christopher Nielsen

unread,
Oct 15, 2018, 8:13:12 PM10/15/18
to ren...@ix.netcom.com, Matthias Schmidt, golang-nuts
On Mon, Oct 15, 2018 at 4:33 PM robert engels <ren...@ix.netcom.com> wrote:
>
> To clarify, this is for a hardware device that protects a local resource - a network based protocol that challenges the device for access is a different story, and yes, when properly implemented is secure (unless someone steals your device! - which is why it is usually password + device, and then you are back to the same problem of compromising passwords when root access has been compromised).

This statement indicates to me you don't understand how hardware
security tokens work. It doesn't matter if you have root access. You
cannot obtain key material from it. If you lose it, you lose the set
of keys on it. That's it. Revoke them and issue new ones using your
root cert/key that never touches a networked system and lives in a
safe.

robert engels

unread,
Oct 15, 2018, 10:21:46 PM10/15/18
to m4dh...@gmail.com, Matthias Schmidt, golang-nuts
That is not true. If you lose the key, anyone else can use the device - which is why there is usually an additional requirement beyond the hardware key - I am referring to hardware dongles given to users.

By LOSE I meant unknowingly lost - not that once I lose it and KNOW I’ve lost it I deactivate the keys - and by then the system may be compromised anyway (think murder to steal the hardware device - the victim is not reporting the device stolen).

Now sometimes that secondary info might be a retina or fingerprint scan, but the point is if the machine providing the information has been compromised (root access granted), they are free to alter the binaries and the OS itself, to compromise these procedures, meaning they probably already captured these elements already (prior to the crime).

It is the coupling of the two scenarios - the security cannot be based on the hardware device alone (since it can be lost/stolen), and when there is backup identifying information, that can be compromised (if the machine is compromised).

I know very well how the hardware devices work.

robert engels

unread,
Oct 15, 2018, 10:26:41 PM10/15/18
to m4dh...@gmail.com, Matthias Schmidt, golang-nuts
Also, what maybe I wasn’t clear here - that is the ‘verification is local - say a local app’, if the machine has been compromised - the binary can be edited to remove the security check - no need to even have the dongle - thus the requirement for an external resource being protected.

EricR

unread,
Oct 16, 2018, 3:49:40 AM10/16/18
to golang-nuts
The attack does not require the attacker to have root on the compromised machine. It does, however, require the page file not to be encrypted, as is common on Linux and Unix systems. The attack I've described requires physical access, e.g. by quickly copying the hard disk. There are special tools and hardware for that. The attacker may need root access on his own system, not the root of the compromised system.

For example, the standard procedure of a law enforcement agency is to confiscate the machine, copy the hard drives, and then investigate the hard drives for forensic evidence, including e.g. checking the page files for master keys if necessary. Of course, your policy could be that a password manager ought not safeguard its users against law enforcement or similar dedicated attackers with physical access (but without tampering the original system, live monitoring with a debugger, etc.). But the reason why good password managers lock the memory is exactly to prevent these kind of attacks.

I'm not going into the politics about whether it's good to give ordinary people such strong encryption or not. I merely wanted to point out one weakness of the system. If you as an implementer "argue around" the issue, your potential future users will not necessarily consider this as a good sign. If I were you, I would simply lock the master key in memory to prevent it from being paged out instead.

Thorsten Sommer

unread,
Oct 16, 2018, 7:32:20 AM10/16/18
to golang-nuts
Thank you Matthias, for sharing your work. I find your password manager useful. Keep the good work.

Matthias Schmidt

unread,
Oct 16, 2018, 2:31:42 PM10/16/18
to golang-nuts
Hi Christopher + Eric,

thanks for your feedback. You are right, i really underestimated the risk of such attacks.

I will lock the key-holding memory in the next release.

cheers,

Matthias

Christopher Nielsen

unread,
Oct 16, 2018, 3:38:04 PM10/16/18
to ren...@ix.netcom.com, Matthias Schmidt, golang-nuts
Maybe we're talking about different things. Are you thinking of TOTP
2FA tokens? Your arguments do apply to those.

I'm not talking about those. I'm talking about devices like a yubikey,
which is essentially a a poor person's HSM.

Matthias Schmidt

unread,
Oct 16, 2018, 3:54:57 PM10/16/18
to golang-nuts
And here it is:


Thanks to your guy's input the key-agent should be now way more secure.

cheers,

Matthias

Matthias Schmidt

unread,
Oct 16, 2018, 3:57:44 PM10/16/18
to golang-nuts
Thanks for giving it a go!

cheers,

Matthias

robert engels

unread,
Oct 16, 2018, 8:35:13 PM10/16/18
to m4dh...@gmail.com, Matthias Schmidt, golang-nuts
I did some reading on the yubikey, and it works pretty much how I expected, and I’m pretty sure my assessment still holds. (And as an aside, up until the latest release they were all completely broken… https://arstechnica.com/information-technology/2017/10/crypto-failure-cripples-millions-of-high-security-keys-750k-estonian-ids/)

If the authentication is device only, then stealing the device gets you in (I can’t imagine any one doing it this way though - I am assuming all services probably use two factor for the initial host device login - so you would need to still the key and the computer/phone - and if they have that, you are probably dead anyway, so you really don’t care at this point).

If it is part of a two factor authentication (password or pin), then if root is compromised it doesn’t help anyway, as someone has already installed a key tracker, etc. to grab the pin password if needed. The key coupled with external  factors (voice, etc.) and machine identity makes it pretty darn safe though… (except bugs in the crypto code as above).

At least according to their website on FIDO2:

Now, Yubico has worked in collaboration with Microsoft on the evolution of the FIDO U2F authentication standard, to create FIDO2. With FIDO2, the Security Key with its strong authentication can now solve multiple use case scenarios and experiences:
  • — second factor in a two factor authentication solution
  • — strong first factor, with the possession of the device only, allowing for a passwordless experience like tap and go
  • — multi-factor with possession of the device AND PIN, to solve high assurance requirements such as financial transactions, or submitting a prescription.
Anyway, your original point about not swapping the master password to disk is valid, but if root is comprised I still say it makes no difference as a malicious program can watch the application live to steal the password directly from pinned, non-swappable memory if so inclined.

I’d probably still buy a yubikey, but it seems to be a nightmare calling hundreds of services to tell them my device was lost/stolen. I didn’t see any “one point of contact” in this case ??? Can I log into a single yubikey website and disable it for all services - doesn’t seem available ?

Burak Serdar

unread,
Oct 18, 2018, 9:32:28 AM10/18/18
to matthias...@gmail.com, golang-nuts
On Tue, Oct 16, 2018 at 1:55 PM Matthias Schmidt
<matthias...@gmail.com> wrote:
>
> And here it is:
>
> https://github.com/ms140569/loki/releases/tag/1.2.0


Thanks for sharing this. I find this interesting because I've been
working on a very similar idea for an OIDC token manager CLI, and came
up with almost the same scheme regarding how you used the domain
sockets and the agent. I used rpc instead of a raw protocol though,
and the agent times out after a while in my case. You can take a look
at https://github.com/bserdar/took the crypto rpc stuff is under
crypta package.

It does suffer from the same problems mentioned in this thread: if you
can scan the memory, the master key is there. I'll add memory locking
to mine.

Matthias Schmidt

unread,
Oct 18, 2018, 9:38:17 AM10/18/18
to golang-nuts
Hi Burak,

and thanks pointing to you work. The memory-pinning was rather easy to integrate, have a look:


Timing-out the key-agent is something which came to my mind as well - i guess i'll do it optionally.

cheers,

Matthias
Reply all
Reply to author
Forward
0 new messages