// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.mail;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Mac;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

/**
 * Utility function to compute and verify XSRF tokens.
 *
 * <p>{@link SignedTokenEmailTokenVerifier} uses this class to verify tokens appearing in the custom
 * <code>xsrfKey
 * </code> JSON request property. The tokens protect against cross-site request forgery by depending
 * upon the browser's security model. The classic browser security model prohibits a script from
 * site A from reading any data received from site B. By sending unforgeable tokens from the server
 * and asking the client to return them to us, the client script must have had read access to the
 * token at some point and is therefore also from our server.
 */
public class SignedToken {
  private static final int INT_SZ = 4;
  private static final String MAC_ALG = "HmacSHA1";

  /**
   * Generate a random key for use with the XSRF library.
   *
   * @return a new private key, base 64 encoded.
   */
  public static String generateRandomKey() {
    final byte[] r = new byte[26];
    new SecureRandom().nextBytes(r);
    return encodeBase64(r);
  }

  private final int maxAge;
  private final SecretKeySpec key;
  private final SecureRandom rng;
  private final int tokenLength;

  /**
   * Create a new utility, using the specific key.
   *
   * @param age the number of seconds a token may remain valid.
   * @param keyBase64 base 64 encoded representation of the key.
   * @throws XsrfException the JVM doesn't support the necessary algorithms.
   */
  public SignedToken(final int age, final String keyBase64) throws XsrfException {
    maxAge = age > 5 ? age / 5 : age;
    key = new SecretKeySpec(decodeBase64(keyBase64), MAC_ALG);
    rng = new SecureRandom();
    tokenLength = 2 * INT_SZ + newMac().getMacLength();
  }

  /**
   * Generate a new signed token.
   *
   * @param text the text string to sign. Typically this should be some user-specific string, to
   *     prevent replay attacks. The text must be safe to appear in whatever context the token
   *     itself will appear, as the text is included on the end of the token.
   * @return the signed token. The text passed in <code>text</code> will appear after the first ','
   *     in the returned token string.
   * @throws XsrfException the JVM doesn't support the necessary algorithms.
   */
  String newToken(final String text) throws XsrfException {
    final int q = rng.nextInt();
    final byte[] buf = new byte[tokenLength];
    encodeInt(buf, 0, q);
    encodeInt(buf, INT_SZ, now() ^ q);
    computeToken(buf, text);
    return encodeBase64(buf) + '$' + text;
  }

  /**
   * Validate a returned token.
   *
   * @param tokenString a token string previously created by this class.
   * @param text text that must have been used during {@link #newToken(String)} in order for the
   *     token to be valid. If null the text will be taken from the token string itself.
   * @return true if the token is valid; false if the token is null, the empty string, has expired,
   *     does not match the text supplied, or is a forged token.
   * @throws XsrfException the JVM doesn't support the necessary algorithms to generate a token.
   *     XSRF services are simply not available.
   */
  ValidToken checkToken(final String tokenString, final String text) throws XsrfException {
    if (tokenString == null || tokenString.length() == 0) {
      return null;
    }

    final int s = tokenString.indexOf('$');
    if (s <= 0) {
      return null;
    }

    final String recvText = tokenString.substring(s + 1);
    final byte[] in;
    try {
      in = decodeBase64(tokenString.substring(0, s));
    } catch (RuntimeException e) {
      return null;
    }
    if (in.length != tokenLength) {
      return null;
    }

    final int q = decodeInt(in, 0);
    final int c = decodeInt(in, INT_SZ) ^ q;
    final int n = now();
    if (maxAge > 0 && Math.abs(c - n) > maxAge) {
      return null;
    }

    final byte[] gen = new byte[tokenLength];
    System.arraycopy(in, 0, gen, 0, 2 * INT_SZ);
    computeToken(gen, text != null ? text : recvText);
    if (!Arrays.equals(gen, in)) {
      return null;
    }

    return new ValidToken(maxAge > 0 && c + (maxAge >> 1) <= n, recvText);
  }

  private void computeToken(final byte[] buf, final String text) throws XsrfException {
    final Mac m = newMac();
    m.update(buf, 0, 2 * INT_SZ);
    m.update(toBytes(text));
    try {
      m.doFinal(buf, 2 * INT_SZ);
    } catch (ShortBufferException e) {
      throw new XsrfException("Unexpected token overflow", e);
    }
  }

  private Mac newMac() throws XsrfException {
    try {
      final Mac m = Mac.getInstance(MAC_ALG);
      m.init(key);
      return m;
    } catch (NoSuchAlgorithmException e) {
      throw new XsrfException(MAC_ALG + " not supported", e);
    } catch (InvalidKeyException e) {
      throw new XsrfException("Invalid private key", e);
    }
  }

  private static int now() {
    return (int) (System.currentTimeMillis() / 5000L);
  }

  private static byte[] decodeBase64(final String s) {
    return Base64.decodeBase64(toBytes(s));
  }

  private static String encodeBase64(final byte[] buf) {
    return toString(Base64.encodeBase64(buf));
  }

  private static void encodeInt(final byte[] buf, final int o, final int v) {
    int _v = v;
    buf[o + 3] = (byte) _v;
    _v >>>= 8;

    buf[o + 2] = (byte) _v;
    _v >>>= 8;

    buf[o + 1] = (byte) _v;
    _v >>>= 8;

    buf[o] = (byte) _v;
  }

  private static int decodeInt(final byte[] buf, final int o) {
    int r = buf[o] << 8;

    r |= buf[o + 1] & 0xff;
    r <<= 8;

    r |= buf[o + 2] & 0xff;
    return (r << 8) | (buf[o + 3] & 0xff);
  }

  private static byte[] toBytes(final String s) {
    final byte[] r = new byte[s.length()];
    for (int k = r.length - 1; k >= 0; k--) {
      r[k] = (byte) s.charAt(k);
    }
    return r;
  }

  private static String toString(final byte[] b) {
    final StringBuilder r = new StringBuilder(b.length);
    for (int i = 0; i < b.length; i++) {
      r.append((char) b[i]);
    }
    return r.toString();
  }
}
