gcry_cipher_setkey(h,k,l)

Werner Koch wk@gnupg.org
Mon, 22 Apr 2002 21:18:26 +0200


On Mon, 22 Apr 2002 17:55:03 +0200, kingruedi  said:

> That's bad :( I wanted to use the md5 sum of the user password as AES256 key. 

It doesn't buy you any security if you as 256 bit key with not enough
key material.  So use AES128 and lookup a decent string to key
algorithm - rfc2440 salted and iterated is probably a good choice and
code can be found in gnupg/g10/passphrase.c - basically it is this:

/* 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.  */
static int
hash_passphrase (const char *passphrase, int hashalgo,
                 int s2kmode,
                 const unsigned char *s2ksalt,
                 unsigned long s2kcount,
                 unsigned char *key, size_t keylen)
{
  GCRY_MD_HD md;
  int pass, i;
  int used = 0;
  int pwlen = strlen (passphrase);

  if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
      || !hashalgo || !keylen || !key || !passphrase)
    return GNUPG_Invalid_Value;
  if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
    return GNUPG_Invalid_Value;
  
  md = gcry_md_open (hashalgo, GCRY_MD_FLAG_SECURE);
  if (!md)
    return map_gcry_err (gcry_errno());

  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;
}


Use 3 for s2kmode and 96 for the count.

  Werner