Skip to content

pkcs8: An easier way to pass in scrypt parameters? #1205

@chenxiaolong

Description

@chenxiaolong

Currently, when calling RsaPrivateKey.to_pkcs8_encrypted_pem(), it seems to use the scrypt crate's default parameters, which are: n=32768, r=8, p=1, len=32. Unfortunately, openssl can't load these files and fails with:

❯ openssl rsa -in /tmp/test.key
Enter pass phrase for /tmp/test.key:
Could not read private key from /tmp/test.key
001E5B249B7F0000:error:030000AC:digital envelope routines:scrypt_alg:memory limit exceeded:providers/implementations/kdfs/scrypt.c:482:
001E5B249B7F0000:error:030000AB:digital envelope routines:PKCS5_v2_scrypt_keyivgen_ex:illegal scrypt parameters:crypto/asn1/p5_scrypt.c:260:

Looking at openssl's manpage, it seems that they default to a lower n value:

       -scrypt
           Uses the scrypt algorithm for private key encryption using default parameters: currently N=16384,
           r=8 and p=1 and AES in CBC mode with a 256 bit key. These parameters can be modified using the
           -scrypt_N, -scrypt_r, -scrypt_p and -v2 options.

Currently, I'm able to match that and create openssl-compatible key files with:

let key: &RsaPrivateKey = <...>;

let mut rng = rand::thread_rng();

let mut salt = [0u8; 16];
rng.fill_bytes(&mut salt);

let mut iv = [0u8; 16];
rng.fill_bytes(&mut iv);

// 14 = log_2(16384), 32 bytes = 256 bits
let scrypt_params = scrypt::Params::new(14, 8, 1, 32).unwrap();
let pbes2_params = pbes2::Parameters::scrypt_aes256cbc(scrypt_params, &salt, &iv).unwrap();

let plain_text_der = key.to_pkcs8_der().unwrap();
let private_key_info = PrivateKeyInfo::try_from(plain_text_der.as_bytes()).unwrap();

let secret_doc = private_key_info.encrypt_with_params(pbes2_params, passphrase).unwrap();

let encrypted_pem = secret_doc.to_pem(EncryptedPrivateKeyInfo::PEM_LABEL, LineEnding::LF).unwrap();

pkcs8's defaults are more secure, so I don't think they should be changed, but could a more convenient API for specifying the parameters be added? (or does such a thing already exist?)

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions