linkSingle Step KDF (NIST SP 800-56C)

This is an implementation of the single-step key derivation function as described in NIST SP 800-56C revision 1, chapter 4. It is an unopinionated approach towards the subject, allowing all 3 options (message digest, hmac and kmac) as H function and leaving open the exact format of the fixedInfo parameter.

Download Build Status Javadocs Coverage Status Maintainability

This is a standalone, lightweight, simple to use, fully tested and stable implementation in Java. The code is compiled with Java 7 to be compatible with most Android versions as well as normal Java applications.


Add dependency to your pom.xml:


2 <groupId>at.favre.lib</groupId>

3 <artifactId>singlestep-kdf</artifactId>

4 <version>{latest-version}</version>


A very simple example:

1// a shared secret provided by your protocol

2byte[] sharedSecret = ...

3// a salt; if you don't have access to a salt, use salt-less SingleStepKdf.fromSha256() or similar

4byte[] salt = ...

5// other info to bind the key to the context, see the NIST spec for more detail

6byte[] otherInfo = "macKey".getBytes();

7byte[] keyMaterial = SingleStepKdf.fromHmacSha256().derive(sharedSecret, 32, salt, otherInfo);

8SecretKey secretKey = new SecretKeySpec(keyMaterial, "AES");

linkFull Example

NIST 800-56C specifies the KDF with an H-function which may be a hash, HMAC or KMAC.

linkUsing with Message Digest (Option 1)

Using Option 1, ie. H(x) = hash(x), where hash is an approved hash function. Note that when you use this option, the salt parameter is not supported. If you want to incorporate a salt just include it into the fixedInfo parameter. If you have no specific reason for choosing Option 1, I would always prefer Option 2 (HMAC) over this one.

1// a shared secret provided by your protocol

2byte[] sharedSecret = Bytes.random(16).array();

3// fixed info to bind the key to the context

4byte[] fixedInfo = "macKey".getBytes();

5// salt is not directly supported with message digest, you may include it in fixedInfo

6byte[] keyMaterial = SingleStepKdf.fromSha256().derive(sharedSecret, 32, fixedInfo);

7SecretKey secretKey = new SecretKeySpec(keyMaterial, "AES");

linkUsing with HMAC (Option 2)

Using Option 2, ie. H(x) = HMAC-hash(salt, x), where HMAC-hash is an implementation of the HMAC algorithm (as defined in FIPS 198) employing an approved hash function. A salt which serves as the HMAC key, and x (the input to H) is a bit string that serves as the HMAC "message". This library can use any Mac implementation. If no salt is provided, an empty array is internally initialized.

1byte[] keyMaterial = SingleStepKdf.fromHmacSha256().derive(sharedSecret, 32, salt, fixedInfo);

2 SecretKey secretKey = new SecretKeySpec(keyMaterial, "AES");

linkUsing with KMAC (Option 3)

KMAC is a MAC using SHA-3/Keccak. Unlike SHA-1 and SHA-2, Keccak does not have the length-extension weakness, hence does not need the HMAC nested construction. Instead, MAC computation can be performed by simply prepending the message with the key. Java has a SHA-3 implementation since version 9. This library is designed to support Java 7, so no default implementation is present for KMAC. It is probably quite easy to implement it yourself using either the HFunctionFactory.MacFactory or implementing yourself with HFunction.

linkUsing custom Message Digest / HMAC implementation

Default 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:

1// create instance with sha1 as backing hash function

2SingleStepKdf sha1Kdf = SingleStepKdf.from(new HFunctionFactory.Default.DigestFactory("SHA-1"));

3// create instance with HMAC-SHA1 as backing h function

4SingleStepKdf hmacSha1Kdf = SingleStepKdf.from(new HFunctionFactory.Default.DigestFactory("HmacSHA1"));

linkHow to use the Fixed-Info Parameter

A bit string of context-specific data that is appropriate for the relying key-establishment scheme. As its name suggests, the value of FixedInfo does not change during the execution of the process.

