{"id":21513237,"url":"https://github.com/patrickfav/hkdf","last_synced_at":"2025-08-19T21:31:45.656Z","repository":{"id":26538545,"uuid":"105349305","full_name":"patrickfav/hkdf","owner":"patrickfav","description":"A standalone Java 7 implementation of HMAC-based key derivation function (HKDF) defined in RFC 5869 first described by Hugo Krawczyk. HKDF follows the \"extract-then-expand\" paradigm which is compatible to NIST 800-56C Rev. 1 two step KDF","archived":false,"fork":false,"pushed_at":"2024-02-12T23:01:40.000Z","size":2901,"stargazers_count":67,"open_issues_count":3,"forks_count":9,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-12-07T09:50:25.671Z","etag":null,"topics":["800-56c","android-compatibility","cryptography","hash","hkdf","hmac","hmac-sha1","hmac-sha256","hmac-sha512","java","java7","jdk7","kdf","key-derivation-function","nist","rfc5869","two-step-key-derivation"],"latest_commit_sha":null,"homepage":"https://favr.dev/opensource/hkdf","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":"2017-09-30T06:57:47.000Z","updated_at":"2024-11-20T02:54:44.000Z","dependencies_parsed_at":"2022-09-02T22:01:12.842Z","dependency_job_id":null,"html_url":"https://github.com/patrickfav/hkdf","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fhkdf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fhkdf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fhkdf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fhkdf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patrickfav","download_url":"https://codeload.github.com/patrickfav/hkdf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230367928,"owners_count":18215338,"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":["800-56c","android-compatibility","cryptography","hash","hkdf","hmac","hmac-sha1","hmac-sha256","hmac-sha512","java","java7","jdk7","kdf","key-derivation-function","nist","rfc5869","two-step-key-derivation"],"created_at":"2024-11-23T22:55:06.903Z","updated_at":"2024-12-19T03:10:00.053Z","avatar_url":"https://github.com/patrickfav.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HMAC-based Key Derivation Function (HKDF) RFC 5869\n\n[Hashed Message Authentication Code](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code) (HMAC)-based\nkey derivation function ([HKDF](https://en.wikipedia.org/wiki/HKDF)), can be used as a building block in various\nprotocols and applications. The [key derivation function](https://en.wikipedia.org/wiki/Key_derivation_function) (KDF)\nis intended to support a wide range of applications and requirements, and is conservative in its use\nof [cryptographic hash functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function). It is likely to\nhave [better security properties](https://crypto.stackexchange.com/questions/13232/how-is-hkdf-expand-better-than-a-simple-hash)\nthan KDF's based on just a hash functions alone. See [RFC 5869](https://tools.ietf.org/html/rfc5869) for full detail.\nHKDF specifies a version of\nthe [NIST Special Publication 800-56C](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr1.pdf) \"\nTwo-Step Key Derivation\" scheme.\n\n[![Maven Central](https://img.shields.io/maven-central/v/at.favre.lib/hkdf)](https://mvnrepository.com/artifact/at.favre.lib/hkdf)\n[![Github Actions](https://github.com/patrickfav/hkdf/actions/workflows/build_deploy.yml/badge.svg)](https://github.com/patrickfav/hkdf/actions)\n[![Javadocs](https://www.javadoc.io/badge/at.favre.lib/hkdf.svg)](https://www.javadoc.io/doc/at.favre.lib/hkdf)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=patrickfav_hkdf\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=patrickfav_hkdf)\n[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=patrickfav_hkdf\u0026metric=security_rating)](https://sonarcloud.io/summary/new_code?id=patrickfav_hkdf)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=patrickfav_hkdf\u0026metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=patrickfav_hkdf)\n\nThis is a standalone, lightweight, simple to use, fully tested and stable implementation in Java. The code is compiled\nwith target [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. It passes all test vectors\nfrom [RFC 5869 Appendix A.](https://tools.ietf.org/html/rfc5869#appendix-A)\n\n## Quickstart\n\nAdd dependency to your `pom.xml` ([check latest release](https://github.com/patrickfav/hkdf/releases)):\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eat.favre.lib\u003c/groupId\u003e\n    \u003cartifactId\u003ehkdf\u003c/artifactId\u003e\n    \u003cversion\u003e{latest-version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nA very simple example:\n\n```java\nbyte[] pseudoRandomKey = HKDF.fromHmacSha256().extract(null, lowEntropyInput);\nbyte[] outputKeyingMaterial = HKDF.fromHmacSha256().expand(pseudoRandomKey, null, 64);\n```\n\n### Full Example\n\nThis example creates a high-quality [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) secret key and initialization vector from a shared secret calculated by a [key agreement](https://en.wikipedia.org/wiki/Key-agreement_protocol) protocol and encrypts with [CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#CBC) block mode:\n\n```java\n//if no dynamic salt is available, a static salt is better than null\nbyte[] staticSalt32Byte = new byte[]{(byte) 0xDA, (byte) 0xAC, 0x3E, 0x10, 0x55, (byte) 0xB5, (byte) 0xF1, 0x3E, 0x53, (byte) 0xE4, 0x70, (byte) 0xA8, 0x77, 0x79, (byte) 0x8E, 0x0A, (byte) 0x89, (byte) 0xAE, (byte) 0x96, 0x5F, 0x19, 0x5D, 0x53, 0x62, 0x58, (byte) 0x84, 0x2C, 0x09, (byte) 0xAD, 0x6E, 0x20, (byte) 0xD4};\n\n//example input\nbyte[] sharedSecret = ...;\n\nHKDF hkdf = HKDF.fromHmacSha256();\n\n//extract the \"raw\" data to create output with concentrated entropy\nbyte[] pseudoRandomKey = hkdf.extract(staticSalt32Byte, sharedSecret);\n\n//create expanded bytes for e.g. AES secret key and IV\nbyte[] expandedAesKey = hkdf.expand(pseudoRandomKey, \"aes-key\".getBytes(StandardCharsets.UTF_8), 16);\nbyte[] expandedIv = hkdf.expand(pseudoRandomKey, \"aes-iv\".getBytes(StandardCharsets.UTF_8), 16);\n\n//Example boilerplate encrypting a simple string with created key/iv\nSecretKey key = new SecretKeySpec(expandedAesKey, \"AES\"); //AES-128 key\nCipher cipher = Cipher.getInstance(\"AES/CBC/PKCS5Padding\");\ncipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(expandedIv));\nbyte[] encrypted = cipher.doFinal(\"my secret message\".getBytes(StandardCharsets.UTF_8));\n```\n\n_Note_: HKDF is not suited for password-based key derivation, since it has no key stretching property. Use something like [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) or [bcrpyt](https://github.com/patrickfav/bcrypt) for that.\n\n### Using custom HMAC implementation\n\n```java\n//don't use md5, this is just an example\nHKDF hkdfMd5 = HKDF.from(new HkdfMacFactory.Default(\"HmacMD5\", 16, Security.getProvider(\"SunJCE\")));\n\nbyte[] lowEntropyInput = new byte[]{0x62, 0x58, (byte) 0x84, 0x2C};\nbyte[] outputKeyingMaterial = hkdfMd5.extractAndExpand(null, lowEntropyInput null, 32);\n```\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\u003ehkdf\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: 'hkdf', version: '{latest-version}'\n\n### Local Jar\n\n[Grab jar from latest release.](https://github.com/patrickfav/hkdf/releases/latest)\n\n\n## Description\n\nFor the full description see the [RFC 5869](https://tools.ietf.org/html/rfc5869). For\nan in-depth discussion about the security considerations [see the Paper \"Cryptographic Extraction and Key Derivation: The HKDF Scheme (2010)\" by Hugo Krawczyk](https://eprint.iacr.org/2010/264). The following\nis a summary of the 2 sources above. If there seems to be a contradiction, the original\nsources are always correct over this.\n\n### Extract and Expand\n\nHKDF follows the \"extract-then-expand\" paradigm, where the KDF logically consists of two modules.\n\n1. To \"extract\" (condense/blend) entropy from a larger random source to provide a more uniformly unbiased and higher entropy but smaller output. This is done by utilising the diffusion properties of cryptographic MACs.\n2. To \"expand\" the generated output of an already reasonably random input such as an existing shared key into a larger cryptographically independent output, thereby producing multiple keys deterministically from that initial shared key, so that the same process may produce those same secret keys safely on multiple devices, as long as the same inputs are utilised.\n\nNote that some existing KDF specifications, such as NIST Special Publication 800-56A, NIST Special Publication 800-108 and IEEE Standard 1363a-2004, either only consider the second stage (expanding a pseudorandom key), or do not explicitly differentiate between the \"extract\" and \"expand\" stages, often resulting in design shortcomings.  The goal of this HKDF is to accommodate a wide range of KDF requirements while minimizing the assumptions about the underlying hash function.\n\n### Use Cases\n\nHKDF is intended for use in a wide variety of KDF applications. Some applications _will not be able_ to use HKDF \"as-is\" due to specific operational requirements. One significant example is the derivation of cryptographic keys from a source of low entropy, such as a user's password. In the case of _password-based KDFs_, a main goal is to slow down dictionary attacks. HKDF naturally accommodates the use of salt; _however, a slowing down mechanism is not part of this specification_. Therefore, for a user's password, other KDFs might be considered like: [PKDF2](https://en.wikipedia.org/wiki/PBKDF2), [bcryt](https://github.com/patrickfav/bcrypt), [scrypt](https://en.wikipedia.org/wiki/Scrypt) or [Argon2](https://github.com/P-H-C/phc-winner-argon2) which are all designed to be computationally intensive.\n\n#### Key Derivation\n\nThe following examples are from [RFC5869 Section 4](https://tools.ietf.org/html/rfc5869#section-4):\n\n* The derivation of cryptographic keys from a shared Diffie-Hellman value in a key-agreement protocol.\n* The derivation of symmetric keys from a hybrid public-key encryption scheme.\n* Key derivation for key-wrapping mechanisms.\n\n##### Creating multiple keys from a single input\n\nThe expand phase includes an \"info\" parameter which should be used to create\nmultiple key material from a single PRK source. For example a Secret Key and\nIV from a shared Diffie-Hellman Value.\n\n#### Pseudorandom number generator (PRNG)\n\nThese two functions may also be combined and used to form a PRNG to improve a random number generator's potentially-biased output, as well as protect it from analysis and help defend the random number generation from malicious inputs.\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 the 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 (+ [errorprone](https://github.com/google/error-prone) static analyzer)\n* Maven\n\n## HKDF Implementations in Java\n\n* [Mozilla: sync-crypto](https://github.com/mozilla-services/sync-crypto/blob/master/src/main/java/org/mozilla/android/sync/crypto/HKDF.java)\n* [WhisperSystems: libsignal-protocol-java](https://github.com/WhisperSystems/libsignal-protocol-java/blob/master/java/src/main/java/org/whispersystems/libsignal/kdf/HKDF.java)\n* [Square: keywhiz](https://github.com/square/keywhiz/blob/master/hkdf/src/main/java/keywhiz/hkdf/Hkdf.java)\n* [Bouncy Castle](https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java)\n* [Google Tink](https://github.com/google/tink/blob/6625fcf2cfc3f56fc8babbb0f0388a5983fab65c/java/src/main/java/com/google/crypto/tink/subtle/Hkdf.java)\n\n## Related Libraries\n\n* [BCyrpt Password Hash Function (Java)](https://github.com/patrickfav/bcrypt)\n* [Single Step KDF [NIST SP 800-56C] (Java)](https://github.com/patrickfav/singlestep-kdf)\n\n# License\n\nCopyright 2017 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%2Fhkdf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatrickfav%2Fhkdf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickfav%2Fhkdf/lists"}