{"id":46793523,"url":"https://github.com/codeheadsystems/hofmann-elimination","last_synced_at":"2026-05-10T17:20:11.644Z","repository":{"id":337313275,"uuid":"1152872322","full_name":"codeheadsystems/hofmann-elimination","owner":"codeheadsystems","description":"OPF framework for shared keys built from sensitive data","archived":false,"fork":false,"pushed_at":"2026-03-08T18:13:53.000Z","size":1026,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-08T19:18:34.065Z","etag":null,"topics":["cryptography","dropwizard","java","opaque","oprf","pake","password-authentication","rfc9497","rfc9807","spring-boot","typescript"],"latest_commit_sha":null,"homepage":"https://codeheadsystems.github.io/hofmann-elimination/","language":"Java","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/codeheadsystems.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-08T15:12:06.000Z","updated_at":"2026-03-08T18:08:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/codeheadsystems/hofmann-elimination","commit_stats":null,"previous_names":["wolpert/hofmann-elimination","codeheadsystems/hofmann-elimination"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/codeheadsystems/hofmann-elimination","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeheadsystems%2Fhofmann-elimination","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeheadsystems%2Fhofmann-elimination/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeheadsystems%2Fhofmann-elimination/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeheadsystems%2Fhofmann-elimination/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codeheadsystems","download_url":"https://codeload.github.com/codeheadsystems/hofmann-elimination/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeheadsystems%2Fhofmann-elimination/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30321455,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T01:36:58.598Z","status":"ssl_error","status_checked_at":"2026-03-10T01:36:50.788Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","dropwizard","java","opaque","oprf","pake","password-authentication","rfc9497","rfc9807","spring-boot","typescript"],"created_at":"2026-03-10T03:05:03.016Z","updated_at":"2026-03-10T03:05:03.608Z","avatar_url":"https://github.com/codeheadsystems.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# the Hofmann Elimination\n\n## tl;dr\n\nThis project implements the OPRF and OPAQUE security protocols to provide a way\nfor common services to reduce their attack surfaces including offline attacks\nfrom stolen credentials. Usable with standard Java frameworks like Dropwizard and Spring Boot.\n\n## Module Structure\n\n![the Hofmann Elimination Build](https://github.com/codeheadsystems/hofmann-elimination/actions/workflows/gradle.yml/badge.svg)\n\n### Java / Server-side (Maven artifacts)\n\n| -- Artifact ID       | Version                                                                                                                                                                                                                        | Description                                                                                                    |\n|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|\n| `hofmann-rfc`        | [![Maven Central: hofmann-rfc](https://img.shields.io/maven-central/v/com.codeheadsystems/hofmann-rfc?label=hofmann-rfc)](https://central.sonatype.com/artifact/com.codeheadsystems/hofmann-rfc)                               | All RFC implementations: hash-to-curve (RFC 9380), OPRF (RFC 9497), OPAQUE (RFC 9807), plus shared model DTOs. |\n| `hofmann-client`     | [![Maven Central: hofmann-client](https://img.shields.io/maven-central/v/com.codeheadsystems/hofmann-client?label=hofmann-client)](https://central.sonatype.com/artifact/com.codeheadsystems/hofmann-client)                   | Client files needed for OPRF/OPAQUE integration.                                                               |\n| `hofmann-server`     | [![Maven Central: hofmann-server](https://img.shields.io/maven-central/v/com.codeheadsystems/hofmann-server?label=hofmann-server)](https://central.sonatype.com/artifact/com.codeheadsystems/hofmann-server)                   | Server files needed for OPRF/OPAQUE integration.                                                               |\n| `hofmann-dropwizard` | [![Maven Central: hofmann-dropwizard](https://img.shields.io/maven-central/v/com.codeheadsystems/hofmann-dropwizard?label=hofmann-dropwizard)](https://central.sonatype.com/artifact/com.codeheadsystems/hofmann-dropwizard)   | Integration files specific for Dropwizard.                                                                     |\n| `hofmann-springboot` | [![Maven Central: hofmann-springboot](https://img.shields.io/maven-central/v/com.codeheadsystems/hofmann-springboot?label=hofmann-springboot)](https://central.sonatype.com/artifact/com.codeheadsystems/hofmann-springboot)   | Integration files specific for Spring Boot.                                                                    |\n\n### TypeScript / Browser client\n\n| Directory              | Description                                                                                              |\n|------------------------|----------------------------------------------------------------------------------------------------------|\n| [`hofmann-typescript`](hofmann-typescript/README.md) | Browser/Node TypeScript client — RFC 9497 OPRF + RFC 9807 OPAQUE-3DH. Built on `@noble/curves` and `@noble/hashes`. Includes a Vite-powered interactive demo page. |\n\n### Demo environment\n\n| Directory              | Description                                                                                              |\n|------------------------|----------------------------------------------------------------------------------------------------------|\n| [`hofmann-demo`](hofmann-demo/README.md) | Docker Compose environment running the Dropwizard server and the TypeScript demo UI behind HAProxy with TLS 1.3. Self-signed P-256 cert generated via `make certs`. Run with `make up`. |\n\n### Example Application\n\nSee [hofmann-elimination-example](https://github.com/codeheadsystems/hofmann-elimination-example) for a complete working application demonstrating OPAQUE integration end-to-end.\n\n### Documentation\n\n- **[Project landing page](https://codeheadsystems.github.io/hofmann-elimination/)** — overview, protocol diagrams, quick start guides\n- **[Migration guide](MIGRATION.md)** — how to migrate an existing site from traditional password auth to OPAQUE\n- **[Configuration guide](USAGE.md)** — server configuration, key management, credential store implementation\n- **[Account recovery guide](RECOVERY.md)** — pluggable account recovery via email, OTP, or custom mechanisms\n- **[Interactive API docs](https://codeheadsystems.github.io/hofmann-elimination/api-docs.html)** — Swagger UI for OPAQUE and OPRF endpoints\n- **At runtime:** Start your Dropwizard or Spring Boot server and visit `/api-docs/` for embedded Swagger UI\n- **Raw OpenAPI specs:** [OPRF API](docs/oprf-api.yaml) | [OPAQUE API](docs/opaque-api.yaml)\n\n### Building\n\n#### Java (requires Java 21)\n\n```\n./gradlew clean build test\n```\n\n#### TypeScript\n\n```\ncd hofmann-typescript\nnpm install\nnpm test\nnpm run build\n```\n\n## Purpose\n\nThis project provides a pure Java implementation of the OPRF and OPAQUE protocols,\nenabling services to authenticate users without ever storing or transmitting the\npassword or private key material. By using OPRF and OPAQUE, services can\nsignificantly reduce the attack surface and protect user credentials even in the\nevent of a server breach — a compromised server database does not expose passwords\nto offline dictionary attacks because the server never holds a recoverable form of\nthe password.\n\nThis project also provides the OPRF primitive on its own. This allows clients\nto create identifiers from hashing sensitive material that are consistent and\nreusable across multiple clients without sharing that key material that generated\nthem. The result is an identifier that services can use without learning what\ndata produced it. Useful when that data is sensitive information the client wants\nto keep private.\n\n## Protocols\n\nThis project implements three layered RFCs:\n\n- **Hash-to-Curve** ([details](hofmann-rfc/HASH_TO_CURVE.md), [rfc 9380](https://www.rfc-editor.org/rfc/rfc9380.html)): Deterministically maps\n  arbitrary input to an elliptic curve point using Simplified SWU and `expand_message_xmd`.\n  Used internally by OPRF.\n\n- **OPRF** ([details](hofmann-rfc/OPRF.md), [rfc 9497](https://www.rfc-editor.org/rfc/rfc9497.html)): Oblivious Pseudorandom Functions. The client\n  computes a pseudorandom function on private input using the server's secret key, without\n  the server ever learning the input. Supports P-256/SHA-256, P-384/SHA-384, P-521/SHA-512,\n  and Ristretto255/SHA-512.\n\n- **OPAQUE** ([details](hofmann-rfc/OPAQUE.md), [rfc 9807](https://www.rfc-editor.org/rfc/rfc9807.html)): Augmented Password-Authenticated Key\n  Exchange. Password-based authentication where the password is never transmitted and a\n  compromised server database does not expose passwords to offline dictionary attacks.\n\n- **Account Recovery** ([details](RECOVERY.md)): Pluggable account recovery that works\n  alongside OPAQUE without modifying the protocol. Users prove their identity through an\n  out-of-band mechanism (email code, SMS OTP, TOTP, etc.) and then re-register with a new\n  password. Implement the `RecoveryChallenger` interface to define your recovery method.\n\nFor protocol details, cipher suites, API reference, and wire formats, see the linked docs above.\n\n## Security\n\nAs of February 2026, this implementation has not undergone a formal security audit.\nSee [SECURITY.md](SECURITY.md) for the full security posture, known design decisions,\nand how to report vulnerabilities.\n\nInitial RFC implementations were produced with the help of AI tooling and reviewed\nagainst the RFC specifications by a human (Ned). AIs have also been used to search\nfor direct and side-channel attack vectors, but this is not a substitute for a formal\nthird-party audit.\n\n## Related Projects\n\nFor a detailed feature comparison table across all projects, see the\n[project landing page](https://codeheadsystems.github.io/hofmann-elimination/).\nThis project is the only known pure-Java, RFC-compliant (9380 + 9497 + 9807) implementation\nsupporting multiple cipher suites that is distributable as a standard Maven artifact with\nframework integrations. But I link to the other projects in case this does not meet\nyour needs.\n\n## License\n\nCopyright 2026 Ned Wolpert\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n## Origins of the name\n\nThe [Hofmann Elimination](https://en.wikipedia.org/wiki/Hofmann_elimination) is a chemical reaction that involves the elimination of an\n amine to produce an alkene. This reaction is named after the German chemist August\nWilhelm von Hofmann, who first described it in the 19th century. The Hofmann elimination\nis often used to synthesize alkenes from amines. It does this by treating the quaternary\nammonium salt with a strong base, such as sodium hydroxide, which leads to the elimination\nof the ammonium group and the formation of an alkene. The reaction is typically carried out\nunder heat to facilitate the elimination process.\n\nUnlike other elimination reactions, the Hofmann elimination produces the least substituted\nalkene as the major product, which is a result of the steric hindrance around the quaternary\nammonium salt. This makes it a useful reaction for synthesizing specific alkenes that may be\ndifficult to obtain through other methods.\n\nJust as the Hofmann elimination removes an amine group from a molecule, leaving no trace\nof the original nitrogen compound in the product, this protocol eliminates the password\nand private key material from every value that leaves the client. The server evaluates the\nfunction, stores credentials, and verifies authentication without ever seeing the sensitive input.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeheadsystems%2Fhofmann-elimination","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodeheadsystems%2Fhofmann-elimination","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeheadsystems%2Fhofmann-elimination/lists"}