FixedInfo may, for example, include appropriately formatted representations of the values of salt and/or the output length. The inclusion of additional copies of the values of salt and the output length in FixedInfo would ensure that each block of derived keying material is affected by all of the information conveyed in OtherInput. See SP 800-56A and SP 800-56B for more detailed recommendations concerning the format and content of FixedInfo (also known as OtherInfo in earlier versions of those documents).


The artifacts are deployed to jcenter and Maven Central.


Add dependency to your pom.xml:


2 <groupId>at.favre.lib</groupId>

3 <artifactId>singlestep-kdf</artifactId>

4 <version>{latest-version}</version>



Add to your build.gradle module dependencies:

1compile group: 'at.favre.lib', name: 'singlestep-kdf', version: '{latest-version}'

linkLocal Jar

Grab jar from latest release.


The following is summarized and shortened version of NIST 800-56C Rev1 chapter about the single-step KDF:

Single 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 or SP 800-56B, 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).

Implementations of these one-step KDFs depend upon the choice of an auxiliary function H, which can be either:

  1. an approved hash function, denoted as hash, as defined in FIPS 180 or FIPS 202;
  2. HMAC with an approved hash function, hash, denoted as HMAC-hash, and defined in FIPS 198; or
  3. a KMAC variant, as defined in SP 800-185. H shall be chosen in accordance with the selection requirements specified in 800-56C Rev1/Section 7.

When 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):

Given 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).

This 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.

linkTwo Step Key Derivation Function

NIST 800-56C Rev1 also describes a two step kdf with a extract and expand phase. The most prominent implementation of it is HKDF (RFC5869). A java implementation of it can be found here.

linkTest Vectors

Unfortunately it seems that the NIST did not provide any official test vectors (see this post). This implementation ist tested against the code snippets posted here. Additionally I released my own test vectors in the wiki so you could test against another possible already existing implementation.

linkSecurity Relevant Information

linkOWASP Dependency Check

This project uses the 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. The build will fail if any issue is found.

linkDigital Signatures

linkSigned Jar

The provided JARs in the Github release page are signed with my private key:

1CN=Patrick Favre-Bulle, OU=Private, O=PF Github Open Source, L=Vienna, ST=Vienna, C=AT

2Validity: Thu Sep 07 16:40:57 SGT 2017 to: Fri Feb 10 16:40:57 SGT 2034

3SHA1: 06:DE:F2:C5:F7:BC:0C:11:ED:35:E2:0F:B1:9F:78:99:0F:BE:43:C4

4SHA256: 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

Use the jarsigner tool (found in your $JAVA_HOME/bin folder) folder to verify.

linkSigned Commits

All tags and commits by me are signed with git with my private key:

1GPG key ID: 4FDF85343912A3AB

2Fingerprint: 2FB392FB05158589B767960C4FDF85343912A3AB


linkJar Sign

If you want to jar sign you need to provide a file keystore.jks in the root folder with the correct credentials set in environment variables ( OPENSOURCE_PROJECTS_KS_PW and OPENSOURCE_PROJECTS_KEY_PW); alias is set as pfopensource.

If you want to skip jar signing just change the skip configuration in the pom.xml jar sign plugin to true:


linkBuild with Maven

Use maven wrapper to create a jar including all dependencies

1./mvnw clean install

linkCheckstyle Config File

This project uses my common-parent which centralized a lot of the plugin versions aswell as providing the checkstyle config rules. Specifically they are maintained in checkstyle-config. Locally the files will be copied after you mvnw install into your target folder and is called target/checkstyle-checker.xml. So if you use a plugin for your IDE, use this file as your local configuration.

linkTech Stack


Copyright 2018 Patrick Favre-Bulle

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at


Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Single Step KDF (NIST SP 800-56C)QuickstartFull ExampleUsing with Message Digest (Option 1)Using with HMAC (Option 2)Using with KMAC (Option 3)Using custom Message Digest / HMAC implementationHow to use the Fixed-Info ParameterDownloadMavenGradleLocal JarDescriptionTwo Step Key Derivation FunctionTest VectorsSecurity Relevant InformationOWASP Dependency CheckDigital SignaturesSigned JarSigned CommitsBuildJar SignBuild with MavenCheckstyle Config FileTech StackRelated LibrariesLicense



Patrick Favre-Bulle 2020