001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.hbase.security.token;
020
021import javax.crypto.SecretKey;
022
023import java.io.DataInput;
024import java.io.DataOutput;
025import java.io.IOException;
026import java.util.Arrays;
027
028import org.apache.yetus.audience.InterfaceAudience;
029import org.apache.hadoop.hbase.util.Bytes;
030import org.apache.hadoop.io.Writable;
031import org.apache.hadoop.io.WritableUtils;
032
033/**
034 * Represents a secret key used for signing and verifying authentication tokens
035 * by {@link AuthenticationTokenSecretManager}.
036 */
037@InterfaceAudience.Private
038public class AuthenticationKey implements Writable {
039  private int id;
040  private long expirationDate;
041  private SecretKey secret;
042
043  public AuthenticationKey() {
044    // for Writable
045  }
046
047  public AuthenticationKey(int keyId, long expirationDate, SecretKey key) {
048    this.id = keyId;
049    this.expirationDate = expirationDate;
050    this.secret = key;
051  }
052
053  public int getKeyId() {
054    return id;
055  }
056
057  public long getExpiration() {
058    return expirationDate;
059  }
060
061  public void setExpiration(long timestamp) {
062    expirationDate = timestamp;
063  }
064
065  SecretKey getKey() {
066    return secret;
067  }
068
069  @Override
070  public int hashCode() {
071    int result = id;
072    result = 31 * result + (int) (expirationDate ^ (expirationDate >>> 32));
073    result = 31 * result + ((secret == null) ? 0 : Arrays.hashCode(secret.getEncoded()));
074    return result;
075  }
076
077  @Override
078  public boolean equals(Object obj) {
079    if (obj == null || !(obj instanceof AuthenticationKey)) {
080      return false;
081    }
082    AuthenticationKey other = (AuthenticationKey)obj;
083    return id == other.getKeyId() &&
084        expirationDate == other.getExpiration() &&
085        (secret == null ? other.getKey() == null :
086            other.getKey() != null &&
087                Bytes.equals(secret.getEncoded(), other.getKey().getEncoded()));       
088  }
089
090  @Override
091  public String toString() {
092    StringBuilder buf = new StringBuilder();
093    buf.append("AuthenticationKey[ ")
094       .append("id=").append(id)
095       .append(", expiration=").append(expirationDate)
096       .append(" ]");
097    return buf.toString();
098  }
099
100  @Override
101  public void write(DataOutput out) throws IOException {
102    WritableUtils.writeVInt(out, id);
103    WritableUtils.writeVLong(out, expirationDate);
104    if (secret == null) {
105      WritableUtils.writeVInt(out, -1);
106    } else {
107      byte[] keyBytes = secret.getEncoded();
108      WritableUtils.writeVInt(out, keyBytes.length);
109      out.write(keyBytes);
110    }
111  }
112
113  @Override
114  public void readFields(DataInput in) throws IOException {
115    id = WritableUtils.readVInt(in);
116    expirationDate = WritableUtils.readVLong(in);
117    int keyLength = WritableUtils.readVInt(in);
118    if (keyLength < 0) {
119      secret = null;
120    } else {
121      byte[] keyBytes = new byte[keyLength];
122      in.readFully(keyBytes);
123      secret = AuthenticationTokenSecretManager.createSecretKey(keyBytes);
124    }
125  }
126}