Java tutorial
/** * The MIT License (MIT) * * Copyright (c) 2013 tojo * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.github.tojo.session.cookies; import static com.github.tojo.session.cookies.SessionInACookie.assertMinLength; import static com.github.tojo.session.cookies.SessionInACookie.assertNotNullAndEmpty; import java.security.InvalidKeyException; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.lang.ArrayUtils; /** * Default implementation of {@link SignatureStrategy}. * * @author github.com/tojo */ class SignatureStrategyDefaultImpl implements SignatureStrategy { static final String SHA_256 = "SHA-256"; static final int SIGNATURE_LENGTH = 32; static final String HMAC_SHA256 = "HmacSHA256"; private final Key key; /** * Constructor * * @param secret * Secret/password for signing of the session data. The password * must be at least 30 characters long and should contain special * characters. */ public SignatureStrategyDefaultImpl(byte[] secret) { try { this.key = buildKey(secret, HMAC_SHA256); } catch (NoSuchAlgorithmException e) { throw new InitializationException(e); } } @Override public byte[] sign(byte[] sessionData) { assertNotNullAndEmpty(sessionData); byte[] signature = null; try { Mac mac = Mac.getInstance(HMAC_SHA256); mac.init(key); signature = mac.doFinal(sessionData); } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new InitializationException(e); } byte[] signedSessionData = ArrayUtils.addAll(signature, sessionData); return signedSessionData; } @Override public byte[] validate(byte[] signedSessionData) throws SignatureException { assertNotNullAndEmpty(signedSessionData); assertMinLength(signedSessionData, SIGNATURE_LENGTH); byte[] signature = ArrayUtils.subarray(signedSessionData, 0, SIGNATURE_LENGTH); byte[] sessionData = ArrayUtils.subarray(signedSessionData, SIGNATURE_LENGTH, signedSessionData.length); byte[] newSignature = ArrayUtils.subarray(sign(sessionData), 0, SIGNATURE_LENGTH); if (!Arrays.equals(newSignature, signature)) { throw new SignatureException("Invalid signature!"); } return sessionData; } // ///////////////////////////////////////////////// // non-public API // ///////////////////////////////////////////////// private Key buildKey(byte[] key, String algorithmus) throws NoSuchAlgorithmException { assertNotNullAndEmpty(key); MessageDigest digester = MessageDigest.getInstance(SHA_256); digester.update(key); SecretKeySpec spec = new SecretKeySpec(digester.digest(), algorithmus); return spec; } }