initial implementation of PBKDF2 using SHA256 for key derivation
This commit is contained in:
parent
c8f4309d3f
commit
9a13dce6d4
90
src/crypto.c
90
src/crypto.c
|
@ -36,6 +36,7 @@
|
|||
#include <assert.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include "sqliteInt.h"
|
||||
#include "btreeInt.h"
|
||||
#include "crypto.h"
|
||||
|
@ -51,19 +52,78 @@ typedef struct {
|
|||
int rekey_plaintext;
|
||||
} codec_ctx;
|
||||
|
||||
static void codec_passphrase_hash(const void *in, int inLen, void *out, int *outLen) {
|
||||
EVP_MD_CTX mdctx;
|
||||
unsigned int md_sz;
|
||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||
|
||||
EVP_MD_CTX_init(&mdctx);
|
||||
EVP_DigestInit_ex(&mdctx, DIGEST, NULL);
|
||||
EVP_DigestUpdate(&mdctx, in, inLen);
|
||||
EVP_DigestFinal_ex(&mdctx, md_value, &md_sz);
|
||||
memcpy(out, md_value, md_sz);
|
||||
EVP_MD_CTX_cleanup(&mdctx);
|
||||
memset(md_value, 0, md_sz);
|
||||
*outLen = md_sz;
|
||||
|
||||
/*
|
||||
* 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 *out, int *nOut) {
|
||||
|
@ -73,7 +133,9 @@ static void codec_prepare_key(sqlite3 *db, const void *zKey, int nKey, void *out
|
|||
*nOut = nKey;
|
||||
/* otherwise the key is provided as a string so hash it to get key data */
|
||||
} else {
|
||||
codec_passphrase_hash(zKey, nKey, out, nOut);
|
||||
unsigned char salt[] = PBKDF2_SALT;
|
||||
*nOut = SHA_DIGEST_LENGTH;
|
||||
PKCS5_PBKDF2_HMAC_SHA256(zKey, nKey, salt, PBKDF2_SALT_SZ, PBKDF2_ITER, SHA_DIGEST_LENGTH, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
src/crypto.h
16
src/crypto.h
|
@ -36,10 +36,24 @@
|
|||
#define CRYPTO_H
|
||||
|
||||
#define CIPHER EVP_aes_256_cfb()
|
||||
#define DIGEST EVP_sha256()
|
||||
#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
|
||||
|
||||
#ifndef PBKDF2_ITER
|
||||
#define PBKDF2_ITER 4000
|
||||
#endif
|
||||
|
||||
void sqlite3pager_get_codec(Pager *pPager, void **ctx);
|
||||
int sqlite3pager_is_mj_pgno(Pager *pPager, Pgno pgno);
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ do_test codec-1.6 {
|
|||
db close
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA hexkey = '98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836489';
|
||||
PRAGMA hexkey = '174258376BE88838254B398D59D4DDF1C37CAD3EC6F2453768924A527167577E';
|
||||
SELECT * from t1;
|
||||
}
|
||||
} {test1 test2}
|
||||
|
|
Loading…
Reference in New Issue