Skip to content

Commit 7646902

Browse files
committed
test(eql-bindings): a keyset opener refuses a value from another keyset
Review of #1095: `Opener::Keyset`'s docs promised the refusal and no test proved it; had that arm opened through the client, a keyset caller would have read another tenant's plaintext. Sealed under acme, opened under globex: ForeignKeyset with nothing retrieved; acme and the client open it. Claude-Session: https://claude.ai/code/session_01V3WFXwax4J3uecpFEJ6yHc
1 parent 20560da commit 7646902

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

‎packages/eql/tests/encryption/tests/targets.rs‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,44 @@ mod given_text_eq {
136136
);
137137
}
138138

139+
/// A keyset opener refuses a value another keyset sealed, before any key
140+
/// is retrieved; the client opens it. If `Opener::Keyset` opened through
141+
/// the client, one tenant's cipher would read another's column.
142+
#[tokio::test]
143+
async fn a_keyset_opener_refuses_a_value_from_another_keyset() {
144+
use stack_kms::IdentifiedBy;
145+
let (cipher, calls) = common::cipher().await;
146+
let named = |n: &str| IdentifiedBy::Name(n.to_string().into());
147+
let acme = cipher.keyset(named("acme")).await.unwrap();
148+
let globex = cipher.keyset(named("globex")).await.unwrap();
149+
let stored = targets::encrypt("TextEq", &acme, &email(), text("secret"))
150+
.unwrap()
151+
.await
152+
.unwrap();
153+
let result = targets::decrypt("TextEq", &globex, &email(), &stored)
154+
.unwrap()
155+
.await;
156+
match result {
157+
Err(stack_encrypt::Error::ForeignKeyset { .. }) => {}
158+
Err(other) => panic!("refused, but not as a foreign keyset: {other}"),
159+
Ok(_) => panic!("globex opened acme's value"),
160+
}
161+
assert!(
162+
calls.lock().unwrap().retrieve.is_empty(),
163+
"nothing was retrieved"
164+
);
165+
let own = targets::decrypt("TextEq", &acme, &email(), &stored)
166+
.unwrap()
167+
.await
168+
.expect("its own keyset opens it");
169+
assert_eq!(opened(own), "secret");
170+
let through_client = targets::decrypt("TextEq", &cipher, &email(), &stored)
171+
.unwrap()
172+
.await
173+
.expect("the client opens any of its keysets' values");
174+
assert_eq!(opened(through_client), "secret");
175+
}
176+
139177
#[tokio::test]
140178
async fn query_bytes_are_the_typed_query_twin() {
141179
let (cipher, calls) = common::cipher().await;

0 commit comments

Comments
 (0)