Skip to content

Commit

Permalink
Strengthen scrypt parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
adamspofford-dfinity committed Jun 14, 2024
1 parent d649fb5 commit 12deeb8
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/cli-reference/quill-generate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ Most `quill` commands take a `--pem-file` parameter, for the key used to sign th

If a password-protected key needs to be exported for use with another tool such as DFX, use [`quill decrypt-pem`].

Technical notes: Passwords are run through `scrypt(r=8,p=1,n=131072,len=32)`, and then the file is encrypted with AES-256-CBC.
Technical notes: Passwords are run through `scrypt(r=8,p=1,n=2^17,len=32)`, and then the file is encrypted with AES-256-CBC.

[`quill decrypt-pem`]: quill-decrypt-pem.mdx
16 changes: 12 additions & 4 deletions src/commands/generate.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use crate::{
lib::{get_account_id, mnemonic_to_key, AnyhowResult},
lib::{get_account_id, key_encryption_params, mnemonic_to_key, AnyhowResult},
read_file,
};
use anyhow::{anyhow, bail, Context};
use bip39::{Language, Mnemonic};
use clap::{Parser, ValueEnum};
use dialoguer::Password;
use ic_agent::{identity::Secp256k1Identity, Identity};
use pkcs8::EncodePrivateKey;
use pkcs8::{EncodePrivateKey, EncryptedPrivateKeyInfo, PrivateKeyInfo};
use rand::{rngs::OsRng, thread_rng, RngCore};
use sec1::LineEnding;
use sec1::{pem::PemLabel, LineEnding};
use std::{
io::{stdin, IsTerminal},
path::PathBuf,
Expand Down Expand Up @@ -122,7 +122,15 @@ Copy this onto a piece of paper or external media and store it in a safe place."
.with_confirmation("Re-enter password", "Passwords did not match")
.interact()?
};
key.to_pkcs8_encrypted_pem(thread_rng(), password, LineEnding::default())?
let key_der = key.to_pkcs8_der()?;
let pki = PrivateKeyInfo::try_from(key_der.as_bytes())?;
let mut rng = thread_rng();
let mut salt = [0u8; 16];
rng.fill_bytes(&mut salt);
let mut iv = [0u8; 16];
rng.fill_bytes(&mut iv);
let doc = pki.encrypt_with_params(key_encryption_params(&salt, &iv), password)?;
doc.to_pem(EncryptedPrivateKeyInfo::PEM_LABEL, LineEnding::default())?
}
};
std::fs::write(&opts.pem_file, &pem)?;
Expand Down
7 changes: 7 additions & 0 deletions src/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use ic_nns_constants::{
use icp_ledger::{AccountIdentifier, Subaccount};
use icrc_ledger_types::icrc1::account::Account;
use k256::SecretKey;
use pkcs8::pkcs5::{pbes2::Parameters, scrypt::Params};
use ring::signature::Ed25519KeyPair;
use serde_cbor::Value;

Expand Down Expand Up @@ -610,6 +611,12 @@ pub fn e8s_to_tokens(e8s: Nat) -> BigDecimal {
BigDecimal::new(e8s.0.into(), 8)
}

pub fn key_encryption_params<'a>(salt: &'a [u8; 16], iv: &'a [u8; 16]) -> Parameters<'a> {
let scrypt_params = Params::new(17, 8, 1, 32).expect("valid scrypt Params consts");
Parameters::scrypt_aes256cbc(scrypt_params, salt, iv)
.expect("valid PKCS5 encryption parameters")
}

#[cfg(test)]
mod tests {
use super::{ParsedAccount, ParsedSubaccount};
Expand Down

0 comments on commit 12deeb8

Please sign in to comment.