0

I'm looking for C implementation of the OpenSSL EVP_BytesToKey function.

This is pseudo-code explanation of the EVP_BytesToKey method (in /doc/ssleay.txt of the OpenSSL source):

/* M[] is an array of message digests
 * MD() is the message digest function */
M[0]=MD(data . salt);
for (i=1; i<count; i++) M[0]=MD(M[0]);

i=1
while (data still needed for key and iv)
{
    M[i]=MD(M[i-1] . data . salt);
    for (i=1; i<count; i++) M[i]=MD(M[i]);
    i++;
}

If the salt is NULL, it is not used.
The digests are concatenated together.
M = M[0] . M[1] . M[2] .......

this is my code(MD() is sha512. And i need the key is 32 bytes and the iv is 16 bytes):

int main()
{
    unsigned long long out[8]; 
    unsigned char key[9] = {0x4b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c};
    int len, i;

    len = sizeof(key);
    sha512(out, key, len);

    unsigned char a[sizeof(out)];
    for (i = 0; i < count; i++) 
    {
        long2char(out, a); // unsigned long long to unsigned char;
        sha512(out, a, sizeof(out));
    }

    return 0;
}

After count times sha512(), the out is 64 bytes, so I think I don't need the rest of that pseudo-code. But the result is not correct, I don't know what went wrong.

I wish you can help me to figure it out. thanks!

jww
  • 97,681
  • 90
  • 411
  • 885
mclycan
  • 1
  • 2
  • OpenSSL's EVP_BytesToKey uses MD5? cipher = EVP_aes_256_cbc();digest = EVP_sha512();EVP_BytesToKey(cipher, digest, salt, password, password_len, rounds, key, iv); But here is EVP_sha512(); So I am confused! – mclycan Apr 11 '15 at 05:03
  • first,I want to thank you for answer my question. In my case, what I want to do is use C to implement this step “EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), salt, password, password_len, rounds, key, iv); ”. I found the cipher "EVP_aes_256_cbc()" is not important here, but the digest "EVP_sha512()" is. And I haven't call the PEM_Read or PEM_Write gear. So I use sha512 algorithm to hash the password and salt. But the total key and IV length is less than the digest length and final result is not correct. I don't know where is wrong. Please help me if you can,and I am very sorry to bother you – mclycan Apr 12 '15 at 12:12
  • I will try the way :[http://www.cryptopp.com/wiki/EVP_BytesToKey]`OPENSSL EVP BytesToKey` . thanks again – mclycan Apr 12 '15 at 14:52

1 Answers1

0

I'm looking for C implementation of the OpenSSL EVP_BytesToKey function...

Perhaps you should just use the one OpenSSL provides? You know, the one called EVP_BytesToKey in evp_key.c (shown below).

OpenSSL 1.1.0c changed the digest algorithm used in some internal components. Formerly, MD5 was used, and 1.1.0 switched to SHA256. Be careful the change is not affecting you in both EVP_BytesToKey and commands like openssl enc


int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
                   const unsigned char *salt, const unsigned char *data,
                   int datal, int count, unsigned char *key,
                   unsigned char *iv)
{
    EVP_MD_CTX *c;
    unsigned char md_buf[EVP_MAX_MD_SIZE];
    int niv, nkey, addmd = 0;
    unsigned int mds = 0, i;
    int rv = 0;
    nkey = EVP_CIPHER_key_length(type);
    niv = EVP_CIPHER_iv_length(type);
    OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH);
    OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH);

    if (data == NULL)
        return nkey;

    c = EVP_MD_CTX_new();
    if (c == NULL)
        goto err;
    for (;;) {
        if (!EVP_DigestInit_ex(c, md, NULL))
            goto err;
        if (addmd++)
            if (!EVP_DigestUpdate(c, &(md_buf[0]), mds))
                goto err;
        if (!EVP_DigestUpdate(c, data, datal))
            goto err;
        if (salt != NULL)
            if (!EVP_DigestUpdate(c, salt, PKCS5_SALT_LEN))
                goto err;
        if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds))
            goto err;

        for (i = 1; i < (unsigned int)count; i++) {
            if (!EVP_DigestInit_ex(c, md, NULL))
                goto err;
            if (!EVP_DigestUpdate(c, &(md_buf[0]), mds))
                goto err;
            if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds))
                goto err;
        }
        i = 0;
        if (nkey) {
            for (;;) {
                if (nkey == 0)
                    break;
                if (i == mds)
                    break;
                if (key != NULL)
                    *(key++) = md_buf[i];
                nkey--;
                i++;
            }
        }
        if (niv && (i != mds)) {
            for (;;) {
                if (niv == 0)
                    break;
                if (i == mds)
                    break;
                if (iv != NULL)
                    *(iv++) = md_buf[i];
                niv--;
                i++;
            }
        }
        if ((nkey == 0) && (niv == 0))
            break;
    }
    rv = EVP_CIPHER_key_length(type);
 err:
    EVP_MD_CTX_free(c);
    OPENSSL_cleanse(md_buf, sizeof(md_buf));
    return rv;
}
jww
  • 97,681
  • 90
  • 411
  • 885