Super, that works beautifully. Thanks!! Now, for sake of completeness, if I wanted to do the opposite, i.e. decrypt a key, I guess the steps are the same, using PEM_read_bio_PKCS8 at the end. Except that the salt and IV must be extracted from the PEM string. What is the function to do that? ________________________________ From: openssl-users <openssl-users-boun...@openssl.org> on behalf of Viktor Dukhovni <openssl-us...@dukhovni.org> Sent: July 22, 2020 7:17 PM To: openssl-users@openssl.org <openssl-users@openssl.org> Subject: Re: Using the library to encrypt a RSA private key compatible with Web Crypto API (PBKDF2)
On Wed, Jul 22, 2020 at 08:36:30PM +0000, Claude Robitaille wrote: > This is NOT about using the command line utility, it is about using > the library in a program and exporting a private key, while encrypting > it. Encrypted public keys are created via the PKCS8 API. > Now, for my application. I am not sure how to do this. I normally use > PEM_write_bio_PKCS8PrivateKey to generate a PEM string. That function > do accept a passphrase and a cipher but it is not possible to set > parameters. The default values, as I could gather by reading on the > Internet are weak so I just do not want to lower the Web Crypto API > end. How to proceed? Is there another function that can be used? The function you're looking for is PEM_write_bio_PKCS8_PRIV_KEY_INFO(). With error checks elided, it boils down to: 1. const EVP_CIPHER *cipher = EVP_get_cipherbyname(SN_aes_256_cbc); 2. X509_ALGOR *pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL, NID_hmacWithSHA512); The function in question needs documentation, it would be fanstastic if someone stepped up to document it, or at least open an issue asking for same: X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, unsigned char *salt, int saltlen, unsigned char *aiv, int prf_nid); When the IV is null a random IV is generated. When the salt is NULL and saltlen == 0 a random salt is used. /* When saltlen is 0 and salt is not NULL you may get a segfault! */ The return value is freed with: void X509_ALGOR_free(X509_ALGOR *); 3. PKCS8_PRIV_KEY_INFO *p8inf = EVP_PKEY2PKCS8(pkey); 4. X509_SIG *p8 = PKCS8_set0_pbe(pass, strlen(pass), p8inf, pbe); Here, you might want to pay attention to the character set in which the password is encoded, if it is not all ASCII, it should be UTF-8 (https://eur06.safelinks.protection.outlook.com/?url=https%3A%2F%2Ftools.ietf.org%2Fhtml%2Frfc8018&data=02%7C01%7C%7C6ecb294783f64bd662eb08d82e969dbe%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637310571707466330&sdata=QJ0dIUR%2FOsrgZn2SpnoRLHQRNZ1E7T4sB0O1CJyWIK8%3D&reserved=0) 5. BIO *bio_out = ... 6. ret = PEM_write_bio_PKCS8(out_bio, p8); -- Viktor.