Bug 84434 - RFE: systemd-ask-password should implement keyboard randomisation as a countermeasure to keyloggers
Summary: RFE: systemd-ask-password should implement keyboard randomisation as a counte...
Status: NEW
Alias: None
Product: systemd
Classification: Unclassified
Component: general (show other bugs)
Version: unspecified
Hardware: All All
: medium enhancement
Assignee: systemd-bugs
QA Contact: systemd-bugs
Depends on:
Reported: 2014-09-28 20:56 UTC by Christoph Anton Mitterer
Modified: 2014-10-24 00:10 UTC (History)
0 users

See Also:
i915 platform:
i915 features:


Description Christoph Anton Mitterer 2014-09-28 20:56:03 UTC

A nice feature for systemd-ask-password would be a trivial but effective measure against keyloggers.

The applications should randomly permute the mapping of keys every time a password is queried and display the mapping from the characters/keys, pressed on the input device, to those which are actually used in the password.

An example would be this.
> Key mappings:
>   character used for the password: ABCDEF0123456789$/;
>   character pressed on the device: ;E48AD05F29$7C/61B3
> Please enter your passpharse:

Of course one would need to extend this to all usable characters.
Pheraps the number of valid input characters should be configurable, i.e. that the user specifies which keyboardlayout is used and the valid characters are automatically deduced from that and/or that the user can give a textfile, which simply contains all the valid passphrase characters.

Further, the randomisation MUST take place each time the passphrase is requested, so it should not only happen once per session or once the system boots,... and especially it should also happen on each retry!
If not, it might again be possible for an attacker that has a keylogger in place to make statistical attacks.

And it should be asserted, that only high quality entropy is used for the randomisation, especially since much of these password queries may happen during boot (e.g. dm-crypt) and urandom may not yet be well enough sed.
If /dev/random blocks, than ask-password should really print a message that the user should generate entropy, just as e.g. gnupg does during key generation.

Now what's the benefit from all this?
Even if an attacker has a hardware (or software) keylogger in place, he won't know the random mapping of the keys.
So he only logs the length of the password and the statistical distribution of the keys - if the password is well enough, the latter shouldn't matter and there isn't much that can be done against the former[0].

This is especially handy in scenarios like this: Using a gpg encrypted key for dm-crypt/LUKS.
If the attacker can log the passphrase, it's useless to him since a) it's randomised and b) he doesn't automatically have the gpg-encrypted key.
And even if he get's the gpg-encrypted key, he still only has a passphrase which was valid only once for that specific mapping.

The downside is of course, that it takes longer for a user to enter his passphrase, but since the whole thing should be just optional, it doesn't really matter.

[0] Well there is one way around that, which could be implemented as a further option:
To ignore any additional characters at the end of the passphrase, e.g. if we have the mappings from the example from above, and the real password would be:
the user would need to enter:
but could also enter

The downside of course is, that either systemd-ask-password would need to know the correct length of the passphrase in order to throw away the rest, or that the program where it feeds the passphrase into (and which knows the passphrase), also supports ignoring the extra characters.
In practise though, many programs work with hashed passphrases, so the correct length would need to be given.
This may be done in a separate random mapping step though, e.g.
actual: 0123456789_
   key: 4_860392157
Enter the password length:

A user could now enter something like:
ask-password should only take everything up to excluding the first occurrence of "_" (which is the key 2 in the above mapping) as the real length, so in the above example
2 would map to 7
7 would already be the first "_" and everything afterwards is ignored.
So the length of the password would be 7 (which is just the length of the above "AFFE123".

The trick with the additional 72734 and the "ignore everything after the first _" is to prevent that the attacker can find out how many digits the length of the passphrase has.
alone, he'd know that the length is something between [0; 9], which may already help a lot in brute force or statistical attacks
But with
he only knows that the length is something between [0; 999999], which doesn't really help anymore.

Comment 1 Christoph Anton Mitterer 2014-09-28 21:07:11 UTC
btw: Originally I've thought about all the for the cryptsetup package from Debian, which ships askpass, a tool which is basically the same as systemd-ask-password.
I've also reported that feature request there:
so maybe code and/or other development efforts could be shared.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.