fn derive_key_and_nonce()

in src/aesgcm.rs [230:264]


fn derive_key_and_nonce(
    cryptographer: &dyn Cryptographer,
    ece_mode: EceMode,
    local_prv_key: &dyn LocalKeyPair,
    remote_pub_key: &dyn RemotePublicKey,
    auth_secret: &[u8],
    salt: &[u8],
) -> Result<KeyAndNonce> {
    if auth_secret.len() != ECE_WEBPUSH_AUTH_SECRET_LENGTH {
        return Err(Error::InvalidAuthSecret);
    }
    if salt.len() != ECE_SALT_LENGTH {
        return Err(Error::InvalidSalt);
    }

    let shared_secret = cryptographer.compute_ecdh_secret(remote_pub_key, local_prv_key)?;
    let raw_remote_pub_key = remote_pub_key.as_raw()?;
    let raw_local_pub_key = local_prv_key.pub_as_raw()?;

    let keypair = match ece_mode {
        EceMode::Encrypt => encode_keys(&raw_remote_pub_key, &raw_local_pub_key),
        EceMode::Decrypt => encode_keys(&raw_local_pub_key, &raw_remote_pub_key),
    }?;
    let keyinfo = generate_info("aesgcm", &keypair)?;
    let nonceinfo = generate_info("nonce", &keypair)?;
    let ikm = cryptographer.hkdf_sha256(
        auth_secret,
        &shared_secret,
        ECE_WEBPUSH_AESGCM_AUTHINFO.as_bytes(),
        ECE_WEBPUSH_IKM_LENGTH,
    )?;
    let key = cryptographer.hkdf_sha256(salt, &ikm, &keyinfo, ECE_AES_KEY_LENGTH)?;
    let nonce = cryptographer.hkdf_sha256(salt, &ikm, &nonceinfo, ECE_NONCE_LENGTH)?;
    Ok((key, nonce))
}