Java tutorial
/* * Copyright 2013-2016 Amazon.com, * Inc. or its affiliates. All Rights Reserved. * * Licensed under the Amazon Software License (the "License"). * You may not use this file except in compliance with the * License. A copy of the License is located at * * http://aws.amazon.com/asl/ * * or in the "license" file accompanying this file. This file is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, express or implied. See the License * for the specific language governing permissions and * limitations under the License. */ package io.fineo.client.auth.cognito; import com.amazonaws.util.StringUtils; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; import javax.crypto.spec.SecretKeySpec; /** * Utility class for all HKDF operations. */ public final class Hkdf { private static final byte[] EMPTY_ARRAY = new byte[0]; private final String algorithm; private SecretKey prk = null; public static Hkdf getInstance(String algorithm) throws NoSuchAlgorithmException { Mac mac = Mac.getInstance(algorithm); return new Hkdf(algorithm); } public void init(byte[] ikm) { this.init(ikm, (byte[]) null); } public void init(byte[] ikm, byte[] salt) { byte[] realSalt = salt == null ? EMPTY_ARRAY : (byte[]) salt.clone(); byte[] rawKeyMaterial = EMPTY_ARRAY; try { Mac e = Mac.getInstance(this.algorithm); if (realSalt.length == 0) { realSalt = new byte[e.getMacLength()]; Arrays.fill(realSalt, (byte) 0); } e.init(new SecretKeySpec(realSalt, this.algorithm)); rawKeyMaterial = e.doFinal(ikm); SecretKeySpec key = new SecretKeySpec(rawKeyMaterial, this.algorithm); Arrays.fill(rawKeyMaterial, (byte) 0); this.unsafeInitWithoutKeyExtraction(key); } catch (GeneralSecurityException var10) { throw new RuntimeException("Unexpected exception", var10); } finally { Arrays.fill(rawKeyMaterial, (byte) 0); } } public void unsafeInitWithoutKeyExtraction(SecretKey rawKey) throws InvalidKeyException { if (!rawKey.getAlgorithm().equals(this.algorithm)) { throw new InvalidKeyException( "Algorithm for the provided key must match the algorithm for this Hkdf. Expected " + this.algorithm + " but found " + rawKey.getAlgorithm()); } else { this.prk = rawKey; } } private Hkdf(String algorithm) { if (!algorithm.startsWith("Hmac")) { throw new IllegalArgumentException( "Invalid algorithm " + algorithm + ". Hkdf may only be used with Hmac algorithms."); } else { this.algorithm = algorithm; } } public byte[] deriveKey(String info, int length) throws IllegalStateException { return this.deriveKey(info != null ? info.getBytes(StringUtils.UTF8) : null, length); } public byte[] deriveKey(byte[] info, int length) throws IllegalStateException { byte[] result = new byte[length]; try { this.deriveKey(info, length, result, 0); return result; } catch (ShortBufferException var5) { throw new RuntimeException(var5); } } public void deriveKey(byte[] info, int length, byte[] output, int offset) throws ShortBufferException, IllegalStateException { this.assertInitialized(); if (length < 0) { throw new IllegalArgumentException("Length must be a non-negative value."); } else if (output.length < offset + length) { throw new ShortBufferException(); } else { Mac mac = this.createMac(); if (length > 255 * mac.getMacLength()) { throw new IllegalArgumentException( "Requested keys may not be longer than 255 times the underlying HMAC length."); } else { byte[] t = EMPTY_ARRAY; try { int loc = 0; for (byte i = 1; loc < length; ++i) { mac.update(t); mac.update(info); mac.update(i); t = mac.doFinal(); for (int x = 0; x < t.length && loc < length; ++loc) { output[loc] = t[x]; ++x; } } } finally { Arrays.fill(t, (byte) 0); } } } } private Mac createMac() { try { Mac ex = Mac.getInstance(this.algorithm); ex.init(this.prk); return ex; } catch (NoSuchAlgorithmException var2) { throw new RuntimeException(var2); } catch (InvalidKeyException var3) { throw new RuntimeException(var3); } } private void assertInitialized() throws IllegalStateException { if (this.prk == null) { throw new IllegalStateException("Hkdf has not been initialized"); } } }