Re: Convert symmetrically encrypted content to base64
On Fri, 24 Aug 2012 15:54:50 -0400 Dave Thompson wrote: Note OpenSSL's RSA privatekey *includes* publickey. RSA publickey is n,e and naive privatekey is n,d, but OpenSSL privatekey is CRT form with n,d,e,p,q + more. There is no need to transmit the publickey separately, [..] Tiny aside: BIO_new_mem_buf will do the strlen() for you if you pass -1 for length. Just a convenience. [..] If PEM_read_* returns null (or nearly any other OpenSSL routine returns a failure indication), look at the error queue. http://www.openssl.org/support/faq.html#PROG6 and #PROG7 also if you don't get readable error. If they didn't, look very carefully at your PEM data. Commandline can do this: openssl asn1parse -in myprivkey.pem and/or: openssal rsa -in myprivkey.pem -text Thanks for your hints. After a lot of testing I figured out that my functions pem2key() and key2pem() works fine. The problem is that I lose some characters (e.g. '+' gets replaced by spaces) while sending the key over the network. But I think this problem don't belong to the mailing list. ;-) Thanks a lot! Björn -- Björn Schießle bjo...@schiessle.org www: http://schiessle.org gnupg key: 0x0x2378A753E2BF04F6 fingerprint: 244F CEB0 CB09 9524 B21F B896 2378 A753 E2BF 04F6 __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager majord...@openssl.org
Re: Convert symmetrically encrypted content to base64
Hi Christian, On Fri, 24 Aug 2012 08:11:25 +0200 Christian Hohnstaedt wrote: please see my comments below: (rather Qt and memory related) Thank you for your feedback. Now I'm trying the implement the function which does exactly the opposite: Take the public and private key in the PEM format from the server and import it in a RSA structure: void Encryption::pem2key(QString publickey, QString privatekey, QString password) { BIO *pubBio = BIO_new_mem_buf(publickey.toLocal8Bit().data(), strlen(publickey.toLocal8Bit().data())); BIO *privBio = BIO_new_mem_buf(privatekey.toLocal8Bit().data(), strlen(privatekey.toLocal8Bit().data())); RSA *rsa = RSA_new(); PEM_read_bio_RSAPublicKey(pubBio, rsa, 0, NULL); PEM_read_bio_RSAPrivateKey(privBio, rsa, 0, password.toLocal8Bit().data()); Keymanager::Instance()-setRSAkey(rsa); BIO_free_all(pubBio); BIO_free_all(privBio); } The program compiles and run without a problem. But if I call the key2pem() function with the newly imported RSA key. I get two quite short keys back (only half a line of data). So something seems to go wrong during import of the PEM encoded keys. Any idea what I'm doing wrong in the pem2key() function? Thanks! Björn __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager majord...@openssl.org
Convert symmetrically encrypted content to base64
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 data00iv00iv 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; istrlen(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 Listopenssl-users@openssl.org Automated List Manager majord...@openssl.org
Re: Convert symmetrically encrypted content to base64
Hi, I think I did it way too complicated. I think the problem was that I always tried to mimic some openssl php code I know, but I think the solution I have now is much easier and standard complained: void Encryption::generateUserKeys(QString password) { RSA *rsa; EVP_PKEY *pkey; int bits = 1024; unsigned long exp = RSA_F4; QMapQString, QString keypair; rsa = RSA_generate_key(bits, exp, NULL, NULL); pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); keypair = key2pem(rsa, password); RSA_free(rsa); sendUserKeysToServer(keypair); } QMapQString, QString Encryption::key2pem(RSA *rsa, QString password) { QMapQString, QString keypair; BUF_MEM *bptr; BIO *pubBio = BIO_new(BIO_s_mem()); BIO *privBio = BIO_new(BIO_s_mem()); PEM_write_bio_RSA_PUBKEY(pubBio, rsa); PEM_write_bio_RSAPrivateKey(privBio, rsa, EVP_aes_128_cfb(),NULL, 0, 0, password.toLocal8Bit().data()); BIO_get_mem_ptr(pubBio, bptr); char *pubKey = (char *)malloc(bptr-length+1); memcpy(pubKey, bptr-data, bptr-length); pubKey[bptr-length] = 0; BIO_get_mem_ptr(privBio, bptr); char *privKey = (char *)malloc(bptr-length+1); memcpy(privKey, bptr-data, bptr-length); privKey[bptr-length] = 0; keypair[privatekey] = QString(privKey); keypair[publickey] = QString(pubKey); BIO_free_all(pubBio); BIO_free_all(privBio); return keypair; } Please feel free to commend on it if you think there is still something to improve. best wishes, Björn -- Björn Schießle bjo...@schiessle.org www: http://schiessle.org gnupg key: 0x0x2378A753E2BF04F6 fingerprint: 244F CEB0 CB09 9524 B21F B896 2378 A753 E2BF 04F6 __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager majord...@openssl.org