{"id":21354937,"url":"https://github.com/salrashid123/mcbn","last_synced_at":"2025-08-22T09:48:02.779Z","repository":{"id":91310065,"uuid":"596345073","full_name":"salrashid123/mcbn","owner":"salrashid123","description":"Multiparty Consent Based Networks (MCBN)","archived":false,"fork":false,"pushed_at":"2024-04-29T11:08:56.000Z","size":1979,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-22T17:46:59.763Z","etag":null,"topics":["cryptography","pki","tls","trusted-computing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salrashid123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-02T01:16:52.000Z","updated_at":"2024-04-29T11:08:59.000Z","dependencies_parsed_at":"2024-04-29T12:28:48.417Z","dependency_job_id":"ef267bef-76d5-404a-b412-de86a42a8e28","html_url":"https://github.com/salrashid123/mcbn","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fmcbn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fmcbn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fmcbn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fmcbn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/mcbn/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243828577,"owners_count":20354524,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","pki","tls","trusted-computing"],"created_at":"2024-11-22T04:15:21.813Z","updated_at":"2025-08-22T09:48:02.745Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Multiparty Consent Based Networks (MCBN)\n\nMultiparty consent based networking (`mcbn`)is a mechanism with which a threshold of participants are required to establish distributed `client-\u003eserver` connectivity using properties of `TLS` itself.  In another variation,the client and server can derive an application-level credential which is unique to the TLS session itself.\n\nIts easier to describe in prose:\n\nSuppose there are \n\n* three participants `Alice, Bob, Carol`\n* two application components:  `client` and `server`\n* the `client` can only connect to the `server` if all three participants agree to do so (or with a threshold of participants)\n* `Frank` operates a compute infrastructure where the `client` and `server` run.\n* each participant needs to provide their share of an encryption key which when combined will allow `client-\u003eserver` connectivity\n* `Frank` cannot have  the ability to see any other participants partial keys or final derived key (neither can the participants see the others)\n* network traffic must be TLS encrypted (of course)\n\n\u003e\u003e\u003e **note**  all this is really experimental and just stuff i thought of; use caution\n\nThis repo concept is defensively published as [Establishing a Secure Sharing Environment Using Partial\nCryptographic K aphic Keys ](https://www.tdcommons.org/cgi/viewcontent.cgi?article=8992\u0026context=dpubs_series)\n\nWhile there _maybe_ ways to achieve this programmatically using bearer tokens or `x509` certificates but they generally involve a trusted third party to broker secret.  \n\nIn this procedure outlined below, no trusted third party is required (well, you're trusting a provider of a TEE infrastructure (Google Cloud, Azure, AWS) that it is doing what its advertized to do as a TEE). \n\nEach participant will release their share of the secret to both the client and server only after ensuring the specific VM that is requesting the share is running in a  Trusted Execution Environment like [Google Confidential Space](https://cloud.google.com/blog/products/identity-security/announcing-confidential-space) and the codebase which is running is going to just use the combined keyshares to establish a TLS connection to the client and server.\n\nBasically, the network connection itself is predicated on having access to all the keys for each participant in an environment where the codebase is trusted and `Frank` cannot access any data running on the VM.\n\nAll of this is achieved using fairly uncommon mechanisms built into `TLS` or seeding how private keys are generated:\n\n- **TCP/UDP**: [Pre-shared Key TLS (PSK)](#pre-shared-key-tls-psk)\n\n    A common `PSK` will be constructed within `Confidential Space` VM  using all participants keys (or with modification using `t-of-n` [Threshold Cryptography](https://gist.github.com/salrashid123/a871efff662a047257879ce7bffb9f13)).   The partial keys will be released to the VM only after _it proves_ to each participant it is running trusted code and the operator (`Frank`), cannot access the system.\n\n    The combined keys will create the same PSK on both the client and server and and then facilitate network connectivity. \n\n    TCP - `TLS-PSK`:\n    * [Pre-Shared Key Ciphersuites for Transport Layer Security (TLS)](https://www.rfc-editor.org/rfc/rfc4279)\n\n    UDP - `DTLS with PSK`:\n    * [Datagram Transport Layer Security Version 1.2](https://www.rfc-editor.org/rfc/rfc6347)\n\n\n- **RSA**: [Deterministic RSA Key](#deterministic-rsa-key)\n\n    The same RSA private key on both ends by \"seeding\" the shared key into the RSA key generator.  This allows each side to use that common RSA key to create a CSR and then have a local CA issue a TLS x509 certificate.\n    Each end trusts the remote TLS cert and issuer but critical bit that is used to grant access is the _comparing the remote peers TLS certificates public key against the local key_.   \n    Since each end uses the same RSA key, this comparison can ensure both ends recieved the same set of partial keys.\n\n    TCP - `Shared RSA key derivation using constructed seeds`:\n\n---\n\nFor  more information on confidential space, see\n\n* [Constructing Trusted Execution Environment (TEE) with GCP Confidential Space](https://github.com/salrashid123/confidential_space)\n\nThough we are referencing GCP `Confidential Space`, this technique can be used extended to connect multiple cloud providers.  For example, the threshold of keys can be decoded in a client running in [AWS Nitro Enclave](https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html) or [Azure SGX](https://learn.microsoft.com/en-us/azure/confidential-computing/confidential-computing-enclaves) while the server runs on GCP.\n\n![image/mcbn.png](images/mcbn.png)\n\n\n---\n\n#### Per-session Application layer credential\n\nIn another variation, instead of the TLS session using a derived/combined key, Both the client and server can derive an application layer credential (bearer token).  This is not covered in this sample but it is alluded to here where instead of the TPM and key oracle as the source, the derive/combined key is used instead\n\n* [TPM One Time Password using TLS SessionKey](https://github.com/salrashid123/tls_tpm_one_time_password)\n\n---\n\n\u003e\u003e\u003e **NOTE** this repo and sample is **not** supported by google. caveat emptor\n\n---\n\n## Combining Partial Keys\n\nIn all the examples below, we're going to \"derive\" the new key using a `sha256(alice+bob+carl)` which can certainly be more secure.\n\n```javascript\nconst alice = '2c6f63f8c0f53a565db041b91c0a95add8913fc102670589db3982228dbfed90';\nconst bob = 'b15244faf36e5e4b178d3891701d245f2e45e881d913b6c35c0ea0ac14224cc2';               \nconst carol = '3e2078d5cd04beabfa4a7a1486bc626d679184df2e0a2b9942d913d4b835516c';\nconst key = crypto.createHash('sha256').update(alice+bob+carol).digest('hex');\n\n//console.log(key);\n// which is \nkey = '6d1bbd1e6235c9d9ec8cdbdf9b32d4d08304a7f305f7c6c67775130d914f4dc4';\n\n// alternatively, \n// successively chain keys with HMAC_SHA256(data,passphrase)\n// key = HMAC_SHA256(HMAC_SHA256(alice,bob),carol)\n\n// const k1 = crypto.createHmac('sha256', bob).update(alice).digest(\"hex\");\n// const key = crypto.createHmac('sha256', carol).update(k1).digest(\"hex\");\n// console.log(key);  // gives 2b6c5604e7b5a3a9832ec2590fd058d610807cee2f3e87bb08dafbb57475d976\n```\n\nUsing `HMAC` or sha256 in these formats requires the known ordering of keys (though you could just `sha256(alice xor bob xor carl) == sha256(bob xor alice xor carl)` etc....and probably the assumption participants are not sending in degenerate keys like `000000...`.\n\nOther realistic possibilities to derive can be some sort of KDF function or using `Threshold Cryptography` with  the final recovered [private key](https://gist.github.com/salrashid123/a871efff662a047257879ce7bffb9f13#file-main-go-L158).  (I haven't though much about the best way of how to derive a new key)\n\nFor alternatives see comments on [Proper way to combine multiple secrets into one HMAC key](https://security.stackexchange.com/questions/183344/proper-way-to-combine-multiple-secrets-into-one-hmac-key), [HKDF](https://security.stackexchange.com/questions/263842/key-derivation-for-hmac-concatenate-vs-multiple-hmac-passes) and [Combining Keys](https://crypto.stackexchange.com/questions/18572/combining-two-keys)\n\nAnyway, we'll just go with the simple scheme above.\n\n---\n\n## Pre-shared Key TLS (PSK)\n\nThis easiest example for PSK uses `nodeJS` but several other examples can be found in the [/psk](/psk) folder: \n\n* `python`: This repo also shows a very basic PSK client/server in python.  PSK support is only present as of python 3.13 ([#63284](https://github.com/python/cpython/issues/63284))\n* `java`: Simple socket echo server using TLS1.2 and PSK. [TlsPSKKeyExchange](https://www.bouncycastle.org/docs/tlsdocs1.8on/org/bouncycastle/tls/TlsPSKKeyExchange.html)\n* `c`: Simple echo server using `SSL_set_psk_server_callback()`\n\n* `go`: (not implemented): [crypto/tls: add PSK support ](https://github.com/golang/go/issues/6379)\n* `envoyproxy`: (not implemented) [envoy issue#13237](https://github.com/envoyproxy/envoy/issues/13237)\n\nAnyway, the following hardcodes the derived key and simply sets up a client/server to demo PSK.\n\n### PSK Server\n\nTo test locally, you can directly run the client and server.\n\n\n```bash\ncd server\n\n## using node cli\nnpm i\nnode main.js\n\n## run using bazel\n#### run static\n# bazel run :main\n\n#### run image\n# bazel run :server_image\n# docker run -p 8081:8081 us-central1-docker.pkg.dev/builder-project/repo1/node_server\n```\n\nTo generate the image with cloud build will result in the predictable hash of:\n\n* `node_server@sha256:b0749faba840a02329463ddd8c86e04f797a18ea6689e5fe34edb72cc2391976`\n\nThis would be the image hash that is bound to `Confidential Space` server VM\n\n```bash\ncd psk/nodejs/server/\n\ngcloud builds submit .\n\nexport PROJECT_ID=$(gcloud config list --format=\"value(core.project)\")\ndocker pull  us-central1-docker.pkg.dev/$PROJECT_ID/repo1/node_server\ndocker inspect  us-central1-docker.pkg.dev/$PROJECT_ID/repo1/node_server\n```\n\n### PSK Client\n\nTo run the client,\n\n```bash\ncd client\n\n## run using node cli\nnpm i\nnode main.js\n\n## run using bazel\n### run static\n# bazel run :main\n\n#### run image\n# bazel run :image\n# docker run --net=host us-central1-docker.pkg.dev/builder-project/repo1/node_client\n\n## or just with openssl client\nexport PSK=6d1bbd1e6235c9d9ec8cdbdf9b32d4d08304a7f305f7c6c67775130d914f4dc4\nopenssl s_client -psk $PSK -psk_identity Client1 \\\n   -connect localhost:8081  -tls1_3\n```\n\nTo generate the image with cloud build which will result in the predictable hash of:\n\n* `node_client@sha256:e0ac77103ab1e37369599cdf496b3c30eeb9acf5260305e9807d639f0f6a516e`\n\nThis would be the image hash that is bound to `Confidential Space` server VM\n\n```bash\ncd psk/nodejs/client/\ngcloud builds submit .\n\nexport PROJECT_ID=$(gcloud config list --format=\"value(core.project)\")\ndocker pull  us-central1-docker.pkg.dev/$PROJECT_ID/repo1/node_client\ndocker inspect  us-central1-docker.pkg.dev/$PROJECT_ID/repo1/node_client\n```\n\n### Openssl TLS1_3\n\nOpenssl also support PSK based TLS. \n\nTLS1.3 reworked the cipher/ciphersuites to the following and which is open to all key exchange mechanism (including PSK even if not declared in the iana name)\n\n```bash\n$ openssl ciphers -v -s -tls1_3 -psk\n   TLS_AES_256_GCM_SHA384  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(256) Mac=AEAD\n   TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD\n   TLS_AES_128_GCM_SHA256  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(128) Mac=AEAD\n```\n\nAs a demo, you can generate a new key or use the existing one\n\n```bash\n# to generate a new key\n# openssl rand -hex 32\n\n# or use the existing one:\nexport PSK=6d1bbd1e6235c9d9ec8cdbdf9b32d4d08304a7f305f7c6c67775130d914f4dc4\nexport PSK_HEX=`echo  -n $PSK |   xxd -p -c 64`\n\n# start server\nopenssl s_server  -psk $PSK_HEX -nocert -accept 8081  -tls1_3 -www\n\n# in a new window with the same PSK, run client\nopenssl s_client -psk $PSK_HEX -tls1_3 -connect localhost:8081\n\n## once connected via client, make an HTTP request\n# GET / HTTP/1.0\n# \u003creturn\u003e\n# \u003creturn\u003e\n\n## or with full verbosity debug HTTP \ndocker run --name server --net=host -p 8081 -v `pwd`/:/apps/ \\\n    -ti docker.io/salrashid123/openssl s_server -psk $PSK_HEX \\\n    -nocert -accept 8081  -tls1_3  \\\n         -tlsextdebug         -trace -www\n\n## run client\ndocker run  --name client   --net=host  \\\n   -ti docker.io/salrashid123/openssl s_client -psk $PSK_HEX \\\n   -connect localhost:8081  -tls1_3  \\\n        -tlsextdebug         -trace\n\n# to stop docker containers,\ndocker rm -f client server\n```\n\n\n\n\n### Wireshark\n\nThe following decodes the PSK traffic using wireshark and openssl:\n\n```bash\nexport PSK=6d1bbd1e6235c9d9ec8cdbdf9b32d4d08304a7f305f7c6c67775130d914f4dc4\nexport PSK_HEX=`echo  -n $PSK |   xxd -p -c 64`\n\n# start server\nopenssl s_server  -psk $PSK_HEX  -nocert -accept 8081  -tls1_3  -www\n\n# in a new window start the trace\nsudo tcpdump -s0 -ilo -w psk.cap port 8081\n\n# in a new window with the PSK env set, run the client \nopenssl s_client -psk $PSK_HEX  -connect localhost:8081 \\\n   -tls1_3  -keylogfile=keylog.log\n\n# shutdown the tcpdump trace and view the decoded data:\nwireshark psk.cap -otls.keylog_file:`pwd`/psk_keylog.log\n\n\n# for tls1.2, a sample trace is provided\nwireshark psk_tls12.cap  -otls.keylog_file:`pwd`/keylog_tls12.log\n```\n\n![images/cipher_suites.png](images/cipher_suites.png)\n\n![images/psk_identity.png](images/psk_identity.png)\n\nThe traces above used `TLS13`, for `TLS12` traces:\n\n![images/cipher_suites_tls12.png](images/cipher_suites_tls12.png)\n\n## stunnel\n\nStunnel also offers support to for PSK:\n\nsee [stunnel PSK](https://www.stunnel.org/auth.html)\n\nas a simple example of a client-server, \n\n`client --\u003e no TLS --\u003e stunnel_client :7070 --\u003e TLS-PSK --\u003e stunnel_server :8081  --\u003e no TLS --\u003e python server: 8080`\n\n```bash\n# start any background server\npython3 -m http.server 8080\n\n# then in different windows, run the client and server stunnels\nstunnel server.conf\n\nstunnel client.conf \n\n# finally run the client\ncurl -v http://localhost:7070/\n```\n\n\n- `server`\n\n```log\nstunnel server.conf  \n\n2024.01.02 09:33:29 LOG5[ui]: stunnel 5.71 on x86_64-pc-linux-gnu platform\n\n2024.01.02 09:33:29 LOG4[ui]: Insecure file permissions on psk.txt\n2024.01.02 09:33:29 LOG5[ui]: Configuration successful\n\n2024.01.02 09:33:29 LOG5[ui]: Binding service [PSK server] to :::8081: Address already in use (98)\n2024.01.02 09:33:32 LOG7[0]: Service [PSK server] started\n2024.01.02 09:33:32 LOG5[0]: Service [PSK server] accepted connection from 127.0.0.1:53004\n2024.01.02 09:33:32 LOG6[0]: Peer certificate not required\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): before SSL initialization\n2024.01.02 09:33:32 LOG5[0]: Key configured for PSK identity \"client1\"\n\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): SSLv3/TLS read client hello\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): SSLv3/TLS write server hello\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): SSLv3/TLS write change cipher spec\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): TLSv1.3 write encrypted extensions\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): SSLv3/TLS write finished\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): TLSv1.3 early data\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): TLSv1.3 early data\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): SSLv3/TLS read finished\n\n2024.01.02 09:33:32 LOG7[0]: Generate session ticket callback\n2024.01.02 09:33:32 LOG7[0]: Initializing application specific data for session authenticated\n2024.01.02 09:33:32 LOG7[0]: Deallocating application specific data for session connect address\n2024.01.02 09:33:32 LOG7[0]: New session callback\n2024.01.02 09:33:32 LOG6[0]: No peer certificate received\n2024.01.02 09:33:32 LOG6[0]: Session id: CC433E3A83193DE52639EC14373B1EC6038D96B4D19F1FE30F3379933E8F33D9\n2024.01.02 09:33:32 LOG7[0]: TLS state (accept): SSLv3/TLS write session ticket\n\n2024.01.02 09:33:32 LOG6[0]: TLSv1.3 ciphersuite: TLS_AES_128_GCM_SHA256 (128-bit encryption)\n2024.01.02 09:33:32 LOG6[0]: Peer temporary key: X25519, 253 bits\n2024.01.02 09:33:32 LOG7[0]: Compression: null, expansion: null\n2024.01.02 09:33:32 LOG6[0]: Session id: CC433E3A83193DE52639EC14373B1EC6038D96B4D19F1FE30F3379933E8F33D9\n\n2024.01.02 09:33:32 LOG5[0]: Service [PSK server] connected remote server from 127.0.0.1:38658\n\n2024.01.02 09:33:32 LOG7[0]: Service [PSK server] finished (0 left)\n```\n\n- `client`\n\n```log\nstunnel client.conf \n\n2024.01.02 09:33:23 LOG5[ui]: stunnel 5.71 on x86_64-pc-linux-gnu platform\n2024.01.02 09:33:23 LOG5[ui]: Compiled with OpenSSL 3.0.10 1 Aug 2023\n2024.01.02 09:33:23 LOG5[ui]: Running  with OpenSSL 3.2.0-beta1 26 Oct 2023\n2024.01.02 09:33:23 LOG5[ui]: Update OpenSSL shared libraries or rebuild stunnel\n2024.01.02 09:33:23 LOG5[ui]: Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,OCSP,PSK,SNI\n\n2024.01.02 09:33:32 LOG7[0]: Service [PSK client 1] started\n2024.01.02 09:33:32 LOG5[0]: Service [PSK client 1] accepted connection from 127.0.0.1:44210\n2024.01.02 09:33:32 LOG6[0]: s_connect: connecting 127.0.0.1:8081\n2024.01.02 09:33:32 LOG7[0]: s_connect: s_poll_wait 127.0.0.1:8081: waiting 10 seconds\n2024.01.02 09:33:32 LOG5[0]: s_connect: connected 127.0.0.1:8081\n2024.01.02 09:33:32 LOG5[0]: Service [PSK client 1] connected remote server from 127.0.0.1:53004\n2024.01.02 09:33:32 LOG6[0]: SNI: sending servername: localhost\n\n2024.01.02 09:33:32 LOG6[0]: Peer certificate not required\n2024.01.02 09:33:32 LOG7[0]: TLS state (connect): before SSL initialization\n\n2024.01.02 09:33:32 LOG6[0]: PSK client configured for identity \"client1\"\n\n2024.01.02 09:33:32 LOG6[0]: TLSv1.3 ciphersuite: TLS_AES_128_GCM_SHA256 (128-bit encryption)\n2024.01.02 09:33:32 LOG6[0]: No peer certificate received\n2024.01.02 09:33:32 LOG6[0]: Session id: 3516C349057726CF3DD75503386706AE95FE08AEBCC4E2DFDB5BA2D0AD0424DC\n\n2024.01.02 09:33:32 LOG7[0]: Service [PSK client 1] finished (0 left)\n```\n\n---\n\n## Datagram TLS (DTLS)\n\n\nFor UDP based traffic, we will use [Datagram Transport Layer Security Version 1.2](https://www.rfc-editor.org/rfc/rfc6347) and the `pion` go library here which supports `PSK`:\n \n* [pion SDK for DTLS](https://github.com/pion/dtls/#using-with-psk)\n\n\n### Openssl\n\nAs a prelimanary demo using openssl PSK while using tcpdump and keylogging,\n\n```bash\nexport PSK=6d1bbd1e6235c9d9ec8cdbdf9b32d4d08304a7f305f7c6c67775130d914f4dc4\nexport PSK_HEX=`echo  -n $PSK |   xxd -p -c 64`\n\nopenssl s_server  -dtls1_2 -psk_identity Client1 \\\n   -psk $PSK_HEX -cipher PSK-AES128-CCM8  -nocert -accept 8081\n\n# sudo tcpdump -s0 -ilo -w psk.cap port 8081\n\nopenssl s_client -dtls1_2 -psk_identity Client1 \\\n      -connect 127.0.0.1:8081 -psk $PSK -cipher PSK-AES128-CCM8 -keylogfile=dtls_keylog.log\n\nwireshark dtls.cap -otls.keylog_file:`pwd`/dtls_keylog.log\n```\n\nThe trace would look like this for dtls\n\n![images/dtls_trace.png](images/dtls_trace.png)\n\n### DTLS Server\n\nNow similar to the TLS-PSK, we can run the client/server locally and then followup with a bazel build so that someday we can deploy to `Confidential Space`\n\n```bash\n# run server locally\ngo run server/server.go\n\n## or with bazel\n## optionally regenerate bazel go dependency\n# bazel run :gazelle -- update-repos -from_file=go.mod -prune=true -to_macro=repositories.bzl%go_repositories\n\n## to run using bazel\n# bazel run --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 server:server \n\n## or generate container image locally\n# bazel run  --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 server:dtls_server_image\n\n## run server image from bazel\n# docker run --net=host -p 8081:8081 us-central1-docker.pkg.dev/builder-project/repo1/dtls_server/server:dtls_server_image\n```\n\nTo generate the image with cloud build which will result in the predictable hash of:\n\n* `dtls_server@sha256:ac99f049143b03a2934753ec73141e0e72e8e42a4f5012f462ebe628fd55ff9d`\n* `dtls_client@sha256:aa4a078fc357ae679d0790a3161d7bcb09a4b3a3d9f2d9e02286edb76de86ab5`\n\n\n```bash\ngcloud builds submit .\n\nexport PROJECT_ID=$(gcloud config list --format=\"value(core.project)\")\n\ndocker pull us-central1-docker.pkg.dev/$PROJECT_ID/repo1/dtls_client\ndocker pull us-central1-docker.pkg.dev/$PROJECT_ID/repo1/dtls_server\ndocker inspect us-central1-docker.pkg.dev/$PROJECT_ID/repo1/dtls_server\ndocker inspect us-central1-docker.pkg.dev/$PROJECT_ID/repo1/dtls_client\n```\n\n### DTLS Client\n\nTo run the client \n\n```bash\n# to run locally\n\ngo run client/client.go\n\n## or with bazel\n## optionally regenerate bazel go dependency\n# bazel run :gazelle -- update-repos -from_file=go.mod -prune=true -to_macro=repositories.bzl%go_repositories\n\n# run client locally\n# bazel run --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 client:client \n\n## to generate container image locally\n# bazel run  --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 client:dtls_client_image\n## to run the client image from bazel\n# docker run --net=host us-central1-docker.pkg.dev/builder-project/repo1/dtls_client/client:dtls_client_image\n```\n\n## Deterministic RSA Key\n\nThis technique basically uses both alice and bob's key together to derive the 'seed' value to use during RSA key generation.\n\nIf the same partial keys are used with a hash or KDF function that results in the same seed value, that seed value can be the \"randomness\" that is fed into [rsa.GenerateKey(random io.Reader, bits int) (*PrivateKey, error)](https://pkg.go.dev/crypto/rsa#GenerateKey).\n\nBasically, you're feeding the function above a _deterministic random key_ (right...)\n\nIts best demonstrated with the following using `certtool`:\n\n```bash\n# start with a pair of secret keys\nexport alice=b06394e28c33be5a8699759023972e9294d51b5007b3b0a51a41e9f58d406f8d\nexport bob=2d362ce19a804d12b85644abf3a0e9bbfbb0e0ba3c5dd7cc4b8e335bc5154496\n\n# generate a new one...i'm using something suspect here like just hashing the combined key...there's certainly better ways like KDF or something\n\nexport S1=`echo -n \"$alice$bob\" | sha256sum | cut -d ' ' -f 1`\necho $S1\n\n# you should see   cb488e9105faa7e26cf30dcc6042fea07fd71c38953973c356d8ecf80421880e\n# now use that key as the 'seed' to generate a keypari and extract the RSA public keys\ncerttool --generate-privkey --outfile priv1.pem --key-type=rsa --sec-param=medium --provable --seed=$S1\nopenssl rsa -in priv1.pem -pubout -out pub1.pem\nopenssl rsa -pubin -in pub1.pem -RSAPublicKey_out\n\n-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAsv9SPzFfsbJ/a2509qwgCJlEW6c66k7nVJssjpZnK/cwXA8L8wJ6\nTwtlNackAuxxUFNGeTzBvCOWGRdKkAB/zPTfbfk+P+VoduRFARH1/LbBaYHCkdYr\n3qHVpdYOoYL7QVaDFMZt3crtzqLqX6coV8CyCl2F+7XIgoZ7feghMsUpgRJ1i/Cb\noVJPnjmKL4nlRtbuQjvHB4eEbOXb4qXPVu/tm8nBzsCMYrfvdzh4Luiqzi6kBcKs\nFh8wgt77loNAY084sVNpqf1pTnJNozR9PP/U0aHsopmSdcbvwsudZBJ7E1wqDX/o\nmefpnh5OhJUFQOihjFxNKO5kdHgOYBsCnwIDAQAB\n-----END RSA PUBLIC KEY-----\n\n\n$ certtool  --verify-provable-privkey --load-privkey priv1.pem --seed=$S1\nKey was verified\n```\n\n\nFor more info, see:\n\n* [Deterministic Random Bit Generator (DRBG)](https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)\n* [Generating a public/private key pair using an initial key](https://stackoverflow.com/questions/18264314/generating-a-public-private-key-pair-using-an-initial-key)\n* [How many random bits are required to create one RSA key](https://crypto.stackexchange.com/questions/53124/how-many-random-bits-are-required-to-create-one-rsa-key)\n* [How to derive a private/public keypair from a random seed](https://crypto.stackexchange.com/questions/81487/how-to-derive-a-private-public-keypair-from-a-random-seed)\n* [Making OpenSSL generate deterministic key](https://stackoverflow.com/questions/22759465/making-openssl-generate-deterministic-key)\n* [Using Go deterministically generate RSA Private Key with custom io.Reader](https://stackoverflow.com/questions/74869997/using-go-deterministicly-generate-rsa-private-key-with-custom-io-reader)\n* [How can one securely generate an asymmetric key pair from a short passphrase?](https://crypto.stackexchange.com/questions/1662/how-can-one-securely-generate-an-asymmetric-key-pair-from-a-short-passphrase/1665#1665)\n* [Golang: A tool to generate a deterministic RSA keypair from a passphrase.](https://github.com/joekir/deterministics)\n* [Python: deterministic-rsa-keygen 0.0.1](https://pypi.org/project/deterministic-rsa-keygen/)\n* [Stackexchange: Proper way to combine multiple secrets into one HMAC key](https://security.stackexchange.com/questions/183344/proper-way-to-combine-multiple-secrets-into-one-hmac-key)\n\n\nThis repo contains a small demo about this feature that i extended for mTLS:\n\n1. client and server recieve alice and bob's secret keys\n2. client and server derive the same RSA key using a hash of partial keys\n3. client and server uses the RSA key to create a CSR\n4. client and server uses *any* CA to issue an x509 certificate for the CSR\n5. server starts mTLS http server  where it accepts certificates issued by the remote peers CA.\n6. client contacts the server using its local client certificate and accepts the server's cert issued by its peers CA\n7. During connection establishment, both the client and server checks if the remote peer's leaf **RSA public key** is the same the local copy.\n\nYou'll notice the code contains a local CA keypair that is built into the sample...the CA only plays a bit part in this picture..\n\nthe 'thing' that allows connection isn't the CA or the certificate it signed (that bit is just for ease of use for mTLS)...the critical bit occurs when each end compares the RSA peer certificates are the same or not.\n\nnote, you could also conceive of a common public CA signer service which only accepts CSRs where the public rsa key is of the expected value (i.,e will only issue client or server certs to CSRs originating from a TEE)\n\nThis repo uses [Deterministic Random Bit Generator (DRBG)](https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final) implemented through [github.com/canonical/go-sp800.90a-drbg](https://pkg.go.dev/github.com/canonical/go-sp800.90a-drbg#NewHash) to generate the deterministic rsa key.\n\nFor example:\n\n```golang\nimport (\n    drbg \"github.com/canonical/go-sp800.90a-drbg\"\n)\n\n    combinedKey := \"y0iOkQX6p-Js8w3MYEL-oH_XHDiVOXPDVtjs-AQhiA4\"\n    r, err := drbg.NewHashWithExternalEntropy(crypto.SHA256, []byte(combinedKey), nil, nil, nil)\n    privkey, err := rsa.GenerateKey(r, bitSize)\n```\n\n(note you can also use [crypto.ed25519.NewKeyFromSeed()](https://pkg.go.dev/crypto/ed25519@go1.20.5#NewKeyFromSeed))\n\nThe following shows a simple client-server where each participants keys are set\n\nThe first step shows the derived key, then the RSA key and the RSA key's hash value.  This should be the same on both ends.\n\nOnce the client makes mTLS contact, it will accept the mTLS connection if it they peer was signed by a common \n\n```bash\n## server\n$ go run server/server.go  \\\n  --alice=b06394e28c33be5a8699759023972e9294d51b5007b3b0a51a41e9f58d406f8d \\\n  --bob=2d362ce19a804d12b85644abf3a0e9bbfbb0e0ba3c5dd7cc4b8e335bc5154496\n\nderived combined key y0iOkQX6p-Js8w3MYEL-oH_XHDiVOXPDVtjs-AQhiA4\n-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAynV1FFgMBUCoYlttNejPqb1zPAY1cQjkdOsghr7az+NHYxFmrCsc\n0mkuXhRqf0QqeVJUNjbFdEVb9+lL3xuT59XucIZ5tpBlmIlcmRnX/7UeJToE9ZGX\nZVl2U3nEroUPcsAA5PH2vs/bPN19U0ekMq1mqCtb0P0/Jhtbk01HfmKmUovTh0oo\nrRolK37dgGgqUo/FVs0Mw4kKYNd0Z3SqKVMigj7EmwN9Ng5GO01VBjsBrA1w146Z\nVWca3/yGfOHsdY6oRgy5q/qxUfK2FKddCNLojR2xOllj4Y3K7Hli9cjBoEQvHy/K\nbpFcvTcF8Qr3TVTkOJYbmW2rauvUSGqg3wIDAQAB\n-----END RSA PUBLIC KEY-----\n\nderived common certificate hash w55b4-JhIH7vLIoKJtilo8zS_QQkiXpLkkdILxqfLCA\nCreating CSR\nCreating Cert\nIssued x509 with serial number 304644566552857710712497793020376072793\nStarting Server..\nderived and remote certificate hash match w55b4-JhIH7vLIoKJtilo8zS_QQkiXpLkkdILxqfLCA\n\n\n## client\n$ go run client/client.go \\\n  --alice=b06394e28c33be5a8699759023972e9294d51b5007b3b0a51a41e9f58d406f8d \\\n  --bob=2d362ce19a804d12b85644abf3a0e9bbfbb0e0ba3c5dd7cc4b8e335bc5154496\n\nderived combined key y0iOkQX6p-Js8w3MYEL-oH_XHDiVOXPDVtjs-AQhiA4\n-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAynV1FFgMBUCoYlttNejPqb1zPAY1cQjkdOsghr7az+NHYxFmrCsc\n0mkuXhRqf0QqeVJUNjbFdEVb9+lL3xuT59XucIZ5tpBlmIlcmRnX/7UeJToE9ZGX\nZVl2U3nEroUPcsAA5PH2vs/bPN19U0ekMq1mqCtb0P0/Jhtbk01HfmKmUovTh0oo\nrRolK37dgGgqUo/FVs0Mw4kKYNd0Z3SqKVMigj7EmwN9Ng5GO01VBjsBrA1w146Z\nVWca3/yGfOHsdY6oRgy5q/qxUfK2FKddCNLojR2xOllj4Y3K7Hli9cjBoEQvHy/K\nbpFcvTcF8Qr3TVTkOJYbmW2rauvUSGqg3wIDAQAB\n-----END RSA PUBLIC KEY-----\n\nderived certificate hash w55b4-JhIH7vLIoKJtilo8zS_QQkiXpLkkdILxqfLCA\nCreating CSR\nCreating Cert\nIssued x509 with serial number 241981356749299476354734320392982310510\nlocal and remote certificate hash match w55b4-JhIH7vLIoKJtilo8zS_QQkiXpLkkdILxqfLCA\nConnected to IP: 127.0.0.1\n200 OK\nok\n```\n\n\nThe the client and server certificates itself will have a unique serial numbers and issue times since the certifiates are generated at each run but the RSA key underlying it will be the same\n\nThe server i used in the example above had:\n\n```bash\n$ openssl x509 -in s.crt  -noout -text\n\nCertificate:\n    Data:\n        Version: 3 (0x2)\n        Serial Number:\n            cf:3a:7c:6a:63:3d:61:f9:7d:ae:da:20:f2:c7:56:c4\n        Signature Algorithm: rsassaPss        \n        Hash Algorithm: sha256\n        Mask Algorithm: mgf1 with sha256\n         Salt Length: 0x20\n        Trailer Field: 0x01 (default)\n        Issuer: C = US, O = Operator, OU = Enterprise, CN = Enterprise Root CA\n        Validity\n            Not Before: Jun  3 13:28:40 2023 GMT\n            Not After : Jun  2 13:28:40 2024 GMT\n        Subject: C = US, ST = California, L = Mountain View, O = Acme Co, OU = Enterprise, CN = server.domain.com\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                Public-Key: (2048 bit)\n                Modulus:\n                    00:ca:75:75:14:58:0c:05:40:a8:62:5b:6d:35:e8:\n                    cf:a9:bd:73:3c:06:35:71:08:e4:74:eb:20:86:be:\n                    da:cf:e3:47:63:11:66:ac:2b:1c:d2:69:2e:5e:14:\n                    6a:7f:44:2a:79:52:54:36:36:c5:74:45:5b:f7:e9:\n                    4b:df:1b:93:e7:d5:ee:70:86:79:b6:90:65:98:89:\n                    5c:99:19:d7:ff:b5:1e:25:3a:04:f5:91:97:65:59:\n                    76:53:79:c4:ae:85:0f:72:c0:00:e4:f1:f6:be:cf:\n                    db:3c:dd:7d:53:47:a4:32:ad:66:a8:2b:5b:d0:fd:\n                    3f:26:1b:5b:93:4d:47:7e:62:a6:52:8b:d3:87:4a:\n                    28:ad:1a:25:2b:7e:dd:80:68:2a:52:8f:c5:56:cd:\n                    0c:c3:89:0a:60:d7:74:67:74:aa:29:53:22:82:3e:\n                    c4:9b:03:7d:36:0e:46:3b:4d:55:06:3b:01:ac:0d:\n                    70:d7:8e:99:55:67:1a:df:fc:86:7c:e1:ec:75:8e:\n                    a8:46:0c:b9:ab:fa:b1:51:f2:b6:14:a7:5d:08:d2:\n                    e8:8d:1d:b1:3a:59:63:e1:8d:ca:ec:79:62:f5:c8:\n                    c1:a0:44:2f:1f:2f:ca:6e:91:5c:bd:37:05:f1:0a:\n                    f7:4d:54:e4:38:96:1b:99:6d:ab:6a:eb:d4:48:6a:\n                    a0:df\n                Exponent: 65537 (0x10001)\n        X509v3 extensions:\n            X509v3 Key Usage: critical\n                Digital Signature\n            X509v3 Extended Key Usage: \n                TLS Web Server Authentication\n            X509v3 Basic Constraints: critical\n                CA:FALSE\n            X509v3 Subject Key Identifier: \n                13:63:7C:82:5F:03:9B:80:1E:8E:BB:10:00:55:14:D5:6F:C8:6F:94\n            X509v3 Authority Key Identifier: \n                58:88:29:FD:AA:3A:F0:9F:51:CA:FD:F1:6B:FC:D7:F0:8E:67:CF:80\n            X509v3 Subject Alternative Name: \n                DNS:server.domain.com\n    Signature Algorithm: rsassaPss\n    Signature Value:        \n        Hash Algorithm: sha256\n        Mask Algorithm: mgf1 with sha256\n         Salt Length: 0x20\n        Trailer Field: 0x01 (default)\n        2d:bc:fa:e0:8d:2d:fa:74:21:d2:b1:13:02:f1:fb:4f:fc:5c:\n        9a:fe:89:8c:46:04:6b:52:71:e8:ed:f9:eb:0a:77:39:8d:e4:\n        d7:6c:3f:fe:ff:fa:f0:82:7e:93:c2:c7:e5:0c:93:98:37:79:\n        cc:92:fa:b9:6e:0e:19:74:8f:ef:39:8e:3a:e9:e6:ed:12:3e:\n        a5:d6:6b:cd:a1:ae:24:ef:56:33:bd:e1:12:4d:2a:b2:77:15:\n        39:f1:c6:58:95:72:bd:b7:a4:e8:81:22:88:af:99:9a:66:bf:\n        78:bd:10:05:97:08:f1:aa:a3:a0:47:68:43:54:ce:70:6f:16:\n        43:09:48:e9:88:2d:6a:7c:d3:72:e5:ea:36:da:50:95:ae:4d:\n        8b:ce:a8:ad:ed:b4:02:8f:cc:ce:54:e0:6a:00:d0:9b:90:39:\n        b5:3d:df:5b:11:ad:69:5f:f1:d6:e1:b4:5d:fb:46:20:49:7b:\n        76:26:4f:47:4f:cb:55:06:1f:75:a0:40:a5:38:10:5c:74:ef:\n        73:6d:22:bc:58:f7:53:ed:f9:87:9e:97:cc:77:84:74:a9:2e:\n        08:7c:d0:4a:a1:2d:a4:bb:29:44:15:e3:36:bf:36:88:97:92:\n        0e:6f:32:a4:8b:48:ff:d4:30:58:b5:d7:67:1e:82:b3:53:55:\n        2f:53:e8:62\n```\n\nsample for keytool,JKS\n\n```bash\nexport alice=b06394e28c33be5a8699759023972e9294d51b5007b3b0a51a41e9f58d406f8d\nexport bob=2d362ce19a804d12b85644abf3a0e9bbfbb0e0ba3c5dd7cc4b8e335bc5154496\nexport S1=`echo -n \"$alice$bob\" | sha256sum | cut -d ' ' -f 1`\necho $S1\n\ncerttool --generate-privkey --outfile priv1.pem --key-type=rsa --sec-param=medium --provable --seed=$S1\nopenssl rsa -in priv1.pem -pubout -out pub1.pem\nopenssl rsa -pubin -in pub1.pem -RSAPublicKey_out\ncerttool  --verify-provable-privkey --load-privkey priv1.pem --seed=$S1\n\nopenssl req -x509 -key priv1.pem -out cert.pem -sha256 -days 3650 -nodes -subj \"/C=US/ST=CA/L=SF/O=Google/OU=Cloud/CN=Spark\"\nopenssl x509 -in cert.pem -text\n\nopenssl pkcs12 -export -out server.p12 -inkey priv1.pem -in cert.pem -password pass:examplestorepass\n\nkeytool -importkeystore -destkeystore spark-keystore.jks -srcstoretype PKCS12 -srckeystore server.p12  -storepass examplestorepass -srcstorepass examplestorepass\nkeytool -importcert -keystore spark-truststore.jks  -storepass examplestorepass -file cert.pem -noprompt\n\nkeytool -list -v -keystore spark-keystore.jks   -storepass examplestorepass\nkeytool -list -v -keystore spark-truststore.jks   -storepass examplestorepass\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fmcbn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Fmcbn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fmcbn/lists"}