Hi,

I want to generate a RSA private and public key and than encrypt the
private key symmetrically with a password to store it on a server. The
data has to be stored and transferred base64 encoded.

This is how I encrypt the private key:

    EVP_CIPHER_CTX  ctx;
    unsigned char *key = (unsigned char*)password.toLocal8Bit().data();
    unsigned char *data = (unsigned char*)privkey.toLocal8Bit().constData());
    int len = strlen((char*)data)+1;
    unsigned char iv[EVP_MAX_IV_LENGTH];

    select_random_iv(iv, EVP_MAX_IV_LENGTH);
    int c_len = len + AES_BLOCK_SIZE, f_len = 0;
    unsigned char *ciphertext = (unsigned char*)malloc(c_len);
    EVP_EncryptInit(&ctx, EVP_aes_128_cfb(), key, iv);
    EVP_EncryptUpdate(&ctx, ciphertext, &c_len, data, len);
    EVP_EncryptFinal(&ctx, ciphertext+c_len, &f_len);

This works fine and if I send the encrypted data, the iv, the key and
the password directly to the decrypt function (decryptPrivateKey(...))
I can also decrypt the data again. But if I encode the data together
with the iv as base64 to store it on the server and later decode it
again the decryption fails.

Here is how I encode the data together with the iv in base64:

    char *base64Key = base64(ciphertext, strlen((char*)ciphertext));
    char *base64IV = base64(iv, strlen((char*)iv));
    char *iv_seperator = (char*)"00iv00";

    base64Key = (char*)realloc(base64Key, 
strlen(base64Key)+strlen(base64IV)+6+1);
    strcat(base64Key, iv_seperator);
    strcat(base64Key, base64IV);

The result is a string <data>"00iv00"<iv> which I transfer to the
server. Now when I retrieve the data again I separate the encrypted key
and the iv, decode it and send it to the decryption function:

    char *data = privkey.toLocal8Bit().data();
    char keyBase64[strlen(data)+1];
    char ivBase64[2000];

    int separator, i;
    bool isKey = true;
    for(i = 0; i<strlen(data); i++) {
        if (data[i] == '0' && data[i+1] == '0' && data[i+2] == 'i' && data[i+3] 
== 'v' && data[i+4] == '0' && data[i+5] == '0') {
            isKey = false;
            keyBase64[i] = '\0';
            i += 5;
            separator = i;
        } else {
            if (isKey) keyBase64[i] = data[i];
            else ivBase64[i-separator-1] = data[i];
        }
    }

    ivBase64[i-separator-1] = '\0';

    unsigned char *key = unbase64(keyBase64, strlen(keyBase64));
    unsigned char *iv = unbase64(ivBase64, strlen(ivBase64));

    return (decryptPrivateKey(key, iv, password));

This is how base64 and unbase64 looks:

char* Encryption::base64(const unsigned char *input, int length)
{
    BIO *bmem, *b64;
    BUF_MEM *bptr;

    b64 = BIO_new(BIO_f_base64());
    bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, input, length);
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);

    char *buff = (char *)malloc(bptr->length+1);
    memcpy(buff, bptr->data, bptr->length);
    buff[bptr->length] = 0;

    BIO_free_all(b64);

    return buff;
}

unsigned char* Encryption::unbase64(char *input, int length)
{
    BIO *b64, *bmem;
    unsigned char *buffer = (unsigned char *)malloc(length);
    memset(buffer, 0, length);

    b64 = BIO_new(BIO_f_base64());
    bmem = BIO_new_mem_buf(input, length);
    bmem = BIO_push(b64, bmem);

    BIO_read(bmem, buffer, length);

    BIO_free_all(bmem);

    return buffer;
}

I already tried several other methods to endoce/decode base64 but
nothing really works. Maybe someone on this list can help me?

Thanks a lot!
Björn

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to