Skip to content

Commit 7e822ba

Browse files
committed
Add HPKE interop test between signum and Bouncy Castle
1 parent 547a42d commit 7e822ba

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package at.asitplus.wallet.lib.openid
2+
3+
import at.asitplus.signum.indispensable.ECCurve
4+
import at.asitplus.signum.indispensable.KeyAgreementPrivateValue
5+
import at.asitplus.signum.supreme.agree.Ephemeral
6+
import at.asitplus.signum.supreme.asymmetric.HPKE
7+
import at.asitplus.testballoon.matrix.matrixSuite
8+
import io.kotest.matchers.shouldBe
9+
import org.bouncycastle.crypto.hpke.HPKE as BcHpke
10+
import kotlin.random.Random
11+
12+
/**
13+
* Verifies that signum's HPKE (RFC 9180) implementation is interoperable with Bouncy Castle's,
14+
* for the cipher suite required by ISO/IEC 18013-7 Annex C (as used in [DcApiVerifier]):
15+
* DHKEM(P-256, HKDF-SHA256), HKDF-SHA256, AES-128-GCM.
16+
*/
17+
val HpkeInteropTest by matrixSuite {
18+
19+
val signumHpke = HPKE(HPKE.KEM.DHKEM_P256_HKDF_SHA256, HPKE.KDF.HKDF_SHA256, HPKE.AEAD.AES_128_GCM)
20+
val bcHpke = BcHpke(BcHpke.mode_base, BcHpke.kem_P256_SHA256, BcHpke.kdf_HKDF_SHA256, BcHpke.aead_AES_GCM128)
21+
22+
val plaintext = Random.nextBytes(257)
23+
val info = Random.nextBytes(64)
24+
val aad = Random.nextBytes(32)
25+
26+
test("signum seals, Bouncy Castle opens") {
27+
val recipientKeyPair = bcHpke.generatePrivateKey()
28+
val recipientPublicKey = signumHpke.kem.DeserializePublicKey(
29+
bcHpke.serializePublicKey(recipientKeyPair.public)
30+
)
31+
32+
val sealed = signumHpke.SealBase(pkR = recipientPublicKey, info = info, aad = aad, pt = plaintext)
33+
34+
bcHpke.open(
35+
sealed.encapsulatedSecret, recipientKeyPair, info, aad, sealed.ciphertext,
36+
null, null, null,
37+
) shouldBe plaintext
38+
}
39+
40+
test("Bouncy Castle seals, signum opens") {
41+
val recipientKey = KeyAgreementPrivateValue.ECDH.Ephemeral(ECCurve.SECP_256_R_1).getOrThrow()
42+
val recipientPublicKey = bcHpke.deserializePublicKey(
43+
signumHpke.kem.SerializePublicKey(recipientKey.publicValue)
44+
)
45+
46+
val sealed = bcHpke.seal(recipientPublicKey, info, aad, plaintext, null, null, null)
47+
val ciphertext = sealed[0]
48+
val encapsulatedSecret = sealed[1]
49+
50+
signumHpke.OpenBase(
51+
enc = encapsulatedSecret,
52+
skR = recipientKey,
53+
info = info,
54+
aad = aad,
55+
ct = ciphertext,
56+
) shouldBe plaintext
57+
}
58+
}

0 commit comments

Comments
 (0)