API-style comments and ktlint formatting
Every comment is reduced to its first sentence plus @param, @return and @throws tags. Comment lines: 20040 to 8526. ktlint 1.8 applied with its default (official Kotlin) style across all modules; 262 files reformatted. The 264 remaining ktlint findings are naming and filename rules, which are code changes, and are left alone. Comments and formatting only. 1208 tests pass, counted from the XML. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
8a7f40fb13
commit
2fa430f21c
@@ -7,16 +7,8 @@ import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* X3DH, both directions.
|
||||
*
|
||||
* The property that matters is agreement: Alice computes a secret from her
|
||||
* private keys and Bob's public bundle, Bob computes one from his private keys
|
||||
* and what Alice sent, and the two must be identical. A wrong DH order, a
|
||||
* swapped argument, or a zero-filled DH4 all still produce 32 plausible bytes,
|
||||
* they just produce *different* 32 bytes on each side, which is why this checks
|
||||
* equality rather than shape.
|
||||
*/
|
||||
class X3DHTest {
|
||||
|
||||
private fun raw(kp: java.security.KeyPair) = X25519.rawFromPublicKey(kp.public)
|
||||
|
||||
@Test
|
||||
@@ -26,21 +18,24 @@ class X3DHTest {
|
||||
val bobSigned = X25519.generate()
|
||||
val bobOneTime = X25519.generate()
|
||||
|
||||
val alice = X3DH.initiate(
|
||||
identityPrivateDH = aliceIdentity.private,
|
||||
bundle = X3DH.Bundle(
|
||||
identityKeyDH = raw(bobIdentity),
|
||||
signedPreKey = raw(bobSigned),
|
||||
oneTimePreKey = raw(bobOneTime),
|
||||
),
|
||||
)
|
||||
val bob = X3DH.respond(
|
||||
identityPrivateDH = bobIdentity.private,
|
||||
signedPreKeyPrivate = bobSigned.private,
|
||||
oneTimePrivate = bobOneTime.private,
|
||||
initiatorIdentityDH = raw(aliceIdentity),
|
||||
initiatorEphemeral = alice.ephemeralPublic,
|
||||
)
|
||||
val alice =
|
||||
X3DH.initiate(
|
||||
identityPrivateDH = aliceIdentity.private,
|
||||
bundle =
|
||||
X3DH.Bundle(
|
||||
identityKeyDH = raw(bobIdentity),
|
||||
signedPreKey = raw(bobSigned),
|
||||
oneTimePreKey = raw(bobOneTime),
|
||||
),
|
||||
)
|
||||
val bob =
|
||||
X3DH.respond(
|
||||
identityPrivateDH = bobIdentity.private,
|
||||
signedPreKeyPrivate = bobSigned.private,
|
||||
oneTimePrivate = bobOneTime.private,
|
||||
initiatorIdentityDH = raw(aliceIdentity),
|
||||
initiatorEphemeral = alice.ephemeralPublic,
|
||||
)
|
||||
assertContentEquals(alice.sharedSecret, bob, "the two sides disagree")
|
||||
assertTrue(alice.sharedSecret.size == 32)
|
||||
}
|
||||
@@ -48,23 +43,24 @@ class X3DHTest {
|
||||
@Test
|
||||
fun `both sides agree when the one-time prekey pool is drained`() {
|
||||
// A degraded but valid state: initial forward secrecy is lost, and the
|
||||
// session must still work. Omitting DH4 on one side while the other
|
||||
// zero-fills it is the classic way to break exactly this case.
|
||||
// session must still work.
|
||||
val aliceIdentity = X25519.generate()
|
||||
val bobIdentity = X25519.generate()
|
||||
val bobSigned = X25519.generate()
|
||||
|
||||
val alice = X3DH.initiate(
|
||||
identityPrivateDH = aliceIdentity.private,
|
||||
bundle = X3DH.Bundle(raw(bobIdentity), raw(bobSigned), null),
|
||||
)
|
||||
val bob = X3DH.respond(
|
||||
identityPrivateDH = bobIdentity.private,
|
||||
signedPreKeyPrivate = bobSigned.private,
|
||||
oneTimePrivate = null,
|
||||
initiatorIdentityDH = raw(aliceIdentity),
|
||||
initiatorEphemeral = alice.ephemeralPublic,
|
||||
)
|
||||
val alice =
|
||||
X3DH.initiate(
|
||||
identityPrivateDH = aliceIdentity.private,
|
||||
bundle = X3DH.Bundle(raw(bobIdentity), raw(bobSigned), null),
|
||||
)
|
||||
val bob =
|
||||
X3DH.respond(
|
||||
identityPrivateDH = bobIdentity.private,
|
||||
signedPreKeyPrivate = bobSigned.private,
|
||||
oneTimePrivate = null,
|
||||
initiatorIdentityDH = raw(aliceIdentity),
|
||||
initiatorEphemeral = alice.ephemeralPublic,
|
||||
)
|
||||
assertContentEquals(alice.sharedSecret, bob)
|
||||
}
|
||||
|
||||
@@ -79,16 +75,18 @@ class X3DHTest {
|
||||
val bobOneTime = X25519.generate()
|
||||
val ephemeral = X25519.generate()
|
||||
|
||||
val withOpk = X3DH.initiate(
|
||||
aliceIdentity.private,
|
||||
X3DH.Bundle(raw(bobIdentity), raw(bobSigned), raw(bobOneTime)),
|
||||
ephemeral,
|
||||
)
|
||||
val withoutOpk = X3DH.initiate(
|
||||
aliceIdentity.private,
|
||||
X3DH.Bundle(raw(bobIdentity), raw(bobSigned), null),
|
||||
ephemeral,
|
||||
)
|
||||
val withOpk =
|
||||
X3DH.initiate(
|
||||
aliceIdentity.private,
|
||||
X3DH.Bundle(raw(bobIdentity), raw(bobSigned), raw(bobOneTime)),
|
||||
ephemeral,
|
||||
)
|
||||
val withoutOpk =
|
||||
X3DH.initiate(
|
||||
aliceIdentity.private,
|
||||
X3DH.Bundle(raw(bobIdentity), raw(bobSigned), null),
|
||||
ephemeral,
|
||||
)
|
||||
assertFalse(withOpk.sharedSecret.contentEquals(withoutOpk.sharedSecret))
|
||||
}
|
||||
|
||||
@@ -100,15 +98,16 @@ class X3DHTest {
|
||||
val malloryIdentity = X25519.generate()
|
||||
val mallorySigned = X25519.generate()
|
||||
|
||||
val toBob = X3DH.initiate(
|
||||
aliceIdentity.private, X3DH.Bundle(raw(bobIdentity), raw(bobSigned), null))
|
||||
val malloryTries = X3DH.respond(
|
||||
identityPrivateDH = malloryIdentity.private,
|
||||
signedPreKeyPrivate = mallorySigned.private,
|
||||
oneTimePrivate = null,
|
||||
initiatorIdentityDH = raw(aliceIdentity),
|
||||
initiatorEphemeral = toBob.ephemeralPublic,
|
||||
)
|
||||
val toBob =
|
||||
X3DH.initiate(aliceIdentity.private, X3DH.Bundle(raw(bobIdentity), raw(bobSigned), null))
|
||||
val malloryTries =
|
||||
X3DH.respond(
|
||||
identityPrivateDH = malloryIdentity.private,
|
||||
signedPreKeyPrivate = mallorySigned.private,
|
||||
oneTimePrivate = null,
|
||||
initiatorIdentityDH = raw(aliceIdentity),
|
||||
initiatorEphemeral = toBob.ephemeralPublic,
|
||||
)
|
||||
assertFalse(toBob.sharedSecret.contentEquals(malloryTries))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user