CommutativeSchemeConformanceSuite
Conformance TCK for CommutativeScheme. Validate a new scheme by subclassing this suite and overriding newScheme, newPeerScheme and proofStrength:
class MySchemeConformanceTest : CommutativeSchemeConformanceSuite() {
override fun newScheme() = MyScheme()
override fun newPeerScheme() = MyScheme()
override fun proofStrength() = ProofStrength.RejectsForgeries
}The suite verifies the commutative-encryption laws the card-deal protocol relies on (round-trip, commutativity, multi-layer strip-order independence, key distinctness) — both within one scheme instance and across the separate instances real peers actually run. It tests the raw CommutativeScheme contract on in-domain byte messages — plaintext domain encoding (e.g. SRA's marker codec) is a scheme-layer concern and is out of scope here; override validPlaintexts if your scheme's valid domain differs from short ASCII.
Every law above is satisfied by a scheme that does nothing. A encrypt returning its argument round-trips, commutes, strips in any order and — because distinctKeysProduceDistinctCiphertexts compares two keys rather than a key against the plaintext — survives even that. So two properties here are about the laws being worth something rather than about them holding: encryptHidesThePlaintextAndStripRecoversIt and the two multi-layer properties assert a layer changes what it covers and keeps changing it until the last one comes off; verifyAnswersForgedTransitionsAsDeclared calls the scheme's verify* pair with transitions it did not produce. Before #2313 the suite touched verify* only on honest input, which is the accept branch of a predicate every shipped scheme stubs to true — coverage in appearance and nothing in fact.
Functions
Round-trip — strip(encrypt(m, k), k) == m — and the secrecy floor: the ciphertext is not the plaintext.
The same law across the instance boundary a real deal actually has: a is applied by the scheme that minted it and b by the scheme that minted it, so nothing about the two layers passes through one object. encryptionIsCommutative one screen up is the degenerate case of this — and the only case the suite had before #2311.
Every pair CommutativeScheme.generateKey hands out both round-trips and hides — the secrecy floor said of the generator rather than of one key.
A three-player deal in the arrangement a real one has: three separately constructed schemes, each holding only its own key, each applying and later removing only its own layer. This is the only property in the suite that drives CommutativeScheme.strip across the instance boundary — encryptionIsCommutativeAcrossPeerInstances covers encrypt alone, and the single-instance sibling above covers both with the boundary removed.
Three layers on, three off in a deranged order, and the plaintext comes back — and the card is unreadable at every step in between.
A second, independently constructed scheme instance — what a remote peer runs, in its own process, on its own device.
A fresh scheme instance under test.
What this scheme's CommutativeScheme.verifyEncrypt / CommutativeScheme.verifyStrip pair does with a transition it did not produce — a declaration the subclass makes and verifyAnswersForgedTransitionsAsDeclared then holds it to.
Sample messages guaranteed to lie in the scheme's valid input domain.
Honest-path verification: an CommutativeScheme.encrypt/CommutativeScheme.strip transition that the scheme itself produced must verify. This is the completeness half — a verifier that rejects everything is as useless as one that accepts everything, and only this property refuses it.
verify* called with six transitions the scheme did not produce, and held to the answer proofStrength declared for all six.