/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.crypt; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import freenet.support.Logger; /** * Implements the HMAC Keyed Message Authentication function, as described in the draft FIPS * standard. */ public enum HMAC { SHA2_256("HmacSHA256", 32); final String algo; final int digestSize; HMAC(String name, int size) { this.algo = name; this.digestSize = size; } public static byte[] mac(HMAC hash, byte[] key, byte[] data) { if(key.length != hash.digestSize) throw new IllegalArgumentException("Wrong keysize! We're not doing key stretching "+ key.length+" expected "+hash.digestSize); SecretKeySpec signingKey = new SecretKeySpec(key, hash.algo); Mac mac; try { mac = Mac.getInstance(hash.algo); } catch (NoSuchAlgorithmException e) { Logger.error(HMAC.class, "No such AlgorithmException", e); throw new Error(e); } try { mac.init(signingKey); } catch (InvalidKeyException e) { Logger.error(HMAC.class, "Impossible InvalidKeyException", e); throw new Error(e); } return mac.doFinal(data); } public static boolean verify(HMAC hash, byte[] key, byte[] data, byte[] mac) { return MessageDigest.isEqual(mac, mac(hash, key, data)); } public static byte[] macWithSHA256(byte[] K, byte[] text) { return mac(HMAC.SHA2_256, K, text); } public static boolean verifyWithSHA256(byte[] K, byte[] text, byte[] mac) { return verify(HMAC.SHA2_256, K, text, mac); } }