sequoia-sq/tests/sq-key-adopt.rs
Justus Winter b89c172c1d
Reincarnation commit.
- This implementation has been moved from the Sequoia repository to
    its own repository.  To inspect the history, either look at the
    Sequoia repository, or graft it onto this repository like this:

      $ git remote add sequoia https://gitlab.com/sequoia-pgp/sequoia
      $ git fetch sequoia 82eb0d7b240d137141fc0aaaa3dff1685bb11864
      $ git replace --graft <THIS-COMMIT> 82eb0d7b240d137141fc0aaaa3dff1685bb11864
2023-02-21 12:43:43 +01:00

314 lines
11 KiB
Rust

#[cfg(test)]
mod integration {
use std::path;
use assert_cmd::Command;
use predicates::prelude::*;
use sequoia_openpgp as openpgp;
use openpgp::Fingerprint;
use openpgp::Result;
use openpgp::cert::prelude::*;
use openpgp::policy::StandardPolicy;
use openpgp::parse::Parse;
use openpgp::types::KeyFlags;
fn dir() -> path::PathBuf {
path::Path::new("tests").join("data").join("keys")
}
fn alice() -> path::PathBuf {
// Fingerprint: 5CCB BA06 74EA 5162 615E 36E9 80E5 ADE9 43CA 0DC3
// Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
// Public-key size: 256 bits
// Secret key: Unencrypted
// Creation time: 2020-12-21 23:00:49 UTC
// Key flags: certification
//
// Subkey: 6A3B 1EC7 6233 62BC 066E 75AB DC42 7976 95D6 24E5
// Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
// Public-key size: 256 bits
// Secret key: Unencrypted
// Creation time: 2020-12-21 23:00:49 UTC
// Key flags: signing
//
// Subkey: 827E 4397 F330 7EDA 6ABD 2A6E AD9C 461D 6D2F 0982
// Public-key algo: ECDH public key algorithm
// Public-key size: 256 bits
// Secret key: Unencrypted
// Creation time: 2020-12-21 23:00:49 UTC
// Key flags: transport encryption, data-at-rest encryption
//
// UserID: Alice Lovelace <alice@example.org>
dir().join("alice-lovelace-encryption-subkey-signing-subkey-priv.pgp")
}
fn alice_primary() -> (Fingerprint, KeyFlags) {
("5CCB BA06 74EA 5162 615E 36E9 80E5 ADE9 43CA 0DC3".parse().unwrap(),
KeyFlags::empty().set_certification())
}
fn alice_signing() -> (Fingerprint, KeyFlags) {
("6A3B 1EC7 6233 62BC 066E 75AB DC42 7976 95D6 24E5".parse().unwrap(),
KeyFlags::empty().set_signing())
}
fn alice_encryption() -> (Fingerprint, KeyFlags) {
("827E 4397 F330 7EDA 6ABD 2A6E AD9C 461D 6D2F 0982".parse().unwrap(),
KeyFlags::empty().set_transport_encryption().set_storage_encryption())
}
fn bob() -> path::PathBuf {
// Fingerprint: C1CF 22F6 C838 07CE 3901 6CDE 8463 B196 87EE 13BB
// Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
// Public-key size: 256 bits
// Secret key: Unencrypted
// Creation time: 2020-12-21 23:02:23 UTC
// Key flags: certification
//
// UserID: Bob Babbage <bob@example.org>
dir().join("bob-babbage-cert-only-priv.pgp")
}
fn bob_primary() -> (Fingerprint, KeyFlags) {
("C1CF 22F6 C838 07CE 3901 6CDE 8463 B196 87EE 13BB".parse().unwrap(),
KeyFlags::empty().set_certification())
}
fn carol() -> path::PathBuf {
// Fingerprint: 0B17 34A8 2726 A5D1 D5AC 1568 1EC1 4781 FD88 09B4
// Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
// Public-key size: 256 bits
// Secret key: Unencrypted
// Creation time: 2020-12-22 00:02:24 UTC
// Key flags: certification
//
// Subkey: 3D56 A424 3D5C C345 638D FB19 05D8 B9EA DB92 A8C1
// Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
// Public-key size: 256 bits
// Secret key: Unencrypted
// Creation time: 2020-12-22 00:02:24 UTC
// Key flags: signing
//
// Subkey: 1F47 6866 1260 CFFA D3DE B630 5652 476A 8B74 5CE5
// Public-key algo: ECDH public key algorithm
// Public-key size: 256 bits
// Secret key: Unencrypted
// Creation time: 2020-12-22 00:02:24 UTC
// Key flags: transport encryption, data-at-rest encryption
//
// UserID: Carol <carol@example.org>
dir().join("carol-encryption-subkey-signing-subkey-priv.pgp")
}
fn carol_primary() -> (Fingerprint, KeyFlags) {
("0B17 34A8 2726 A5D1 D5AC 1568 1EC1 4781 FD88 09B4".parse().unwrap(),
KeyFlags::empty().set_certification())
}
fn carol_signing() -> (Fingerprint, KeyFlags) {
("3D56 A424 3D5C C345 638D FB19 05D8 B9EA DB92 A8C1".parse().unwrap(),
KeyFlags::empty().set_signing())
}
fn carol_encryption() -> (Fingerprint, KeyFlags) {
("1F47 6866 1260 CFFA D3DE B630 5652 476A 8B74 5CE5".parse().unwrap(),
KeyFlags::empty().set_transport_encryption().set_storage_encryption())
}
fn check(output: &[u8],
key_count: usize,
keys: ((Fingerprint, KeyFlags), &[(Fingerprint, KeyFlags)]))
-> Result<()>
{
let p = &StandardPolicy::new();
let cert = Cert::from_bytes(output).unwrap();
let vc = cert.with_policy(p, None).unwrap();
assert_eq!(key_count, vc.keys().count());
assert_eq!(vc.primary_key().fingerprint(), keys.0.0);
assert_eq!(vc.primary_key().key_flags(), Some(keys.0.1));
for (subkey, keyflags) in keys.1 {
let mut found = false;
for k in vc.keys().subkeys() {
if k.fingerprint() == *subkey {
assert_eq!(k.key_flags().as_ref(), Some(keyflags));
found = true;
break;
}
}
assert!(found);
}
Ok(())
}
#[test]
fn adopt_encryption() -> Result<()> {
// Adopt an encryption subkey.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_encryption().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 2, (bob_primary(), &[alice_encryption()])).is_ok()
}));
Ok(())
}
#[test]
fn adopt_signing() -> Result<()> {
// Adopt a signing subkey (subkey has secret key material).
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_signing().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 2, (bob_primary(), &[alice_signing()])).is_ok()
}));
Ok(())
}
#[test]
fn adopt_certification() -> Result<()> {
// Adopt a certification subkey (subkey has secret key material).
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(carol())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_primary().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 4, (carol_primary(), &[alice_primary()])).is_ok()
}));
Ok(())
}
#[test]
fn adopt_encryption_and_signing() -> Result<()> {
// Adopt an encryption subkey and a signing subkey.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_signing().0.to_hex())
.arg("--key").arg(alice_encryption().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 3,
(bob_primary(),
&[alice_signing(), alice_encryption()]))
.is_ok()
}));
Ok(())
}
#[test]
fn adopt_twice() -> Result<()> {
// Adopt the same an encryption subkey twice.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_encryption().0.to_hex())
.arg("--key").arg(alice_encryption().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 2, (bob_primary(), &[alice_encryption()])).is_ok()
}));
Ok(())
}
#[test]
fn adopt_key_appears_twice() -> Result<()> {
// Adopt the an encryption subkey that appears twice.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(alice())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_encryption().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 2, (bob_primary(), &[alice_encryption()])).is_ok()
}));
Ok(())
}
#[test]
fn adopt_own_encryption() -> Result<()> {
// Adopt its own encryption subkey. This should be a noop.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(alice())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_encryption().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 3, (alice_primary(), &[alice_encryption()])).is_ok()
}));
Ok(())
}
#[test]
fn adopt_own_primary() -> Result<()> {
// Adopt own primary key.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(bob())
.arg("--key").arg(bob_primary().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 2, (bob_primary(), &[bob_primary()])).is_ok()
}));
Ok(())
}
#[test]
fn adopt_missing() -> Result<()> {
// Adopt a key that is not present.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(bob())
.arg("--key").arg("1234 5678 90AB CDEF 1234 5678 90AB CDEF")
.assert()
.code(1);
Ok(())
}
#[test]
fn adopt_from_multiple() -> Result<()> {
// Adopt from multiple certificates simultaneously.
Command::cargo_bin("sq").unwrap().arg("key").arg("adopt")
.arg(bob())
.arg("--keyring").arg(alice())
.arg("--key").arg(alice_signing().0.to_hex())
.arg("--key").arg(alice_encryption().0.to_hex())
.arg("--keyring").arg(carol())
.arg("--key").arg(carol_signing().0.to_hex())
.arg("--key").arg(carol_encryption().0.to_hex())
.assert()
.code(0)
.stdout(predicate::function(|output: &[u8]| -> bool {
check(output, 5,
(bob_primary(),
&[
alice_signing(), alice_encryption(),
carol_signing(), carol_encryption()
]))
.is_ok()
}));
Ok(())
}
}