@Override
 public boolean equals(Object obj) {
   if (obj == null || !(obj instanceof AuthenticationKey)) {
     return false;
   }
   AuthenticationKey other = (AuthenticationKey) obj;
   return id == other.getKeyId()
       && expirationDate == other.getExpiration()
       && (secret == null
           ? other.getKey() == null
           : other.getKey() != null
               && Bytes.equals(secret.getEncoded(), other.getKey().getEncoded()));
 }
 @Override
 protected byte[] createPassword(AuthenticationTokenIdentifier identifier) {
   long now = EnvironmentEdgeManager.currentTime();
   AuthenticationKey secretKey = currentKey;
   identifier.setKeyId(secretKey.getKeyId());
   identifier.setIssueDate(now);
   identifier.setExpirationDate(now + tokenMaxLifetime);
   identifier.setSequenceNumber(tokenSeq.getAndIncrement());
   return createPassword(identifier.getBytes(), secretKey.getKey());
 }
 @Override
 public byte[] retrievePassword(AuthenticationTokenIdentifier identifier) throws InvalidToken {
   long now = EnvironmentEdgeManager.currentTime();
   if (identifier.getExpirationDate() < now) {
     throw new InvalidToken("Token has expired");
   }
   AuthenticationKey masterKey = allKeys.get(identifier.getKeyId());
   if (masterKey == null) {
     throw new InvalidToken("Unknown master key for token (id=" + identifier.getKeyId() + ")");
   }
   // regenerate the password
   return createPassword(identifier.getBytes(), masterKey.getKey());
 }