/** * Generates a new KeyIdentifier and sets that to be the current key being used. * @return A new KeyIdentifier. */ protected final KeyIdentifier generateKey() { Random rand = new Random(); int nextId; do { nextId = rand.nextInt(Integer.MAX_VALUE); } while (hasKey(nextId)); long now = System.currentTimeMillis(); SecretKey nextKey = keyGenerator.generateKey(); KeyIdentifier keyIdentifier = new KeyIdentifier(nextKey, nextId, keyExpirationPeriod > 0 ? (now + keyExpirationPeriod) : Long.MAX_VALUE); addKey(keyIdentifier); this.currentKey = keyIdentifier; LOG.info("Changed current key to {}", currentKey); return keyIdentifier; }
@Override public final void startUp() throws NoSuchAlgorithmException, IOException { keyGenerator = KeyGenerator.getInstance(keyAlgo); keyGenerator.init(keyLength); threadLocalMac = new ThreadLocal<Mac>() { @Override public Mac initialValue() { try { return Mac.getInstance(keyAlgo); } catch (NoSuchAlgorithmException nsae) { throw new IllegalArgumentException("Unknown algorithm for secret keys: " + keyAlgo); } } }; doInit(); }
/** * Computes a digest for the given input message, using the key identified by the given ID. * @param keyId Identifier of the secret key to use. * @param message The data over which we should generate a digest. * @return The computed digest. * @throws InvalidKeyException If the input {@code keyId} does not match a known key or the key is not accepted * by the internal {@code Mac} implementation. */ protected final byte[] generateMAC(int keyId, byte[] message) throws InvalidKeyException { KeyIdentifier key = getKey(keyId); if (key == null) { throw new InvalidKeyException("No key found for ID " + keyId); } return generateMAC(key.getKey(), message); }
@Override public final DigestId generateMAC(byte[] message) throws InvalidKeyException { KeyIdentifier signingKey = currentKey; byte[] digest = generateMAC(signingKey.getKey(), message); return new DigestId(signingKey.getKeyId(), digest); }
@Override public final <T> void validateMAC(Codec<T> codec, Signed<T> signedMessage) throws InvalidDigestException, InvalidKeyException { try { byte[] newDigest = generateMAC(signedMessage.getKeyId(), codec.encode(signedMessage.getMessage())); if (!Bytes.equals(signedMessage.getDigestBytes(), newDigest)) { throw new InvalidDigestException("Token signature is not valid!"); } } catch (IOException ioe) { throw Throwables.propagate(ioe); } }