Support encrypted native identity keys
This commit is contained in:
+42
-5
@@ -358,13 +358,24 @@ pub fn derive_native_session_key(
|
||||
}
|
||||
|
||||
pub fn load_ed25519_identity(path: &Path) -> Result<SigningKey> {
|
||||
load_ed25519_identity_with_passphrase(path, None)
|
||||
}
|
||||
|
||||
pub fn load_ed25519_identity_with_passphrase(
|
||||
path: &Path,
|
||||
passphrase: Option<&str>,
|
||||
) -> Result<SigningKey> {
|
||||
let private_key = ssh_key::PrivateKey::read_openssh_file(path)
|
||||
.with_context(|| format!("read OpenSSH identity {}", path.display()))?;
|
||||
anyhow::ensure!(
|
||||
!private_key.is_encrypted(),
|
||||
"OpenSSH identity {} is encrypted; encrypted-key prompts are not wired yet",
|
||||
path.display()
|
||||
);
|
||||
let private_key = if private_key.is_encrypted() {
|
||||
let passphrase = passphrase
|
||||
.ok_or_else(|| anyhow::anyhow!("OpenSSH identity {} is encrypted", path.display()))?;
|
||||
private_key
|
||||
.decrypt(passphrase)
|
||||
.with_context(|| format!("decrypt OpenSSH identity {}", path.display()))?
|
||||
} else {
|
||||
private_key
|
||||
};
|
||||
let ed25519 = private_key
|
||||
.key_data()
|
||||
.ed25519()
|
||||
@@ -929,6 +940,32 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_ed25519_identity_decrypts_encrypted_openssh_private_key() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("id_ed25519");
|
||||
let signing = SigningKey::from_bytes(&[12u8; 32]);
|
||||
let keypair = ssh_key::private::Ed25519Keypair::from(&signing);
|
||||
let private =
|
||||
ssh_key::PrivateKey::new(ssh_key::private::KeypairData::from(keypair), "").unwrap();
|
||||
let encrypted = private
|
||||
.encrypt(&mut rand::rngs::OsRng, "correct horse battery staple")
|
||||
.unwrap();
|
||||
encrypted
|
||||
.write_openssh_file(&path, ssh_key::LineEnding::LF)
|
||||
.unwrap();
|
||||
|
||||
assert!(load_ed25519_identity(&path).is_err());
|
||||
assert!(load_ed25519_identity_with_passphrase(&path, Some("wrong")).is_err());
|
||||
let loaded =
|
||||
load_ed25519_identity_with_passphrase(&path, Some("correct horse battery staple"))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
VerifyingKey::from(&loaded).to_bytes(),
|
||||
VerifyingKey::from(&signing).to_bytes()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_session_key_derivation_matches_and_binds_transcript() {
|
||||
let host_signing = SigningKey::from_bytes(&[3u8; 32]);
|
||||
|
||||
Reference in New Issue
Block a user