{"id":23009652,"url":"https://github.com/jiep/spake2plus","last_synced_at":"2025-08-14T04:32:47.200Z","repository":{"id":267963364,"uuid":"887989009","full_name":"jiep/spake2plus","owner":"jiep","description":"Python 3 implementation of SPAKE2+ protocol, according to RFC 9383","archived":false,"fork":false,"pushed_at":"2024-12-13T14:00:24.000Z","size":1003,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-13T15:36:16.847Z","etag":null,"topics":["cryptography","pake","rfc9383","spake2plus"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jiep.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":"2024-11-13T16:14:12.000Z","updated_at":"2024-12-13T14:00:26.000Z","dependencies_parsed_at":"2024-12-13T15:36:33.650Z","dependency_job_id":"19bf480d-a01f-40bf-a5aa-d131195e8da3","html_url":"https://github.com/jiep/spake2plus","commit_stats":null,"previous_names":["jiep/spake2plus"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiep%2Fspake2plus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiep%2Fspake2plus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiep%2Fspake2plus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiep%2Fspake2plus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jiep","download_url":"https://codeload.github.com/jiep/spake2plus/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229800393,"owners_count":18126028,"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","pake","rfc9383","spake2plus"],"created_at":"2024-12-15T09:15:13.937Z","updated_at":"2025-08-14T04:32:47.180Z","avatar_url":"https://github.com/jiep.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SPAKE2+\n\n[![Python Tests](https://github.com/jiep/spake2plus/actions/workflows/test.yml/badge.svg)](https://github.com/jiep/spake2plus/actions/workflows/test.yml)\n[![Lint](https://github.com/jiep/spake2plus/actions/workflows/lint.yml/badge.svg)](https://github.com/jiep/spake2plus/actions/workflows/lint.yml)\n[![Build Wheel](https://github.com/jiep/spake2plus/actions/workflows/wheel.yml/badge.svg)](https://github.com/jiep/spake2plus/actions/workflows/wheel.yml)\n[![Dependabot Updates](https://github.com/jiep/spake2plus/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/jiep/spake2plus/actions/workflows/dependabot/dependabot-updates)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/images/logo.png\" width=\"25%\"/\u003e\n\u003c/p\u003e\n\n**SPAKE2+** is a Python 3 implementation of SPAKE2+ protocol, according to [RFC 9383\nSPAKE2+, an Augmented Password-Authenticated Key Exchange (PAKE) Protocol](https://www.rfc-editor.org/rfc/rfc9383.html).\n\n\u003e [!CAUTION]\nThis code has not been audited or formally reviewed for security. Use it at your own risk and only for educational purposes or in non-critical environments.\n\n## What is SPAKE2+?\n\nSPAKE2+ is a cryptographic protocol designed to establish a shared secret between two parties (Prover and Verifier) over an insecure channel. It is an augmentation of the SPAKE2 protocol, adding explicit identities to prevent key compromise impersonation (KCI) attacks. \n\nThe protocol is efficient, secure, and suitable for password-based authenticated key exchange (PAKE). Unlike traditional methods that transmit hashed passwords or challenge-responses, SPAKE2+ ensures the shared secret is derived without exposing the password, even in the presence of eavesdroppers or active attackers.\n\n### Key Features:\n1. **Password-Based Authentication**: Ensures both parties authenticate using a shared password, protecting against unauthorized access.\n2. **Implicit Mutual Authentication**: If the protocol succeeds, both parties confirm they share the same password.\n3. **Resistance to KCI Attacks**: Explicit identities (`idProver` and `idVerifier`) are incorporated into the protocol to prevent impersonation by a compromised party.\n4. **Elliptic Curve Cryptography (ECC)**: Leverages ECC for computational efficiency and security.\n5. **No Password Exposure**: The password itself is never transmitted or derived directly during the protocol.\n\n### How it Works:\n1. **Registration Phase**: Both parties exchange public parameters to initialize the protocol securely.\n2. **Password Derivation**: The shared password is processed with Argon2id, using explicit identities (`idProver` and `idVerifier`) and the hash function of the ciphersuite, to derive keying material.\n2. **Key Exchange**: The Prover and Verifier compute and exchange values (`X`, `Y`) to establish a shared secret.\n3. **Verification**: Both parties derive cryptographic secrets (`confirmP`, `confirmV`) to verify the integrity of the exchange and finalize authentication.\n\nSPAKE2+ is commonly used in applications requiring secure password-based authentication without relying on a trusted third party. It is especially suitable for environments where both parties already share a secret (like a password) and need to establish a secure communication channel.\n\n\n### Protocol overview\n\n```mermaid\n\nsequenceDiagram\n    participant Prover\n    participant Verifier\n\n    Note left of Prover: password\n\n    Note left of Prover: w0, w1 \u003c- Argon2id(password)\u003cbr/\u003e L = w1*P\n\n    Prover-\u003e\u003eVerifier: Offline Registration\u003cbr/\u003ew0, L\n\n    Note left of Prover: x \u003c- [0, p-1]\u003cbr/\u003eX = x*P + w0*M\n    Prover-\u003e\u003eVerifier: X\n    Note right of Verifier: y \u003c- [0, p-1]\u003cbr/\u003eY = y*P + w0*N\n    Verifier-\u003e\u003eProver: Y\n    Note left of Prover: Z = h*x*(Y - w0*N)\u003cbr/\u003eV = h*w1*(Y - w0*N)\n    Note right of Verifier: Z = h*y*(X - w0*M)\u003cbr/\u003eV = h*y*L\n\n    Note over Prover,Verifier: Compute transcript TT\u003cbr/\u003eK_main = Hash(TT)\u003cbr/\u003eK_confirmP || K_confirmV = KDF(K_main, \"ConfirmationKeys\")\u003cbr/\u003eK_shared = KDF(K_main, \"SharedKey\")\n    \n    Note right of Verifier: confirmV = MAC(K_confirmV, X)\n\n    Verifier-\u003e\u003eProver: confirmV\n    Note left of Prover: confirmP = MAC(K_confirmP, Y)\u003cbr/\u003eexpected_confirmV = MAC(K_confirmV, X)\u003cbr/\u003eequal_constant_time(expected_confirmV, confirmV)\n    Prover-\u003e\u003eVerifier: confirmP\n\n    Note right of Verifier: expected_confirmP = MAC(K_confirmP, Y)\u003cbr/\u003eequal_constant_time(expected_confirmP, confirmP)\n```\n\n## Requirements\n\nThis package requires the following dependencies:\n\n* [`cryptography`](https://pypi.org/project/cryptography/)\n* [`ecpy`](https://pypi.org/project/ecpy/)\n\nAll dependencies are automatically installed when you install the package via `pip`.\n\n## Installation\n\nDownload the latest version from [Releases](https://github.com/jiep/spake2plus/releases) and install with:\n\n```\npip install spake2plus-\u003cversion\u003e-py3-none-any.whl\n```\n\n## Build from source\n\nYou can install this package locally using `pip` upon cloning this repository:\n\n```bash\npip install -e .\n```\n\n## Usage\n\n```bash \nusage: spake2plus [-h] [-v] [--host HOST] [--port PORT]\n                  {verifier,prover,registration} ...\n\nSPAKE2+ Protocol\n\npositional arguments:\n  {verifier,prover,registration}\n    verifier            Run the verifier role in the\n                        SPAKE2+ protocol\n    prover              Run the prover role in the SPAKE2+\n                        protocol\n    registration        Perform registration for the Prover\n\noptions:\n  -h, --help            show this help message and exit\n  -v, --verbose         Increase output verbosity (e.g.,\n                        -v, -vv, -vvv)\n  --host HOST           Host to connect to (default:\n                        localhost)\n  --port PORT           Port to connect to (default: 12345)\n```\n\n### Offline registration\n\nThe `Prover` computes the values `w0` and `w1`, as well as the registration record `L`. `w0` and `w1` are derived by hashing the password with the identities of the two participants. `w0` and the record `L` are then shared with the `Verifier`. \n\n```bash\nusage: spake2plus registration [-h] --password PASSWORD --idProver IDPROVER --idVerifier IDVERIFIER\n                               [--ciphersuite {P256-SHA256,P256-SHA512,P384-SHA256,P384-SHA512,P521-SHA512,Edwards25519-SHA256,Edwards448-SHA512}]\n\noptions:\n  -h, --help            show this help message and exit\n  --password PASSWORD   Password for key generation\n  --idProver IDPROVER   Prover's identity\n  --idVerifier IDVERIFIER\n                        Verifier's identity\n  --ciphersuite {P256-SHA256,P256-SHA512,P384-SHA256,P384-SHA512,P521-SHA512,Edwards25519-SHA256,Edwards448-SHA512}\n                        Ciphersuite to use (default: P256-SHA256)\n```\n\n### Verifier\n\n```bash\nusage: spake2plus verifier [-h] --idProver IDPROVER --idVerifier IDVERIFIER --context CONTEXT --w0 W0 --L L\n                           [--ciphersuite {P256-SHA256,P256-SHA512,P384-SHA256,P384-SHA512,P521-SHA512,Edwards25519-SHA256,Edwards448-SHA512}]\n\noptions:\n  -h, --help            show this help message and exit\n  --idProver IDPROVER   Prover's identity\n  --idVerifier IDVERIFIER\n                        Verifier's identity\n  --context CONTEXT     Protocol context\n  --w0 W0               Value for w0 as hexadecimal string\n  --L L                 Value for L as hexadecimal string\n  --ciphersuite {P256-SHA256,P256-SHA512,P384-SHA256,P384-SHA512,P521-SHA512,Edwards25519-SHA256,Edwards448-SHA512}\n                        Ciphersuite to use (default: P256-SHA256)\n```\n\n### Prover\n\n```bash\nusage: spake2plus prover [-h] --idProver IDPROVER --idVerifier IDVERIFIER --context CONTEXT --w0 W0 --w1 W1\n                         [--ciphersuite {P256-SHA256,P256-SHA512,P384-SHA256,P384-SHA512,P521-SHA512,Edwards25519-SHA256,Edwards448-SHA512}]\n\noptions:\n  -h, --help            show this help message and exit\n  --idProver IDPROVER   Prover's identity\n  --idVerifier IDVERIFIER\n                        Verifier's identity\n  --context CONTEXT     Protocol context\n  --w0 W0               Value for w0 as hexadecimal string\n  --w1 W1               Value for w1 as hexadecimal string\n  --ciphersuite {P256-SHA256,P256-SHA512,P384-SHA256,P384-SHA512,P521-SHA512,Edwards25519-SHA256,Edwards448-SHA512}\n                        Ciphersuite to use (default: P256-SHA256)\n```\n\n## Examples\n\n### Registration\n\n```bash\nspake2plus registration --password superImporT4antPassWord! --idProver alice --idVerifier bob --ciphersuite P256-SHA256\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eShow output\u003c/summary\u003e\n\n```bash\n2024-12-01 14:06:51.789 [INFO] Ciphersuite: P256-SHA256\n2024-12-01 14:06:52.048 [INFO] w0 = 3bccdf7f0940907dac69758d327eb9c40c5a7f95ee63a80e042e5473ce789e76\n2024-12-01 14:06:52.048 [INFO] w1 = 59f7bce5c93c087e114d95b542f100124e1814be7f383c376a9a441045092a0b\n2024-12-01 14:06:52.048 [INFO] L  = 04c9b019fbe6d4e727dfd9cd831f3c36a6fec8b05972bed62d3b0493c8cfc2163dc739cda27dcb7aa6726008f7312281d9ffe61edc178af1f26a96a1a6dc6cfbc4\n```\n\n\u003c/details\u003e\n\n### Verifier\n\nThe `Verifier` acts as a server in the protocol. You can run it as follows:\n\n```bash\nspake2plus verifier --idProver alice --idVerifier bob --context KeyExchange --w0 3bccdf7f0940907dac69758d327eb9c40c5a7f95ee63a80e042e5473ce789e76 --L 04c9b019fbe6d4e727dfd9cd831f3c36a6fec8b05972bed62d3b0493c8cfc2163dc739cda27dcb7aa6726008f7312281d9ffe61edc178af1f26a96a1a6dc6cfbc4 --ciphersuite P256-SHA256\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eShow output\u003c/summary\u003e\n\n```bash\n2024-12-01 14:11:45.727 [INFO] Ciphersuite: P256-SHA256\n2024-12-01 14:11:45.728 [INFO] Verifier is listening on localhost:12345...\n2024-12-01 14:13:04.771 [INFO] P -\u003e V [65]: X = 04dfc96734066fd75a4093d402f33945312f71637c8515524cd44736d0d762cd8a162a72d868fb5e155908f01af1319f69739f6591451ca9978b6bb64a4c4383a8\n2024-12-01 14:13:04.886 [INFO] P \u003c- V [65]: Y = 04835bd8437b2dd3bd920dcbb3aa81c72874e8bdb81aa76c3c2b99a7e9ca22ad397dd844c701eb77264d61f13926a5fc3730d100bb08e4935d770885392d29e1dd\n2024-12-01 14:13:04.887 [INFO] V: Computing key schedule...\n2024-12-01 14:13:04.888 [INFO] P \u003c- V [32]: confirmV = ab44635917470ac4cf52130c881749151e544b8f4fcc987aad2e64afc5201665\n2024-12-01 14:13:04.979 [INFO] P -\u003e V [[32]]: confirmP = d97eba35ac718b69bc8549bb5d73646d42d68739cf392f4d346eab88a6e556a3\n2024-12-01 14:13:04.979 [INFO] V: Protocol completed successfully.\n```\n\u003c/details\u003e\n\n### Prover\n\nThe `Prover` acts as a client in the protocol. You can run it as follows:\n\n```bash\nspake2plus prover --idProver alice --idVerifier bob --context KeyExchange --w0 3bccdf7f0940907dac69758d327eb9c40c5a7f95ee63a80e042e5473ce789e76 --w1 59f7bce5c93c087e114d95b542f100124e1814be7f383c376a9a441045092a0b --ciphersuite P256-SHA256\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eShow output\u003c/summary\u003e\n\n```bash\n2024-12-01 14:13:04.724 [INFO] Ciphersuite: P256-SHA256\n2024-12-01 14:13:04.725 [INFO] Connected to Verifier at localhost:12345\n2024-12-01 14:13:04.771 [INFO] P -\u003e V [65]: X = 04dfc96734066fd75a4093d402f33945312f71637c8515524cd44736d0d762cd8a162a72d868fb5e155908f01af1319f69739f6591451ca9978b6bb64a4c4383a8]\n2024-12-01 14:13:04.886 [INFO] P \u003c- V [65]: Y = 04835bd8437b2dd3bd920dcbb3aa81c72874e8bdb81aa76c3c2b99a7e9ca22ad397dd844c701eb77264d61f13926a5fc3730d100bb08e4935d770885392d29e1dd\n2024-12-01 14:13:04.977 [INFO] P: Computing key schedule...\n2024-12-01 14:13:04.979 [INFO] P \u003c- V [32]: confirmV = ab44635917470ac4cf52130c881749151e544b8f4fcc987aad2e64afc5201665\n2024-12-01 14:13:04.979 [INFO] P -\u003e V [32]: confirmP = d97eba35ac718b69bc8549bb5d73646d42d68739cf392f4d346eab88a6e556a3\n2024-12-01 14:13:04.979 [INFO] P: Protocol completed successfully.\n```\n\u003c/details\u003e\n\n\u003e [!NOTE]  \n\u003e If not specified ciphersuite, `P256-SHA256` is used by default.\n\u003e\n\u003e Ciphersuites allowed: `P256-SHA256`, `P256-SHA512`, `P384-SHA256`, `P384-SHA512`, `P521-SHA512`, `Edwards25519-SHA256`, and `Edwards448-SHA512`.\n\n\u003e [!WARNING]  \n\u003e `idProvider`, `idVerifier`, `context`  must be the identical for `Prover` and `Verifier`! \n\n\n## Ciphersuites\n\n| Ciphersuite           | G            | Hash              | KDF                   | MAC                   | PBKDF              |\n|-----------------------|--------------|-------------------|-----------------------|-----------------------|--------------------|\n| `P256-SHA256`         | P-256        | SHA256 [RFC6234]  | HKDF-SHA256 [RFC5869] | HMAC-SHA256 [RFC2104] | Argon2id [RFC9106] |\n| `P256-SHA512`         | P-256        | SHA512 [RFC6234]  | HKDF-SHA512 [RFC5869] | HMAC-SHA512 [RFC2104] | Argon2id [RFC9106] |\n| `P384-SHA256`         | P-384        | SHA256 [RFC6234]  | HKDF-SHA256 [RFC5869] | HMAC-SHA256 [RFC2104] | Argon2id [RFC9106] |\n| `P384-SHA512`         | P-384        | SHA512 [RFC6234]  | HKDF-SHA512 [RFC5869] | HMAC-SHA512 [RFC2104] | Argon2id [RFC9106] |\n| `P521-SHA512`         | P-521        | SHA512 [RFC6234]  | HKDF-SHA512 [RFC5869] | HMAC-SHA512 [RFC2104] | Argon2id [RFC9106] |\n| `P521-SHA512`         | P-521        | SHA512 [RFC6234]  | HKDF-SHA512 [RFC5869] | HMAC-SHA512 [RFC2104] | Argon2id [RFC9106] |\n| `Edwards25519-SHA256` | Edwards25519 | SHA256 [RFC6234]  | HKDF-SHA256 [RFC5869] | HMAC-SHA256 [RFC2104] | Argon2id [RFC9106] |\n| `Edwards448-SHA512`   | Edwards448   | SHA512 [RFC6234]  | HKDF-SHA512 [RFC5869] | HMAC-SHA512 [RFC2104] | Argon2id [RFC9106] |\n\n\u003cdetails\u003e\n\n\u003csummary\u003eShow references\u003c/summary\u003e\n\n- [RFC6234] Eastlake 3rd, D. and T. Hansen, \"US Secure Hash Algorithms\n            (SHA and SHA-based HMAC and HKDF)\", RFC 6234,\n            DOI 10.17487/RFC6234, May 2011,\n            https://www.rfc-editor.org/info/rfc6234\n\n- [RFC5869] Krawczyk, H. and P. Eronen, \"HMAC-based Extract-and-Expand\n            Key Derivation Function (HKDF)\", RFC 5869,\n            DOI 10.17487/RFC5869, May 2010,\n            https://www.rfc-editor.org/info/rfc5869\n\n- [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, \"HMAC: Keyed-\n            Hashing for Message Authentication\", RFC 2104,\n            DOI 10.17487/RFC2104, February 1997,\n            https://www.rfc-editor.org/info/rfc2104\n\n- [RFC9106] Biryukov, A., Dinu, D., Khovratovich, D., and S.\n            Josefsson, \"Argon2 Memory-Hard Function for Password\n            Hashing and Proof-of-Work Applications\", RFC 9106,\n            DOI 10.17487/RFC9106, September 2021,\n            https://www.rfc-editor.org/info/rfc9106\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eShow values for N and M\u003c/summary\u003e\n\n- `P-256`\n\n  ```\n  M = 02886e2f97ace46e55ba9dd7242579f2993b64e16ef3dcab95afd497333d8fa12f\n\n  seed: 1.2.840.10045.3.1.7 point generation seed (M)\n  ```\n\n  ```\n  N = 03d8bbd6c639c62937b04d997f38c3770719c629d7014d49a24b4f98baa1292b49\n\n  seed: 1.2.840.10045.3.1.7 point generation seed (N)\n  ```\n\n- `P-384`\n\n  ```\n  M = 030ff0895ae5ebf6187080a82d82b42e2765e3b2f8749c7e05eba366434b363d3dc36f15314739074d2eb8613fceec2853\n\n  seed: 1.3.132.0.34 point generation seed (M)\n  ```\n\n  ```\n  N = 02c72cf2e390853a1c1c4ad816a62fd15824f56078918f43f922ca21518f9c543bb252c5490214cf9aa3f0baab4b665c10\n\n  seed: 1.3.132.0.34 point generation seed (N)\n  ```\n\n- `P-521`\n\n  ```\n  M =\n  02003f06f38131b2ba2600791e82488e8d20ab889af753a41806c5db18d37d85608cfae06b82e4a72cd744c719193562a653ea1f119eef9356907edc9b56979962d7aa\n\n  seed: 1.3.132.0.35 point generation seed (M)\n  ```\n\n  ```\n  N = 0200c7924b9ec017f3094562894336a53c50167ba8c5963876880542bc669e494b2532d76c5b53dfb349fdf69154b9e0048c58a42e8ed04cef052a3bc349d95575cd25\n\n  seed: 1.3.132.0.35 point generation seed (N)\n  ```\n\n- `Edwards25519`\n\n  ```\n  M = d048032c6ea0b6d697ddc2e86bda85a33adac920f1bf18e1b0c6d166a5cecdaf\n\n  seed: edwards25519 point generation seed (M)\n  ```\n\n  ```\n  N = d3bfb518f44f3430f29d0c92af503865a1ed3281dc69b35dd868ba85f886c4ab\n\n  seed: edwards25519 point generation seed (N)\n  ```\n\n- `Edwards448`\n\n  ```\n  M = b6221038a775ecd007a4e4dde39fd76ae91d3cf0cc92be8f0c2fa6d6b66f9a12942f5a92646109152292464f3e63d354701c7848d9fc3b8880\n\n  seed: edwards448 point generation seed (M)\n  ```\n\n  ```\n  N = 6034c65b66e4cd7a49b0edec3e3c9ccc4588afd8cf324e29f0a84a072531c4dbf97ff9af195ed714a689251f08f8e06e2d1f24a0ffc0146600\n\n  seed: edwards448 point generation seed (N)\n  ```\n\n\u003c/details\u003e\n\n\n\n## Contributing\n\nContributions are welcome! To contribute, follow these steps:\n\n1. Fork the repository.\n2. Create a new branch (`git checkout -b feature/new-feature`).\n3. Make your changes and commit them (`git commit -m 'Add new feature'`).\n4. Push to your branch (git push origin feature/new-feature).\n5. Open a pull request.\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.\n\n## Logo\n\nThe logo used in this project was automatically created by **ChatGPT**. This process involves a combination of creative design assisted by AI to provide a visual representation of the project.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiep%2Fspake2plus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjiep%2Fspake2plus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiep%2Fspake2plus/lists"}