package org.multibit.mbm.auth.hmac; import com.google.common.base.Charsets; import com.google.common.base.Objects; import org.multibit.mbm.auth.Authority; import java.security.MessageDigest; import static com.google.common.base.Preconditions.checkNotNull; /** * <p>Value object to provide the following to {@link org.multibit.mbm.auth.hmac.HmacAuthenticator}:</p> * <ul> * <li>Storage of the necessary credentials for HMAC authentication</li> * </ul> * * @since 0.0.1 */ public class HmacServerCredentials { private final String apiKey; private final String digest; private final String canonicalRepresentation; private final String algorithm; private final Authority[] requiredAuthorities; /** * @param algorithm The algorithm used for computing the digest (e.g. "HmacSHA1", "HmacSHA256", "HmacSHA512") * @param apiKey The API key used for looking up the shared secret key associated with the user * @param digest The digest of (contents + shared secret key) * @param canonicalRepresentation The canonical representation of the request that was signed * @param requiredAuthorities The authorities required to authenticate (provided by the {@link org.multibit.mbm.auth.annotation.RestrictedTo} annotation) */ public HmacServerCredentials( String algorithm, String apiKey, String digest, String canonicalRepresentation, Authority[] requiredAuthorities) { this.algorithm = checkNotNull(algorithm); this.apiKey = checkNotNull(apiKey); this.digest = checkNotNull(digest); this.canonicalRepresentation = checkNotNull(canonicalRepresentation); this.requiredAuthorities = checkNotNull(requiredAuthorities); } /** * @return The name of the algorithm used to compute the digest */ public String getAlgorithm() { return algorithm; } /** * @return The public API key (allows look up of shared secret key) */ public String getApiKey() { return apiKey; } /** * @return The digest of the request content and shared secret key */ public String getDigest() { return digest; } /** * @return The canonical representation of the request that was signed */ public String getCanonicalRepresentation() { return canonicalRepresentation; } /** * @return The authorities required to successfully authenticate */ public Authority[] getRequiredAuthorities() { return requiredAuthorities; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if ((obj == null) || (getClass() != obj.getClass())) { return false; } final HmacServerCredentials that = (HmacServerCredentials) obj; final byte[] thisBytes = digest.getBytes(Charsets.UTF_8); final byte[] thatBytes = that.digest.getBytes(Charsets.UTF_8); return apiKey.equals(that.apiKey) && MessageDigest.isEqual(thisBytes, thatBytes); } @Override public int hashCode() { return (31 * apiKey.hashCode()) + digest.hashCode(); } @Override public String toString() { return Objects.toStringHelper(this) .add("apiKey", apiKey) .add("digest", digest) .add("contents", canonicalRepresentation) .add("authorities", requiredAuthorities) .toString(); } }