On Tue, Sep 20, 2005 at 10:06:36AM +0200, Werner Koch wrote:
On Tue, 20 Sep 2005 08:53:46 +0200, Daniel A Nagy said:
4. Some implementations give up before trying all possible ways of
decrypting a message. For example, GnuPG gives up if it encounters a
passphrase-derived symmetric key specifier and the entered passphrase is
wrong, even if it is followed by an asymmetrically encrypted symmetric key
for which it does have access to the corresponding private decryption key.
There are actually two problems:
There is no way to cancel the input of a passphrase when using the
CLI, so that gpg can continue with other keys. When using the
gpg-agent, this is possible but a bug inhibited this - I just fixed
I never thought of this as a problem, but maybe you're right.
The other problem is that we can't reliable decide whether the
passphrase is correct. The only way to do this is by looking at the
algorithm byte to check whether this gives a valid algorithm. This is
far form being reliable. Due to gpg's streaming based design with only
a very limited look-ahead we can't do a test decryption and roll back
if it does not work out.
I would suggest a completely different approach: try extracting a key from
each ESK (be it password-derived, password-encrypted or
asymmetcially encrypted), and use the one which inspires most confidence:
An asymmetrically decrypted key has an approx. 1 in 17 million chance of
being incorrect, symmetrically encrypted keys have a roughly 1 in 20 chance
of being incorrect, while there's absolutely no indication wheter a
passphrase-derived secret key is correct or not.
Thus, deriving a decryption key from a passphrase and then merrily
proceeding to the decryption of the encrypted content is incorrect. A
correct implementation should try to extract a key from each ESK, and in
case of success (asymmetric decryption with leading 0 and correct checksum,
symmetric encryption with valid algorithm id or any passphrase-derived key)
replacing the tentative decryption key, if the new key inspires more
confidence than the previous tentative key. Eventually, the last tentative
key should be used for decryption.
A way to check early that the decryption worked would be needed to
solve the problem - I am not sure whether this is really needed given
the security implications of such a check.
Yes, that's somewhat hazardous, indeed (although only in non-interactive
applications). But it's not necessary, as explained above.