{"id":21513239,"url":"https://github.com/patrickfav/singlestep-kdf","last_synced_at":"2025-04-09T18:52:52.330Z","repository":{"id":47284221,"uuid":"158036786","full_name":"patrickfav/singlestep-kdf","owner":"patrickfav","description":"Implementation of the single-step key derivation function (KDF) as described in NIST Special Publication 800-56C Rev1 supporting messages digest and HMAC.","archived":false,"fork":false,"pushed_at":"2023-03-12T18:01:56.000Z","size":2196,"stargazers_count":10,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-23T20:51:15.578Z","etag":null,"topics":["cryptography","hmac","java","kdf","key-agreement","key-derivation","key-derivation-function","message-digest","nist","nist800-56","secretkey","security","singlestep-kdf"],"latest_commit_sha":null,"homepage":"https://favr.dev/opensource/singlestep-kdf","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/patrickfav.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-18T00:28:29.000Z","updated_at":"2024-12-09T19:53:53.000Z","dependencies_parsed_at":"2022-09-02T22:01:16.594Z","dependency_job_id":null,"html_url":"https://github.com/patrickfav/singlestep-kdf","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fsinglestep-kdf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fsinglestep-kdf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fsinglestep-kdf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fsinglestep-kdf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patrickfav","download_url":"https://codeload.github.com/patrickfav/singlestep-kdf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248093221,"owners_count":21046646,"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","hmac","java","kdf","key-agreement","key-derivation","key-derivation-function","message-digest","nist","nist800-56","secretkey","security","singlestep-kdf"],"created_at":"2024-11-23T22:55:07.349Z","updated_at":"2025-04-09T18:52:52.303Z","avatar_url":"https://github.com/patrickfav.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Single Step KDF (NIST SP 800-56C)\n\nThis is an implementation of the single-step key derivation function as described\nin [NIST SP 800-56C revision 1, chapter 4](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr1.pdf).\nIt is an unopinionated approach towards the subject, allowing all 3 options (message digest, hmac and kmac) as H\nfunction and leaving open the exact format of the `fixedInfo` parameter.\n\n[![Maven Central](https://img.shields.io/maven-central/v/at.favre.lib/singlestep-kdf)](https://mvnrepository.com/artifact/at.favre.lib/singlestep-kdf)\n[![Github Actions](https://github.com/patrickfav/singlestep-kdf/actions/workflows/build_deploy.yml/badge.svg)](https://github.com/patrickfav/singlestep-kdf/actions)\n[![Javadocs](https://www.javadoc.io/badge/at.favre.lib/singlestep-kdf.svg)](https://www.javadoc.io/doc/at.favre.lib/singlestep-kdf)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=patrickfav_singlestep-kdf\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=patrickfav_singlestep-kdf)\n[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=patrickfav_singlestep-kdf\u0026metric=security_rating)](https://sonarcloud.io/summary/new_code?id=patrickfav_singlestep-kdf)\n[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=patrickfav_singlestep-kdf\u0026metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=patrickfav_singlestep-kdf)\n\nThis is a standalone, lightweight, simple to use, fully tested and stable implementation in Java. The code is compiled\nwith [Java 7](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_7) to be compatible with most [\n_Android_](https://www.android.com/) versions as well as normal Java applications.\n\n## Quickstart\n\nAdd dependency to your `pom.xml`:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eat.favre.lib\u003c/groupId\u003e\n    \u003cartifactId\u003esinglestep-kdf\u003c/artifactId\u003e\n    \u003cversion\u003e{latest-version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nA very simple example:\n\n```java\n// a shared secret provided by your protocol\nbyte[] sharedSecret = ...\n// a salt; if you don't have access to a salt, use salt-less SingleStepKdf.fromSha256() or similar\nbyte[] salt = ...\n// other info to bind the key to the context, see the NIST spec for more detail\nbyte[] otherInfo = \"macKey\".getBytes();\nbyte[] keyMaterial = SingleStepKdf.fromHmacSha256().derive(sharedSecret, 32, salt, otherInfo);\nSecretKey secretKey = new SecretKeySpec(keyMaterial, \"AES\");\n```\n\n## Full Example\n\nNIST 800-56C specifies the KDF with an H-function which may be a [hash](https://en.wikipedia.org/wiki/Cryptographic_hash_function), [HMAC](https://en.wikipedia.org/wiki/HMAC) or [KMAC](https://keccak.team/index.html).\n\n### Using with Message Digest (Option 1)\n\nUsing Option 1, i.e. `H(x) = hash(x)`, where hash is an approved hash function. Note that when you use this option, the\nsalt parameter is not supported. If you want to incorporate a salt just include it into the `fixedInfo` parameter. **If\nyou have no specific reason for choosing Option 1, I would always prefer Option 2 (HMAC) over this one.**\n\n```java\n// a shared secret provided by your protocol\nbyte[] sharedSecret = Bytes.random(16).array();\n// fixed info to bind the key to the context\nbyte[] fixedInfo = \"macKey\".getBytes();\n// salt is not directly supported with message digest, you may include it in fixedInfo\nbyte[] keyMaterial = SingleStepKdf.fromSha256().derive(sharedSecret, 32, fixedInfo);\nSecretKey secretKey = new SecretKeySpec(keyMaterial, \"AES\");\n```\n\n### Using with HMAC (Option 2)\n\nUsing Option 2, i.e. `H(x) = HMAC-hash(salt, x)`, where HMAC-hash is an implementation of the HMAC algorithm (as defined\nin FIPS 198) employing an approved hash function. A salt which serves as the HMAC key, and x (the input to H) is a bit\nstring that serves as the HMAC \"message\". This library can use any `Mac` implementation. If no salt is provided, an\nempty array is internally initialized.\n\n```java\nbyte[] keyMaterial = SingleStepKdf.fromHmacSha256().derive(sharedSecret, 32, salt, fixedInfo);\n        SecretKey secretKey = new SecretKeySpec(keyMaterial, \"AES\");\n```\n\n### Using with KMAC (Option 3)\n\nKMAC is a MAC using [SHA-3/Keccak](https://en.wikipedia.org/wiki/SHA-3). Unlike SHA-1 and\nSHA-2, [Keccak](http://keccak.noekeon.org/) does not have\nthe [length-extension weakness](https://en.wikipedia.org/wiki/Length_extension_attack), hence does not need the HMAC\nnested construction. Instead, MAC computation can be performed by simply prepending the message with the key. Java has\nan SHA-3 implementation [since version 9](https://openjdk.java.net/jeps/287). This library is designed to support Java\n7, so no default implementation is present for KMAC. It is probably quite easy to implement it yourself using either\nthe `HFunctionFactory.MacFactory` or implementing yourself with `HFunction`.\n\n### Using custom Message Digest / HMAC implementation\n\nDefault implementation exists for the h-function which can be used for any `MessageDigest` or `Mac`. It is also possible to implement it from scratch by using the `HFunction` interface. A factory is used to generate instances. This can be used like this:\n\n```java\n// create instance with sha1 as backing hash function\nSingleStepKdf sha1Kdf = SingleStepKdf.from(new HFunctionFactory.Default.DigestFactory(\"SHA-1\"));\n// create instance with HMAC-SHA1 as backing h function\nSingleStepKdf hmacSha1Kdf = SingleStepKdf.from(new HFunctionFactory.Default.DigestFactory(\"HmacSHA1\"));\n```\n\n### How to use the Fixed-Info Parameter\n\nA bit string of context-specific data that is appropriate for the relying on key-establishment scheme. As its name\nsuggests, the value of `FixedInfo` does not change during the execution of the process.\n\n`FixedInfo` may, for example, include appropriately formatted representations of the values of salt and/or the output\nlength. The inclusion of additional copies of the values of salt and the output length in `FixedInfo` would ensure that\neach block of derived keying material is affected by all the information conveyed in `OtherInput`.\nSee [SP 800-56A](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf)\nand [SP 800-56B](https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-56br1.pdf) for more detailed\nrecommendations concerning the format and content of `FixedInfo` (also known as OtherInfo in earlier versions of those\ndocuments).\n\n## Download\n\nThe artifacts are deployed to [jcenter](https://bintray.com/bintray/jcenter) and [Maven Central](https://search.maven.org/).\n\n### Maven\n\nAdd dependency to your `pom.xml`:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eat.favre.lib\u003c/groupId\u003e\n    \u003cartifactId\u003esinglestep-kdf\u003c/artifactId\u003e\n    \u003cversion\u003e{latest-version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Gradle\n\nAdd to your `build.gradle` module dependencies:\n\n    compile group: 'at.favre.lib', name: 'singlestep-kdf', version: '{latest-version}'\n\n### Local Jar\n\n[Grab jar from the latest release.](https://github.com/patrickfav/singlestep-kdf/releases/latest)\n\n\n## Description\n\nThe following is summarized and shortened version of [NIST 800-56C Rev1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr1.pdf) chapter about the single-step KDF:\n\nSingle Step KDF specifies a family of approved key-derivation functions (KDFs) that are executed in a single step; The input to each specified KDF includes the shared secret generated during the execution of a key-establishment scheme specified in [SP 800-56A](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf) or [SP 800-56B](https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-56br1.pdf), an indication of the desired bit length of the keying material to be output, and, perhaps, other information (as determined by the particular implementation of the key-establishment scheme and/or key-derivation function).\n\nImplementations of these one-step KDFs depend upon the choice of an auxiliary function H, which can be either:\n \n 1. an approved hash function, denoted as hash, as defined in [FIPS 180](https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.180-4.pdf) or [FIPS 202](https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf); \n 2. HMAC with an approved hash function, hash, denoted as HMAC-hash, and defined in [FIPS 198](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf); or \n 3. a KMAC variant, as defined in [SP 800-185](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf). H shall be chosen in accordance with the selection requirements specified in [800-56C Rev1/Section 7](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr1.pdf).\n\nWhen an approved MAC algorithm (HMAC or KMAC) is used to define the auxiliary function H, it is permitted to use a known salt value as the MAC key. In such cases, it is assumed that the MAC algorithm will satisfy the following property (for each of its supported security strengths):\n\nGiven knowledge of the key `k`, and (perhaps) partial knowledge of a message `x` that includes an unknown substring `z`, it must be computationally infeasible to predict the (as-yet-unseen) value of `MAC(k, x, …)` with a probability of success that is a significant improvement over simply guessing either the MAC value or the value of `z`, even if one has already seen the values of `MAC(kj, xj, …)` for a feasible number of other `(kj, xj)` pairs, where each key `kj` is known and each (partially known) message `xj` includes the same unknown substring `z`, provided that none of the `(kj, xj)` pairs is identical to `(k, x)`.\n\nThis property is consistent with the use of the MAC algorithm as the specification of a family of pseudorandom functions defined on the appropriate message space and indexed by the choice of MAC key. Under Option 2 and Option 3 of the KDF specification below, the auxiliary function H is a particular selection from such a family.\n\n### Two-Step Key Derivation Function\n\nNIST 800-56C Rev1 also describes a two-step kdf with an extract and expand phase. The most prominent implementation of\nit is [HKDF (RFC5869)](https://tools.ietf.org/html/rfc5869). A java implementation of it can\nbe [found here](https://github.com/patrickfav/hkdf).\n\n### Test Vectors\n\nUnfortunately it seems that the NIST did not provide any official test\nvectors ([see this post](https://crypto.stackexchange.com/questions/64140/where-can-i-find-official-test-vectors-for-nist-sp-800-56c-r1-single-step-kdf)).\nThis implementation ist tested against\nthe [code snippets posted here](https://stackoverflow.com/questions/10879658/existing-implementations-for-nist-sp-800-56a-concatenation-key-derivation-functi/10971402#10971402).\nAdditionally, I released\nmy [own test vectors in the wiki](https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors),\nso you could test against another possible already existing implementation.\n\n## Security Relevant Information\n\n### OWASP Dependency Check\n\nThis project uses the [OWASP Dependency-Check](https://www.owasp.org/index.php/OWASP_Dependency_Check) which is a utility that identifies project dependencies and checks if there are any known, publicly disclosed, vulnerabilities against a [NIST database](https://nvd.nist.gov/vuln/data-feeds).\nThe build will fail if any issue is found.\n\n### Digital Signatures\n\n#### Signed Jar\n\nThe provided JARs in the GitHub release page are signed with my private key:\n\n    CN=Patrick Favre-Bulle, OU=Private, O=PF Github Open Source, L=Vienna, ST=Vienna, C=AT\n    Validity: Thu Sep 07 16:40:57 SGT 2017 to: Fri Feb 10 16:40:57 SGT 2034\n    SHA1: 06:DE:F2:C5:F7:BC:0C:11:ED:35:E2:0F:B1:9F:78:99:0F:BE:43:C4\n    SHA256: 2B:65:33:B0:1C:0D:2A:69:4E:2D:53:8F:29:D5:6C:D6:87:AF:06:42:1F:1A:EE:B3:3C:E0:6D:0B:65:A1:AA:88\n\nUse the jarsigner tool (found in your `$JAVA_HOME/bin` folder) folder to verify.\n\n#### Signed Commits\n\nAll tags and commits by me are signed with git with my private key:\n\n    GPG key ID: 4FDF85343912A3AB\n    Fingerprint: 2FB392FB05158589B767960C4FDF85343912A3AB\n\n## Build\n\n### Jar Sign\n\nIf you want to jar sign you need to provide a file `keystore.jks` in the\nroot folder with the correct credentials set in environment variables (\n`OPENSOURCE_PROJECTS_KS_PW` and `OPENSOURCE_PROJECTS_KEY_PW`); alias is\nset as `pfopensource`.\n\nIf you want to skip jar signing just change the skip configuration in the\n`pom.xml` jar sign plugin to true:\n\n    \u003cskip\u003etrue\u003c/skip\u003e\n\n### Build with Maven\n\nUse maven wrapper to create a jar including all dependencies\n\n    ./mvnw clean install\n\n### Checkstyle Config File\n\nThis project uses my [`common-parent`](https://github.com/patrickfav/mvn-common-parent) which centralized a lot of\nthe plugin versions aswell as providing the checkstyle config rules. Specifically they are maintained in [`checkstyle-config`](https://github.com/patrickfav/checkstyle-config). Locally the files will be copied after you `mvnw install` into your `target` folder and is called\n`target/checkstyle-checker.xml`. So if you use a plugin for your IDE, use this file as your local configuration.\n\n## Tech-Stack\n\n* Java 7\n* Maven (Wrapper)\n* Errorprone, Checkstyle\n\n## Related Libraries\n\n* [BCyrpt Password Hash Function (Java)](https://github.com/patrickfav/bcrypt)\n* [HKDF [RFC5869] Two-Step KDF (Java)](https://github.com/patrickfav/hkdf)\n\n# License\n\nCopyright 2018 Patrick Favre-Bulle\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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickfav%2Fsinglestep-kdf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatrickfav%2Fsinglestep-kdf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickfav%2Fsinglestep-kdf/lists"}