Zulip Chat Archive
Stream: lean4
Topic: type class combiner with polymorphic list type/instance?
David Stainton 🦡 (Aug 29 2024 at 05:30):
New to Lean. Trying to keep my question concise.
I need some guidance or advice on using Lean.
I should say that I'm only about half-way through reading Functional Programming in Lean.
So... perhaps you can tell me, go and read these chapters over there and then revisit this problem.
I wrote a KEM type class.
My goal is to write a KEM combiner which combines an arbitrary number of KEMs together.
Seems like I can't just put this into the Combiner type class definition...
List (Σ α : Type, KEM α × α)
Perhaps my KEM type class is not good and I need something else.
Before I realized exactly how I wanted to use Lean, I was curious how Lean
might be used to create symbolic cryptographic models, so @Mario Carneiro
wrote a really impressive KEM definition, complete with proofs of "KEM correctness".
My intention is to revisit that later after I learn Lean a bit better.
Here's what my KEM type class looks like... using my beginner Lean functional programming skills:
class Key (key : Type) where
encode : key → ByteArray
decode : ByteArray → Option key
class PrivateKey (privkey : Type) extends Key privkey
class PublicKey (pubkey : Type) extends Key pubkey
class KEM (scheme : Type) where
PublicKeyType : Type
PrivateKeyType : Type
name : String
generateKeyPair : IO (PublicKeyType × PrivateKeyType)
encapsulate : scheme → PublicKeyType → IO (ByteArray × ByteArray)
decapsulate : scheme → PrivateKeyType → ByteArray → ByteArray
privateKeySize : Nat
publicKeySize : Nat
encodePrivateKey : PrivateKeyType → ByteArray
decodePrivateKey : ByteArray → Option PrivateKeyType
encodePublicKey : PublicKeyType → ByteArray
decodePublicKey : ByteArray → Option PublicKeyType
I construct my List of KEM like this:
def defaultHash := fun x => Sha256.hash x
instance : Adapter X25519Scheme where
hash := defaultHash
instance : Adapter X448Scheme where
hash := defaultHash
instance : Adapter X41417Scheme where
hash := defaultHash
def X25519AsKEM : KEM X25519Scheme := inferInstance
def X448AsKEM : KEM X448Scheme := inferInstance
def X41417AsKEM : KEM X41417Scheme := inferInstance
def X25519Instance : X25519Scheme := {}
def X448Instance : X448Scheme := {}
def X41417Instance : X41417Scheme := {}
def Schemes : List (Σ α : Type, KEM α × α) :=
[
⟨X25519Scheme, (X25519AsKEM, X25519Instance)⟩,
⟨X448Scheme, (X448AsKEM, X448Instance)⟩,
⟨X41417Scheme, (X41417AsKEM, X41417Instance)⟩,
]
I test the list of KEMs like this:
def testKEM {α : Type} [kemInstance : KEM α] (kem : α) : IO Unit := do
let (alicePublicKey, alicePrivateKey) ← kemInstance.generateKeyPair
let (ciphertext, bobSharedSecret) ← kemInstance.encapsulate kem alicePublicKey
let aliceSharedSecret := kemInstance.decapsulate kem alicePrivateKey ciphertext
if bobSharedSecret == aliceSharedSecret then
IO.println s!"KEM test for {kemInstance.name} PASSED."
else
panic! "KEM test failed!"
def testAllKEMs : List (Σ α : Type, KEM α × α) → IO Unit
| [] => IO.println "All KEM tests passed!"
| ⟨_, _, kem⟩ :: rest => do
testKEM kem
testAllKEMs rest
Yakov Pechersky (Aug 29 2024 at 05:51):
May I ask, why do you use class and instance, as opposed to structure and def?
David Stainton 🦡 (Aug 29 2024 at 05:52):
Not sure. Would it be better to use structures to represent the KEM instead?
Yakov Pechersky (Aug 29 2024 at 05:52):
Your testKem is expecting to find the Kem functions using typeclass search. But in your testAllKEMs, you aren't supplying the unwrapped foo : KEM kem
back to the TC system
Yakov Pechersky (Aug 29 2024 at 05:55):
You could change your inductive step to have
def testAllKEMs : List (Σ α : Type, KEM α × α) → IO Unit
| [] => IO.println "All KEM tests passed!"
| ⟨_, inst, kem⟩ :: rest => do
have := inst
testKEM kem
testAllKEMs rest
David Stainton 🦡 (Aug 29 2024 at 05:59):
Okay thanks I'll try changing it to a polymorphic structure. It sounds like that could make it easier to write a Kem combiner. The structure could have a field of the List type above.
Yakov Pechersky (Aug 29 2024 at 05:59):
Did my example work even with the current class based style?
David Stainton 🦡 (Aug 29 2024 at 06:07):
yeah your change works too.
Last updated: May 02 2025 at 03:31 UTC