Fwd: KWallet weaknesses
Werner Koch
wk at gnupg.org
Mon Dec 8 22:10:15 GMT 2003
On Mon, 8 Dec 2003 20:28:32 +0100, Dirk Mueller said:
> a) You said the passphrase -> key code is bad. Which code should we use
> instead? Where can we get a working implementation, or verify our own?
Either PKCS#5 or the S2K code from OpenPGP. Here is an implementation
under the GPL from gnupg-1.9/agent/protect.c derived from gnupg:
/* Transform a passphrase into a suitable key of length KEYLEN and
store this key in the caller provided buffer KEY. The caller must
provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable
value is 96).
Returns an error code on failure.
Example usage:
unsigned char salt[8];
unsigned char *key;
size_t keylen;
gcry_get_nonce (salt, sizeof salt)
key = gcry_malloc_secure (keylen);
if (!key)
rc = out_of_core ();
else
{
rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
3, salt, 96, key, keylen);
if (!rc)
rc = gcry_cipher_setkey (hd, key, keylen);
xfree (key);
}
*/
static int
hash_passphrase (const char *passphrase, int hashalgo,
int s2kmode,
const unsigned char *s2ksalt,
unsigned long s2kcount,
unsigned char *key, size_t keylen)
{
int rc;
gcry_md_hd_t md;
int pass, i;
int used = 0;
int pwlen = strlen (passphrase);
if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
|| !hashalgo || !keylen || !key || !passphrase)
return gpg_error (GPG_ERR_INV_VALUE);
if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
return gpg_error (GPG_ERR_INV_VALUE);
rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE);
if (rc)
return rc;
for (pass=0; used < keylen; pass++)
{
if (pass)
{
gcry_md_reset (md);
for (i=0; i < pass; i++) /* preset the hash context */
gcry_md_putc (md, 0);
}
if (s2kmode == 1 || s2kmode == 3)
{
int len2 = pwlen + 8;
unsigned long count = len2;
if (s2kmode == 3)
{
count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
if (count < len2)
count = len2;
}
while (count > len2)
{
gcry_md_write (md, s2ksalt, 8);
gcry_md_write (md, passphrase, pwlen);
count -= len2;
}
if (count < 8)
gcry_md_write (md, s2ksalt, count);
else
{
gcry_md_write (md, s2ksalt, 8);
count -= 8;
gcry_md_write (md, passphrase, count);
}
}
else
gcry_md_write (md, passphrase, pwlen);
gcry_md_final (md);
i = gcry_md_get_algo_dlen (hashalgo);
if (i > keylen - used)
i = keylen - used;
memcpy (key+used, gcry_md_read (md, hashalgo), i);
used += i;
}
gcry_md_close(md);
return 0;
}
> b) You said that the version numbers will allow replay attacks. Though I don't
I talked about a rollback attack, that is at one time you change the
algorithm because a weakness was found in Blowfish and under certain
conditions an attacker might be able to trick you to use Blowfish
again even you are using the modern-ultra-resistant-algorithm. There
is no immediate need but you should think about it when you allow for
different algorithms. BTW, even Schneier is not anymore certain of
his Blowfish; all other modern algorithm have meanwhile been better
analyzed than Blowfish.
Werner
--
Werner Koch <wk at gnupg.org>
The GnuPG Experts http://g10code.com
Free Software Foundation Europe http://fsfeurope.org
More information about the kde-core-devel
mailing list