use PKCS5_PBKDF2_HMAC_SHA1 for improved compatibility with more widely distributed openssl libraries

This commit is contained in:
Stephen Lombardo 2009-04-24 15:45:40 -04:00
parent 276ad912c0
commit 86376028f4
2 changed files with 3 additions and 85 deletions

View File

@ -55,79 +55,6 @@ typedef struct {
Btree *pBt;
} codec_ctx;
/*
* The following two functions PKCS5_PBKDF2_HMAC_SHA256 and h__dump implement a
* PBKDF2 (rfc2898) variant using SHA 256 instead of SHA1. These functions were extracted directly from
* from openssl-0.9.8j crypto/evp/p5_crpt2.c. The only modifications have been to use a variable
* defined HMAC_HASH to allow selection of the message digest (instead of fixing it to EVP_sha1().
* - Stephen
*/
#ifdef DEBUG_PKCS5V2
static void h__dump (const unsigned char *p, int len)
{
for (; len --; p++) fprintf(stderr, "%02X ", *p);
fprintf(stderr, "\n");
}
#endif
/* This is an implementation of PKCS#5 v2.0 password based encryption key
* derivation function PBKDF2 using the only currently defined function HMAC
* with SHA1. Verified against test vectors posted by Peter Gutmann
* <pgut001@cs.auckland.ac.nz> to the PKCS-TNG <pkcs-tng@rsa.com> mailing list.
*/
static int PKCS5_PBKDF2_HMAC_SHA256(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
int keylen, unsigned char *out)
{
unsigned char digtmp[SHA_DIGEST_LENGTH], *p, itmp[4];
int cplen, j, k, tkeylen;
unsigned long i = 1;
HMAC_CTX hctx;
HMAC_CTX_init(&hctx);
p = out;
tkeylen = keylen;
if(!pass) passlen = 0;
else if(passlen == -1) passlen = strlen(pass);
while(tkeylen) {
if(tkeylen > SHA_DIGEST_LENGTH) cplen = SHA_DIGEST_LENGTH;
else cplen = tkeylen;
/* We are unlikely to ever use more than 256 blocks (5120 bits!)
* but just in case...
*/
itmp[0] = (unsigned char)((i >> 24) & 0xff);
itmp[1] = (unsigned char)((i >> 16) & 0xff);
itmp[2] = (unsigned char)((i >> 8) & 0xff);
itmp[3] = (unsigned char)(i & 0xff);
HMAC_Init_ex(&hctx, pass, passlen, HMAC_HASH, NULL);
HMAC_Update(&hctx, salt, saltlen);
HMAC_Update(&hctx, itmp, 4);
HMAC_Final(&hctx, digtmp, NULL);
memcpy(p, digtmp, cplen);
for(j = 1; j < iter; j++) {
HMAC(HMAC_HASH, pass, passlen,
digtmp, SHA_DIGEST_LENGTH, digtmp, NULL);
for(k = 0; k < cplen; k++) p[k] ^= digtmp[k];
}
tkeylen-= cplen;
i++;
p+= cplen;
}
HMAC_CTX_cleanup(&hctx);
#ifdef DEBUG_PKCS5V2
fprintf(stderr, "Password:\n");
h__dump (pass, passlen);
fprintf(stderr, "Salt:\n");
h__dump (salt, saltlen);
fprintf(stderr, "Iteration count %d\n", iter);
fprintf(stderr, "Key:\n");
h__dump (out, keylen);
#endif
return 1;
}
static void codec_prepare_key(sqlite3 *db, const void *zKey, int nKey, void *salt, int nSalt, void *out, int *nOut) {
/* if key data lenth is exactly 256 bits / 32 bytes use the data directly */
if (nKey == 67 && sqlite3StrNICmp(zKey ,"x'", 2) == 0) {
@ -141,8 +68,8 @@ static void codec_prepare_key(sqlite3 *db, const void *zKey, int nKey, void *sal
sqlite3DbFree(db, key);
/* otherwise the key is provided as a string so hash it to get key data */
} else {
*nOut = SHA_DIGEST_LENGTH;
PKCS5_PBKDF2_HMAC_SHA256(zKey, nKey, salt, nSalt, PBKDF2_ITER, SHA_DIGEST_LENGTH, out);
*nOut = KEY_LENGTH;
PKCS5_PBKDF2_HMAC_SHA1(zKey, nKey, salt, nSalt, PBKDF2_ITER, KEY_LENGTH, out);
}
}

View File

@ -41,16 +41,7 @@
#define CIPHER_DECRYPT 0
#define CIPHER_ENCRYPT 1
#define HMAC_HASH EVP_sha256()
#define SHA_DIGEST_LENGTH 32
#ifndef PBKDF2_SALT
#define PBKDF2_SALT {0x99, 0x76, 0x93, 0x7a, 0xc7, 0x2e, 0xd3, 0x88}
#endif
#ifndef PBKDF2_SALT_SZ
#define PBKDF2_SALT_SZ 8
#endif
#define KEY_LENGTH 32
#ifndef PBKDF2_ITER
#define PBKDF2_ITER 4000