| Copyright | (c) 2023-2024 Apotheca Labs (c) 2024-2025 Haskell Foundation |
|---|---|
| License | BSD-3-Clause |
| Maintainer | joris@well-typed.com, leo@apotheca.io |
| Stability | experimental |
| Portability | POSIX |
| Safe Haskell | Safe-Inferred |
| Language | GHC2021 |
Botan.Low.PubKey.KeyAgreement
Description
Synopsis
- newtype KeyAgreement = MkKeyAgreement {}
- withKeyAgreement :: KeyAgreement -> (BotanPKOpKeyAgreement -> IO a) -> IO a
- keyAgreementCreate :: PrivKey -> KDFName -> IO KeyAgreement
- keyAgreementDestroy :: KeyAgreement -> IO ()
- keyAgreementExportPublic :: PrivKey -> IO ByteString
- keyAgreementSize :: KeyAgreement -> IO Int
- keyAgreement :: KeyAgreement -> ByteString -> ByteString -> IO ByteString
PK Key Agreement
Key agreement is a scheme where two parties exchange public keys, after which it is possible for them to derive a secret key which is known only to the two of them.
There are different approaches possible for key agreement. In many protocols, both parties generate a new key, exchange public keys, and derive a secret, after which they throw away their private keys, using them only the once. However this requires the parties to both be online and able to communicate with each other.
In other protocols, one of the parties publishes their public key online in some way, and then it is possible for someone to send encrypted messages to that recipient by generating a new keypair, performing key exchange with the published public key, and then sending both the message along with their ephemeral public key. Then the recipient uses the provided public key along with their private key to complete the key exchange, recover the shared secret, and decrypt the message.
Typically the raw output of the key agreement function is not uniformly distributed, and may not be of an appropriate length to use as a key. To resolve these problems, key agreement will use a Key Derivation Functions (KDF) on the shared secret to produce an output of the desired length.
- ECDH over GF(p) Weierstrass curves
- ECDH over x25519
- DH over prime fields
Usage
This is a simplified, executable example showing how Alice and Bob can derive the same shared secret using key agreement.
>>>:{{-# OPTIONS_GHC -Wall #-} import Botan.Low.Hash import Botan.Low.KDF import Botan.Low.PubKey import Botan.Low.PubKey.KeyAgreement import Botan.Low.RNG import Data.ByteString (ByteString) :}
First, Alice and Bob generate their private keys:
>>>:{generateKeys :: IO (PrivKey, PrivKey) generateKeys = do rng <- rngInit UserRNG alicePrivKey <- privKeyCreate ECDH Secp521r1 rng bobPrivKey <- privKeyCreate ECDH Secp521r1 rng pure (alicePrivKey, bobPrivKey) :}
Then, they exchange their public keys using any channel, private or public and independently derive shared keys.
Alice and Bob exchange public keys:
>>>:{deriveSharedKeys :: PrivKey -> PrivKey -> IO (ByteString, ByteString) deriveSharedKeys alicePrivKey bobPrivKey = do rng <- rngInit UserRNG alicePubKey <- keyAgreementExportPublic alicePrivKey bobPubKey <- keyAgreementExportPublic bobPrivKey salt <- rngGet rng 4 aliceKeyAgreement <- keyAgreementCreate alicePrivKey (kdf2 SHA256) aliceSharedKey <- keyAgreement aliceKeyAgreement bobPubKey salt bobKeyAgreement <- keyAgreementCreate bobPrivKey (kdf2 SHA256) bobSharedKey <- keyAgreement bobKeyAgreement alicePubKey salt pure (aliceSharedKey, bobSharedKey) :}
Now we can check that both parties derive the same shared key using the same salt:
>>>:{main :: IO () main = do (alicePrivKey, bobPrivKey) <- generateKeys (aliceSharedKey, bobSharedKey) <- deriveSharedKeys alicePrivKey bobPrivKey print (aliceSharedKey == bobSharedKey) :}
>>>mainTrue
Key agreement
newtype KeyAgreement Source #
Constructors
| MkKeyAgreement | |
withKeyAgreement :: KeyAgreement -> (BotanPKOpKeyAgreement -> IO a) -> IO a Source #
Arguments
| :: PrivKey | key |
| -> KDFName | kdf |
| -> IO KeyAgreement | op |
keyAgreementDestroy :: KeyAgreement -> IO () Source #
keyAgreementExportPublic Source #
Arguments
| :: PrivKey | key |
| -> IO ByteString | out[] |
Arguments
| :: KeyAgreement | op |
| -> IO Int | out_len |
Arguments
| :: KeyAgreement | op |
| -> ByteString | out[] |
| -> ByteString | other_key[] |
| -> IO ByteString | salt[] |