v0.2.5-pre.009
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/capability.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
#[test]
|
||||
fn capability_variants_are_distinct_and_stable() {
|
||||
assert_ne!(super::WalletCapability::View, super::WalletCapability::Owner);
|
||||
assert_eq!(format!("{:?}", super::WalletCapability::View), "View");
|
||||
assert_eq!(format!("{:?}", super::WalletCapability::Owner), "Owner");
|
||||
assert_ne!(crate::WalletCapability::View, crate::WalletCapability::Owner);
|
||||
assert_eq!(format!("{:?}", crate::WalletCapability::View), "View");
|
||||
assert_eq!(format!("{:?}", crate::WalletCapability::Owner), "Owner");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/crypto.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
use base64::Engine as _;
|
||||
use base64::Engine; // rust-rules: derive-import
|
||||
|
||||
const VECTOR: &[u8] = include_bytes!("../tests/fixtures/kspwallet_v1_crypto_vectors.json");
|
||||
|
||||
@@ -70,15 +70,15 @@ fn deterministic_argon2id_and_xchacha_wrap_vector_matches_external_canary() -> k
|
||||
};
|
||||
assert_eq!(derived.as_bytes(), &expected_derived);
|
||||
|
||||
let content = super::SecretKeyV1::from_bytes(content_key);
|
||||
let wrapped_result = super::wrap_key(&derived, &content, &nonce, aad.as_slice());
|
||||
let content = crate::SecretKeyV1::from_bytes(content_key);
|
||||
let wrapped_result = crate::wrap_key(&derived, &content, &nonce, aad.as_slice());
|
||||
let wrapped = match wrapped_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(wrapped, expected_wrapped);
|
||||
|
||||
let unwrapped_result = super::unwrap_key(&derived, &nonce, aad.as_slice(), wrapped.as_slice());
|
||||
let unwrapped_result = crate::unwrap_key(&derived, &nonce, aad.as_slice(), wrapped.as_slice());
|
||||
let unwrapped = match unwrapped_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
@@ -89,16 +89,16 @@ fn deterministic_argon2id_and_xchacha_wrap_vector_matches_external_canary() -> k
|
||||
|
||||
#[test]
|
||||
fn xchacha_tampering_is_reported_as_generic_authentication_failure() -> ksp_core_lib::Result<()> {
|
||||
let key = super::SecretKeyV1::from_bytes([0x11_u8; 32]);
|
||||
let key = crate::SecretKeyV1::from_bytes([0x11_u8; 32]);
|
||||
let nonce = [0x22_u8; crate::KSPWALLET_V1_XCHACHA_NONCE_BYTES];
|
||||
let plaintext = [0x33_u8; 32];
|
||||
let encrypted_result = super::encrypt_bytes(&key, &nonce, b"kspwallet-test-aad", plaintext.as_slice());
|
||||
let encrypted_result = crate::encrypt_bytes(&key, &nonce, b"kspwallet-test-aad", plaintext.as_slice());
|
||||
let mut encrypted = match encrypted_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
encrypted[0] ^= 1;
|
||||
let result = super::decrypt_bytes(&key, &nonce, b"kspwallet-test-aad", encrypted.as_slice());
|
||||
let result = crate::decrypt_bytes(&key, &nonce, b"kspwallet-test-aad", encrypted.as_slice());
|
||||
assert!(result.is_err());
|
||||
let error = match result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -110,12 +110,12 @@ fn xchacha_tampering_is_reported_as_generic_authentication_failure() -> ksp_core
|
||||
|
||||
#[test]
|
||||
fn secret_key_debug_is_redacted_and_random_sources_are_callable() -> ksp_core_lib::Result<()> {
|
||||
let key_result = super::SecretKeyV1::random();
|
||||
let key_result = crate::SecretKeyV1::random();
|
||||
let key = match key_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let nonce_result = super::random_nonce();
|
||||
let nonce_result = crate::random_nonce();
|
||||
let nonce = match nonce_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/metadata.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
fn test_pubkey() -> ksp_core_lib::Pubkey {
|
||||
return ksp_core_lib::PRGIDPK_SOLANA_SYSTEM;
|
||||
@@ -7,8 +7,8 @@ fn test_pubkey() -> ksp_core_lib::Pubkey {
|
||||
|
||||
#[test]
|
||||
fn authorized_info_exposes_metadata_after_authorization() {
|
||||
let note = super::WalletNote { id: std::string::String::from("purpose"), text: std::string::String::from("devnet test wallet") };
|
||||
let info = super::WalletInfo {
|
||||
let note = crate::WalletNote { id: std::string::String::from("purpose"), text: std::string::String::from("devnet test wallet") };
|
||||
let info = crate::WalletInfo {
|
||||
format_version: 1,
|
||||
capability: crate::WalletCapability::View,
|
||||
pubkey: test_pubkey(),
|
||||
@@ -25,11 +25,11 @@ fn authorized_info_exposes_metadata_after_authorization() {
|
||||
|
||||
#[test]
|
||||
fn authorized_info_debug_redacts_alias_and_note_text() {
|
||||
let note = super::WalletNote {
|
||||
let note = crate::WalletNote {
|
||||
id: std::string::String::from("NOTE-ID-CANARY"),
|
||||
text: std::string::String::from("NOTE-SECRET-CANARY"),
|
||||
};
|
||||
let info = super::WalletInfo {
|
||||
let info = crate::WalletInfo {
|
||||
format_version: 1,
|
||||
capability: crate::WalletCapability::Owner,
|
||||
pubkey: test_pubkey(),
|
||||
@@ -46,7 +46,7 @@ fn authorized_info_debug_redacts_alias_and_note_text() {
|
||||
|
||||
#[test]
|
||||
fn locked_info_does_not_carry_authorized_identity_or_metadata() {
|
||||
let info = super::LockedWalletInfo { format_version: 1, view_enabled: true };
|
||||
let info = crate::LockedWalletInfo { format_version: 1, view_enabled: true };
|
||||
assert_eq!(info.format_version(), 1);
|
||||
assert!(info.view_enabled());
|
||||
let rendered = format!("{info:?}");
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/password.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
#[test]
|
||||
fn view_password_debug_is_redacted() {
|
||||
let password = super::ViewPassword::new(std::string::String::from("VIEW-SECRET-CANARY"));
|
||||
let password = crate::ViewPassword::new(std::string::String::from("VIEW-SECRET-CANARY"));
|
||||
let rendered = format!("{password:?}");
|
||||
assert_eq!(rendered, "ViewPassword(<redacted>)");
|
||||
assert!(!rendered.contains("VIEW-SECRET-CANARY"));
|
||||
@@ -11,7 +11,7 @@ fn view_password_debug_is_redacted() {
|
||||
|
||||
#[test]
|
||||
fn owner_password_debug_is_redacted() {
|
||||
let password = super::OwnerPassword::new(std::string::String::from("OWNER-SECRET-CANARY"));
|
||||
let password = crate::OwnerPassword::new(std::string::String::from("OWNER-SECRET-CANARY"));
|
||||
let rendered = format!("{password:?}");
|
||||
assert_eq!(rendered, "OwnerPassword(<redacted>)");
|
||||
assert!(!rendered.contains("OWNER-SECRET-CANARY"));
|
||||
@@ -19,6 +19,6 @@ fn owner_password_debug_is_redacted() {
|
||||
|
||||
#[test]
|
||||
fn password_wrappers_require_drop_for_zeroization() {
|
||||
assert!(std::mem::needs_drop::<super::ViewPassword>());
|
||||
assert!(std::mem::needs_drop::<super::OwnerPassword>());
|
||||
assert!(std::mem::needs_drop::<crate::ViewPassword>());
|
||||
assert!(std::mem::needs_drop::<crate::OwnerPassword>());
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/payload.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
use base64::Engine as _;
|
||||
use base64::Engine; // rust-rules: derive-import
|
||||
|
||||
#[test]
|
||||
fn metadata_payload_rejects_duplicate_note_identifiers() -> ksp_core_lib::Result<()> {
|
||||
@@ -18,7 +18,7 @@ fn metadata_payload_rejects_duplicate_note_identifiers() -> ksp_core_lib::Result
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(test_error("test metadata payload could not be serialized")),
|
||||
};
|
||||
let result = super::decode_metadata_payload(encoded.as_slice());
|
||||
let result = crate::decode_metadata_payload(encoded.as_slice());
|
||||
let error = match result {
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(test_error("duplicate note identifiers unexpectedly parsed")),
|
||||
std::result::Result::Err(error) => error,
|
||||
|
||||
86
crates/ksp-wallet-lib/unit_tests/security.rs
Normal file
86
crates/ksp-wallet-lib/unit_tests/security.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/security.rs
|
||||
// version: 2
|
||||
|
||||
//! Adversarial security canaries for native `.kspwallet` V1.
|
||||
|
||||
use base64::Engine; // rust-rules: derive-import
|
||||
|
||||
const FULL_VECTOR: &[u8] = include_bytes!("../tests/fixtures/kspwallet_v1_full_vector.json");
|
||||
|
||||
#[test]
|
||||
fn owner_signed_regions_reject_canonical_tampering_before_unlock() {
|
||||
for pointer in [
|
||||
"/key_slots/0/kdf/salt",
|
||||
"/key_slots/0/wrap/ciphertext",
|
||||
"/owner_control/ciphertext",
|
||||
"/metadata/ciphertext",
|
||||
"/secret/ciphertext",
|
||||
"/state_signature/signature",
|
||||
] {
|
||||
let tampered = tamper_base64url_field(FULL_VECTOR, pointer);
|
||||
let error = crate::inspect_locked_wallet_v1(tampered.as_slice()).expect_err("OWNER-signed canonical tampering must be rejected");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_AUTHENTICATION_FAILED, "unexpected error code for tampered field {pointer}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn owner_signature_verification_precedes_owner_and_view_password_kdf() {
|
||||
let tampered = tamper_base64url_field(FULL_VECTOR, "/metadata/ciphertext");
|
||||
let runtime = runtime();
|
||||
|
||||
let owner = runtime.block_on(crate::open_wallet_owner_v1(tampered.as_slice(), crate::OwnerPassword::new(std::string::String::new())));
|
||||
assert_eq!(owner.expect_err("tampered state must fail before an empty OWNER password reaches Argon2").code(), crate::ERROR_CODE_AUTHENTICATION_FAILED);
|
||||
|
||||
let view = runtime.block_on(crate::open_wallet_view_v1(tampered.as_slice(), crate::ViewPassword::new(std::string::String::new())));
|
||||
assert_eq!(view.expect_err("tampered state must fail before an empty VIEW password reaches Argon2").code(), crate::ERROR_CODE_AUTHENTICATION_FAILED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_credential_tampering_does_not_forge_owner_state_and_cannot_unlock_view() {
|
||||
let tampered = tamper_base64url_field(FULL_VECTOR, "/key_slots/1/wrap/ciphertext");
|
||||
let locked = crate::inspect_locked_wallet_v1(tampered.as_slice()).expect("VIEW wrapping credentials are intentionally outside the OWNER state transcript");
|
||||
assert!(locked.view_enabled());
|
||||
|
||||
let runtime = runtime();
|
||||
let owner =
|
||||
runtime.block_on(crate::open_wallet_owner_v1(tampered.as_slice(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))));
|
||||
assert!(owner.is_ok(), "VIEW credential tampering must not invalidate OWNER unlock");
|
||||
|
||||
let view = runtime.block_on(crate::open_wallet_view_v1(tampered.as_slice(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))));
|
||||
assert_eq!(view.expect_err("tampered VIEW wrapping must not unlock metadata").code(), crate::ERROR_CODE_VIEW_UNLOCK_FAILED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unlock_failures_do_not_echo_password_material() {
|
||||
let owner_canary = "OWNER-PASSWORD-LEAK-CANARY";
|
||||
let view_canary = "VIEW-PASSWORD-LEAK-CANARY";
|
||||
let runtime = runtime();
|
||||
|
||||
let owner = runtime.block_on(crate::open_wallet_owner_v1(FULL_VECTOR, crate::OwnerPassword::new(std::string::String::from(owner_canary))));
|
||||
let owner_error = owner.expect_err("wrong OWNER password must fail");
|
||||
assert_eq!(owner_error.code(), crate::ERROR_CODE_OWNER_UNLOCK_FAILED);
|
||||
assert!(!owner_error.to_string().contains(owner_canary));
|
||||
assert!(!format!("{owner_error:?}").contains(owner_canary));
|
||||
|
||||
let view = runtime.block_on(crate::open_wallet_view_v1(FULL_VECTOR, crate::ViewPassword::new(std::string::String::from(view_canary))));
|
||||
let view_error = view.expect_err("wrong VIEW password must fail");
|
||||
assert_eq!(view_error.code(), crate::ERROR_CODE_VIEW_UNLOCK_FAILED);
|
||||
assert!(!view_error.to_string().contains(view_canary));
|
||||
assert!(!format!("{view_error:?}").contains(view_canary));
|
||||
}
|
||||
|
||||
fn tamper_base64url_field(source: &[u8], pointer: &str) -> std::vec::Vec<u8> {
|
||||
let mut value: serde_json::Value = serde_json::from_slice(source).expect("security fixture must be valid JSON");
|
||||
let target = value.pointer_mut(pointer).expect("security fixture pointer must exist");
|
||||
let encoded = target.as_str().expect("security fixture target must be a Base64url string");
|
||||
let mut decoded = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(encoded.as_bytes()).expect("security fixture Base64url must decode");
|
||||
let first = decoded.first_mut().expect("security fixture Base64url field must not be empty");
|
||||
*first ^= 0x01;
|
||||
*target = serde_json::Value::String(base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(decoded.as_slice()));
|
||||
zeroize::Zeroize::zeroize(decoded.as_mut_slice());
|
||||
return serde_json::to_vec(&value).expect("tampered security fixture must serialize");
|
||||
}
|
||||
|
||||
fn runtime() -> tokio::runtime::Runtime {
|
||||
return tokio::runtime::Builder::new_current_thread().build().expect("security test runtime must be creatable");
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/transcript.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
use base64::Engine as _;
|
||||
use base64::Engine; // rust-rules: derive-import
|
||||
|
||||
const FIXTURE: &[u8] = include_bytes!("../tests/fixtures/kspwallet_v1_wire_only.json");
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/transfer.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
use zeroize::Zeroize as _;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::PermissionsExt; // rust-rules: derive-import
|
||||
use zeroize::Zeroize; // rust-rules: derive-import
|
||||
|
||||
fn runtime() -> tokio::runtime::Runtime {
|
||||
return tokio::runtime::Builder::new_current_thread().build().expect("Wallet transfer test runtime must build");
|
||||
@@ -234,7 +236,6 @@ fn owner_transfer_file_export_is_no_clobber() {
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt as _;
|
||||
let mode = std::fs::metadata(export_path.as_path()).expect("export metadata must be readable").permissions().mode() & 0o777;
|
||||
assert_eq!(mode, 0o600);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/wallet.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
const FULL_VECTOR: &[u8] = include_bytes!("../tests/fixtures/kspwallet_v1_full_vector.json");
|
||||
const FULL_VECTOR_META: &[u8] = include_bytes!("../tests/fixtures/kspwallet_v1_full_vector_meta.json");
|
||||
@@ -26,7 +26,7 @@ fn externally_generated_full_vector_opens_view_and_owner_independently() -> ksp_
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
let view_result = runtime.block_on(super::open_wallet_view_v1(FULL_VECTOR, crate::ViewPassword::new(vector.view_password_utf8)));
|
||||
let view_result = runtime.block_on(crate::open_wallet_view_v1(FULL_VECTOR, crate::ViewPassword::new(vector.view_password_utf8)));
|
||||
let view = match view_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
@@ -36,7 +36,7 @@ fn externally_generated_full_vector_opens_view_and_owner_independently() -> ksp_
|
||||
assert_eq!(view.alias(), std::option::Option::Some(vector.expected_alias.as_str()));
|
||||
assert_note_texts(view.notes(), vector.expected_notes.as_slice());
|
||||
|
||||
let owner_result = runtime.block_on(super::open_wallet_owner_v1(FULL_VECTOR, crate::OwnerPassword::new(vector.owner_password_utf8)));
|
||||
let owner_result = runtime.block_on(crate::open_wallet_owner_v1(FULL_VECTOR, crate::OwnerPassword::new(vector.owner_password_utf8)));
|
||||
let owner = match owner_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
@@ -59,21 +59,21 @@ fn wrong_passwords_do_not_cross_unlock_capabilities() -> ksp_core_lib::Result<()
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
let wrong_view = runtime.block_on(super::open_wallet_view_v1(FULL_VECTOR, crate::ViewPassword::new(std::string::String::from("wrong-view-password"))));
|
||||
let wrong_view = runtime.block_on(crate::open_wallet_view_v1(FULL_VECTOR, crate::ViewPassword::new(std::string::String::from("wrong-view-password"))));
|
||||
let wrong_view_error = match wrong_view {
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(test_error("wrong VIEW password unexpectedly unlocked Wallet")),
|
||||
std::result::Result::Err(error) => error,
|
||||
};
|
||||
assert_eq!(wrong_view_error.code(), crate::ERROR_CODE_VIEW_UNLOCK_FAILED);
|
||||
|
||||
let wrong_owner = runtime.block_on(super::open_wallet_owner_v1(FULL_VECTOR, crate::OwnerPassword::new(std::string::String::from("wrong-owner-password"))));
|
||||
let wrong_owner = runtime.block_on(crate::open_wallet_owner_v1(FULL_VECTOR, crate::OwnerPassword::new(std::string::String::from("wrong-owner-password"))));
|
||||
let wrong_owner_error = match wrong_owner {
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(test_error("wrong OWNER password unexpectedly unlocked Wallet")),
|
||||
std::result::Result::Err(error) => error,
|
||||
};
|
||||
assert_eq!(wrong_owner_error.code(), crate::ERROR_CODE_OWNER_UNLOCK_FAILED);
|
||||
|
||||
let view_as_owner = runtime.block_on(super::open_wallet_owner_v1(FULL_VECTOR, crate::OwnerPassword::new(vector.view_password_utf8)));
|
||||
let view_as_owner = runtime.block_on(crate::open_wallet_owner_v1(FULL_VECTOR, crate::OwnerPassword::new(vector.view_password_utf8)));
|
||||
let view_as_owner_error = match view_as_owner {
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(test_error("VIEW password unexpectedly unlocked OWNER")),
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -88,7 +88,7 @@ fn owner_signed_metadata_tampering_is_rejected_before_unlock() -> ksp_core_lib::
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let inspect_result = super::inspect_locked_wallet_v1(tampered.as_slice());
|
||||
let inspect_result = crate::inspect_locked_wallet_v1(tampered.as_slice());
|
||||
let error = match inspect_result {
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(test_error("tampered OWNER-signed metadata unexpectedly verified")),
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -107,7 +107,7 @@ fn view_wrap_can_change_without_breaking_owner_authenticated_state() -> ksp_core
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let inspected = match super::inspect_locked_wallet_v1(tampered.as_slice()) {
|
||||
let inspected = match crate::inspect_locked_wallet_v1(tampered.as_slice()) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
@@ -117,12 +117,12 @@ fn view_wrap_can_change_without_breaking_owner_authenticated_state() -> ksp_core
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let owner_result = runtime.block_on(super::open_wallet_owner_v1(tampered.as_slice(), crate::OwnerPassword::new(vector.owner_password_utf8)));
|
||||
let owner_result = runtime.block_on(crate::open_wallet_owner_v1(tampered.as_slice(), crate::OwnerPassword::new(vector.owner_password_utf8)));
|
||||
if let std::result::Result::Err(error) = owner_result {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
|
||||
let view_result = runtime.block_on(super::open_wallet_view_v1(tampered.as_slice(), crate::ViewPassword::new(vector.view_password_utf8)));
|
||||
let view_result = runtime.block_on(crate::open_wallet_view_v1(tampered.as_slice(), crate::ViewPassword::new(vector.view_password_utf8)));
|
||||
let view_error = match view_result {
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(test_error("modified VIEW wrapping unexpectedly unlocked metadata")),
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -147,7 +147,7 @@ fn locked_full_vector_contains_no_authorized_identity_or_metadata_plaintext() ->
|
||||
for note in vector.expected_notes {
|
||||
assert!(!document.contains(note.as_str()));
|
||||
}
|
||||
let locked = match super::inspect_locked_wallet_v1(FULL_VECTOR) {
|
||||
let locked = match crate::inspect_locked_wallet_v1(FULL_VECTOR) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
@@ -181,7 +181,7 @@ fn create_uses_calibrated_defaults_and_keeps_locked_projection_private() -> ksp_
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let owner_result = runtime.block_on(super::create_wallet_v1(
|
||||
let owner_result = runtime.block_on(crate::create_wallet_v1(
|
||||
crate::OwnerPassword::new(std::string::String::from("pre005-create-owner-password")),
|
||||
std::option::Option::None,
|
||||
metadata,
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/wire.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
const FIXTURE: &[u8] = include_bytes!("../tests/fixtures/kspwallet_v1_wire_only.json");
|
||||
|
||||
#[test]
|
||||
fn strict_v1_fixture_parses_and_round_trips_semantically() -> ksp_core_lib::Result<()> {
|
||||
let parsed = match super::KspWalletEnvelopeV1::parse_json(FIXTURE) {
|
||||
let parsed = match crate::KspWalletEnvelopeV1::parse_json(FIXTURE) {
|
||||
std::result::Result::Ok(parsed) => parsed,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(parsed.format_version(), crate::KSPWALLET_FORMAT_VERSION_V1);
|
||||
assert!(parsed.view_descriptor().enabled());
|
||||
assert_eq!(parsed.owner_slot().role(), super::WalletKeySlotRoleV1::Owner);
|
||||
assert_eq!(parsed.view_slot().map(super::WalletKeySlotV1::role), std::option::Option::Some(super::WalletKeySlotRoleV1::View));
|
||||
assert_eq!(parsed.owner_slot().role(), crate::WalletKeySlotRoleV1::Owner);
|
||||
assert_eq!(parsed.view_slot().map(crate::WalletKeySlotV1::role), std::option::Option::Some(crate::WalletKeySlotRoleV1::View));
|
||||
assert_eq!(parsed.owner_control().payload_version(), 1);
|
||||
assert_eq!(parsed.metadata().payload_version(), 1);
|
||||
assert_eq!(parsed.secret().payload_version(), 1);
|
||||
@@ -21,7 +21,7 @@ fn strict_v1_fixture_parses_and_round_trips_semantically() -> ksp_core_lib::Resu
|
||||
std::result::Result::Ok(serialized) => serialized,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let reparsed = match super::KspWalletEnvelopeV1::parse_json(serialized.as_slice()) {
|
||||
let reparsed = match crate::KspWalletEnvelopeV1::parse_json(serialized.as_slice()) {
|
||||
std::result::Result::Ok(reparsed) => reparsed,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
@@ -32,7 +32,7 @@ fn strict_v1_fixture_parses_and_round_trips_semantically() -> ksp_core_lib::Resu
|
||||
#[test]
|
||||
fn unknown_format_version_is_rejected_before_v1_shape_validation() {
|
||||
let source = std::string::String::from_utf8_lossy(FIXTURE).replace("\"format_version\": 1", "\"format_version\": 2");
|
||||
let result = super::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
let result = crate::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
assert!(result.is_err());
|
||||
let error = match result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -44,7 +44,7 @@ fn unknown_format_version_is_rejected_before_v1_shape_validation() {
|
||||
#[test]
|
||||
fn unknown_top_level_field_is_rejected() {
|
||||
let source = std::string::String::from_utf8_lossy(FIXTURE).replacen("{", "{\n \"unexpected\": true,", 1);
|
||||
let result = super::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
let result = crate::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
assert!(result.is_err());
|
||||
let error = match result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -57,7 +57,7 @@ fn unknown_top_level_field_is_rejected() {
|
||||
fn padded_or_noncanonical_base64url_is_rejected() {
|
||||
let source = std::string::String::from_utf8_lossy(FIXTURE)
|
||||
.replace("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8\"", "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=\"");
|
||||
let result = super::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
let result = crate::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
assert!(result.is_err());
|
||||
let error = match result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -70,7 +70,7 @@ fn padded_or_noncanonical_base64url_is_rejected() {
|
||||
fn enabled_view_descriptor_must_match_the_view_slot() {
|
||||
let source =
|
||||
std::string::String::from_utf8_lossy(FIXTURE).replacen("\"slot_id\": \"ICEiIyQlJicoKSorLC0uLw\"", "\"slot_id\": \"EBESExQVFhcYGRobHB0eHw\"", 1);
|
||||
let result = super::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
let result = crate::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
assert!(result.is_err());
|
||||
let error = match result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -82,7 +82,7 @@ fn enabled_view_descriptor_must_match_the_view_slot() {
|
||||
#[test]
|
||||
fn zero_or_pathological_kdf_parameters_are_rejected_before_crypto() {
|
||||
let zero_source = std::string::String::from_utf8_lossy(FIXTURE).replacen("\"memory_kib\": 65536", "\"memory_kib\": 0", 1);
|
||||
let zero_result = super::KspWalletEnvelopeV1::parse_json(zero_source.as_bytes());
|
||||
let zero_result = crate::KspWalletEnvelopeV1::parse_json(zero_source.as_bytes());
|
||||
assert!(zero_result.is_err());
|
||||
let zero_error = match zero_result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -91,7 +91,7 @@ fn zero_or_pathological_kdf_parameters_are_rejected_before_crypto() {
|
||||
assert_eq!(zero_error.code(), crate::ERROR_CODE_CRYPTO_PARAMETERS_INVALID);
|
||||
|
||||
let high_source = std::string::String::from_utf8_lossy(FIXTURE).replacen("\"memory_kib\": 65536", "\"memory_kib\": 1048577", 1);
|
||||
let high_result = super::KspWalletEnvelopeV1::parse_json(high_source.as_bytes());
|
||||
let high_result = crate::KspWalletEnvelopeV1::parse_json(high_source.as_bytes());
|
||||
assert!(high_result.is_err());
|
||||
let high_error = match high_result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -107,7 +107,7 @@ fn argon2_memory_must_cover_all_lanes_before_crypto() {
|
||||
"\"parallelism\": 2",
|
||||
1,
|
||||
);
|
||||
let result = super::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
let result = crate::KspWalletEnvelopeV1::parse_json(source.as_bytes());
|
||||
assert!(result.is_err());
|
||||
let error = match result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -119,7 +119,7 @@ fn argon2_memory_must_cover_all_lanes_before_crypto() {
|
||||
#[test]
|
||||
fn oversized_document_is_rejected_before_json_or_crypto() {
|
||||
let oversized = std::vec![b' '; crate::KSPWALLET_MAX_FILE_BYTES + 1];
|
||||
let result = super::KspWalletEnvelopeV1::parse_json(oversized.as_slice());
|
||||
let result = crate::KspWalletEnvelopeV1::parse_json(oversized.as_slice());
|
||||
assert!(result.is_err());
|
||||
let error = match result {
|
||||
std::result::Result::Err(error) => error,
|
||||
@@ -130,7 +130,7 @@ fn oversized_document_is_rejected_before_json_or_crypto() {
|
||||
|
||||
#[test]
|
||||
fn envelope_debug_does_not_render_ciphertext_contents() -> ksp_core_lib::Result<()> {
|
||||
let parsed = match super::KspWalletEnvelopeV1::parse_json(FIXTURE) {
|
||||
let parsed = match crate::KspWalletEnvelopeV1::parse_json(FIXTURE) {
|
||||
std::result::Result::Ok(parsed) => parsed,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user