Skip to content

Instantly share code, notes, and snippets.

@Zenithar
Last active December 5, 2023 19:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zenithar/2e81cb7e122d0ff38adbd9971c3c939b to your computer and use it in GitHub Desktop.
Save Zenithar/2e81cb7e122d0ff38adbd9971c3c939b to your computer and use it in GitHub Desktop.
package main
import (
"crypto/ecdh"
"crypto/rand"
"crypto/sha256"
"fmt"
"io"
"os"
"github.com/cloudflare/circl/kem/kyber/kyber768"
"golang.org/x/crypto/hkdf"
)
// This snippet implements X25519+Kyber768 key exchange.
// https://www.ietf.org/archive/id/draft-tls-westerbaan-xyber768d00-02.html
func main() {
// X25518 ECDH
xc := ecdh.X25519()
// Kyber768 KEM
k := kyber768.Scheme()
// Client ------------------------------------------------------------------
// Generate private key
xskC, err := xc.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
xpkC := xskC.PublicKey()
kpkC, kskC, err := k.GenerateKeyPair()
if err != nil {
panic(err)
}
bkpkC, _ := kpkC.MarshalBinary()
fmt.Fprintf(os.Stdout, "Client => Server: xpkC (%x) || kpkC (%x)\n", xpkC.Bytes(), bkpkC)
// Server ------------------------------------------------------------------
// Generate private key
xskS, err := xc.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
xpkS := xskS.PublicKey()
// Generate random secret matching the encapsulated seed size.
randomSecret := make([]byte, k.EncapsulationSeedSize())
if _, err := io.ReadFull(rand.Reader, randomSecret[:]); err != nil {
panic(err)
}
// Encapsulate the random secret using the client kyber public key.
encS, ssS, err := k.EncapsulateDeterministically(kpkC, randomSecret)
if err != nil {
panic(err)
}
// Compute xpkC^xskS
xssS, err := xskS.ECDH(xpkC)
if err != nil {
panic(err)
}
// HKDF-SHA256(xssS || ssS) for final shared secret derivation.
sharedSecretS := hkdf.Extract(sha256.New, append(xssS, ssS...), nil)
fmt.Fprintf(os.Stdout, "Server => Client: xpkS (%x) || encS (%x)\n", xpkS.Bytes(), encS)
// Client ------------------------------------------------------------------
xssC, err := xskC.ECDH(xpkS)
if err != nil {
panic(err)
}
ssC, err := k.Decapsulate(kskC, encS)
if err != nil {
panic(err)
}
sharedSecretC := hkdf.Extract(sha256.New, append(xssC, ssC...), nil)
// -------------------------------------------------------------------------
fmt.Fprintf(os.Stdout, "SharedSecret (S) %x\n", sharedSecretS)
fmt.Fprintf(os.Stdout, "SharedSecret (C) %x\n", sharedSecretC)
}
Client => Server: xpkC (ff3e2fd4e76815edacc0459458ed9de85dc8c14454905c5d9e42ee16f4c0264e) || kpkC (e756581efca29d532d6f5c3b5efc5b8ee9a6f26aa2cae520a71acc19b668296196aab0b92cdb3b1f9705159494b23816c24502253313517131432ca48c10902b7588e1a41c8e1a9b2725cf5a48b0e1c750d6ec451b0b63f9ec8c147a39052bc9990cc94b04b275a469c592c2a81a2a3ad7c012b0c0b75669d26ac112654c94db16f49645430099b93337f42a91b946373443760854c7dd01699d43559da92b4f860ca2302b44ba7a3f7a202313438586cab3e804809792a80626b94906ef68344d8a8c5f05079545b6fac246c8eaa252196721193eb1a71eb6c89d5c458eaab984852267ec808df6829da1612ae9d132dd501c11f3247eea40f7597a590b42235a6bf840b365d93d20041671c67f44e3a65a43cb61577caed59929fa4fe9065a7a9c2655c2afb34abeac6625a4609d683ac10e6564c1ca6562078721e93f06f6378978676b52a026288c56e1b52398c5f5429587a1301c9c0afe952c0f29104f5b58c18186adb971e6e65314287b09969c57cc864afa642e86a818139883b127cae6c5907b3a283195a3314988da347c626ecfe9b807a1cacb507484710d10678ba5a606838688ed783a91547644aa261499ac72c35d3e4cbe70e28decca4551f37b8156668fa869248a0575e78529524e137b440d1849adca835227a99e683892071adcd38a442cc1ea57b43a426470b9bfbf8659a6a999f6972f70b02e5de338038323735081def034373c0a2145b13ffbb46205382e172473c34801f0639cd07596d85c854969eff572f4416d5f721c78b58bbe64393eb302cddc34abdbb6379ac7d125a32441304894a40a16ad9fd4a80d604ff03a26b5772b439505b3a3ae07f8279564551a73c7520b44e8da14766c7940ec12e143824efc1f1abb86904890a5234a72d96045eb620b115ffe67b3a762bf3b514d7ebcafed572a4d398d5eca446cc645d3f281b569545b876dd5e952f610583dc1a474da6e2c76ba7fc24ae7a70c8c262f8f1807296c49d2d6c6877bc279e2c0d285797c44b5b7001d81db2cd52c20cb97ccdfb0101da837feda0148f3be16f35271655c624460a2d7491d4757f6161b7c7513c92986f6847cacd7832c6113ba741b23a0c923eb1aac3377a6e64d4fa97b063806d286a9185bae60526f8666921778872bb2bd06434a66c2a83d1a3570f75b25c869d304a89494884311c62bc11123e78d028660ecf06bafd56b78391ec8f54525ba9794d23d0c909b47285b5960a393f9751e4b0ecb002dfbfaa3334c936dcb99d92c090ea680ad81984f003f4110a920528f39102a348237b47513433794e813112ba466ab770780d9074b90420200284b48c12f3741e8568aa2516021d9bcd8c8a572e1822efa37049b62f6192b76171af615150da302b0d38b12326226636499b9cee0fb51b9d25ac882ae12945877022f825064700209bd71693732ac4216cb1301584cb948040c683088131dabb6a6094a68b4a45d691474a5394745af376331c361c4d319bab48359d6a393940468d9a0351f3cca963042a8b746620a61d35a73c3b117ea4476313a4e48a53815c45ff331c5d7f54cc17b59cd0a901c1a85c5c2a88503af2fcca62cea50ca671a2de25be94b4319f2ad48698ff1556b30dae138a5b6ffa8eb7b59d9d6b52cbbedf2dcf40d2475)
Server => Client: xpkS (9f56bd72e36ddbbd2e4534e2d04da595ee68d7b8bfc39a130dc28ed683bf9f45) || encS (ee080605def092acf2401b7edead7f693d896c49717a26b26861f312d514a8d4b373b59167c86abb993b521444c059918ada88df9e9b3bea83786edce0cfdaf2f64e5c3205d86d90c022a71c2f5f88913106d8aa017cb4318952573cbb8d4fce4a1ef495b376f528f69bc4d181e643d69c1311bcabcd9635ee45da0b92b1aa5e1c47b5eec814a6b50f7e1e7d6f00394014bbdaf411809599cf03e55acc05bace24b5c3c67e4e7e9d876a2df85f4f1dbbca6dfd15357508312daa75a11b7197eeffc9910d03acf734c3bf84506a922e655560493ab601d1cf69550a6d1a8480bc52ce0c84314bf09854dcaa92c95f66fdbc8e1aff5c7c8faa1c4c4e8687fa4c6014a655edcd85430012d439cba9cd3d5c0878c1e928db8b1abb5ce97c0d4096c414dd24c7bc47bd40a8bd3867a5624075f80c97125b2d8a0b0b98671ee0d9de59da63b6025be8d759d2bb61e2af082966e84110d512e18407e95b028337f7d0258a01281a1b8bb6db4a385c8c1a760395f155fae9b3d256782e7fc3074cc0571d7cd17d9c7e21e0041886ede3bdfaa53479d5745201c2d6fb653c00bdaf0a01e48531cb266651c0ddc9a03f737a35900fe0135226a3ee3cf3d714a9159822e8f07909cdd5183f8541fead3cd66ceb55d1a7b158ddbff8daaeac054bf27d4c517876dd4c270ac606a2dc4ed0f6b0129cde377f3f77e97f6ffe454ecf37759b7e165f7d700eb0be98db65530fdbf93bfad51f663351e2f85c0c6dc132ba5c11ed0418e1c8f2e33b5e5434a33c1deb980fe38964ae0a92b6c24775df1d1341672a90bd320199db809f3b3a04a50be8246e8432d7b8be230502b0de389881e101d7e30e3398e1b83282e7b744621198b644e511695f9f09f4ed0770457f4cdeae567d59457207072c8a2699f4435e6b913ef1bcf8f726b7e5fbd1a633a42ddb2a4782f11e916ef6f156a569c9799779df796157734767e5c19c357758fd81bec41b589ed2cc4100e542028da294a308ac7b4581a3367e5f547d4ba96e8fd23479f8648329c6f4902c585b3b40e6244cb295cd083844dcf46e82e963f71c4df19ecea002b4759ee028c525b7d1549ac302030b889b25b8ceb5c87829f00942d558cf7d8d95d346a65cef817c35e1f260ab4f79e0772d2dd899218d34f845415f61b1b51a1b7fd57ada43563cf2caf216eafa4246851f9b600de903936c05a7b7e7c6fa89fb7a683cd8c38322a4f79ab4a7157099b2c67b330798b728950d8077a02b4ec44088f6bd4625c24144dee2956fc84910858684a58c0c9def294160268bc8900fd4ea6ce5975dbd8e7b7c97313f2d07d4bbdf798c876fd23f13dcdd17dc4c4d80efe81f7052d7295e2dde25d4c411a2fbdb0e88f8efa01b257ac7978bacd19feb8b3f53a5891978b75ff3018e636b6efb0e873aa2bd444b85f736755f7c3b686e08cbd5ce9df0599bbb30fdd6fce5c007e4c2f0ef73c99774a213a8fd2a9f3eb68cf3c3a1710269b21bfc77f3ad3ba0eefc719fd09b57556fba8210823043dc)
SharedSecret (S) d9d0c51b012d4677ebbc58e9b14ee4357cbde8c97d2c354c50a7cc973fd9206b
SharedSecret (C) d9d0c51b012d4677ebbc58e9b14ee4357cbde8c97d2c354c50a7cc973fd9206b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment