Package org.kocakosm.pitaya.security

Source Code of org.kocakosm.pitaya.security.Passwords

/*----------------------------------------------------------------------------*
* This file is part of Pitaya.                                               *
* Copyright (C) 2012-2014 Osman KOCAK <kocakosm@gmail.com>                   *
*                                                                            *
* This program is free software: you can redistribute it and/or modify it    *
* under the terms of the GNU Lesser General Public License as published by   *
* the Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version.                                                 *
* This program is distributed in the hope that it will be useful, but        *
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public     *
* License for more details.                                                  *
* You should have received a copy of the GNU Lesser General Public License   *
* along with this program. If not, see <http://www.gnu.org/licenses/>.       *
*----------------------------------------------------------------------------*/

package org.kocakosm.pitaya.security;

import org.kocakosm.pitaya.charset.UTF8;
import org.kocakosm.pitaya.util.ByteBuffer;
import org.kocakosm.pitaya.util.Strings;

import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Random;

/**
* Passwords related utility functions.
*
* @author Osman KOCAK
*/
public final class Passwords
{
  private static final int R = 8;
  private static final int P = 1;
  private static final int N = 1 << 14;
  private static final int R_MIN = 8;
  private static final int P_MIN = 1;
  private static final int N_MIN = 1 << 14;
  private static final int SALT_LENGTH = 16;
  private static final int HASH_LENGTH = 32;
  private static final Random PRNG = new SecureRandom();
  private static final char[] ALPHABET = new char[] {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
  };

  /**
   * Generates a pseudo-random password (10 alphanumeric characters).
   *
   * @return a pseudo-random password.
   */
  public static String generate()
  {
    return Strings.random(10, PRNG, ALPHABET);
  }

  /**
   * Hashes the given password (using {@linkplain KDFs#scrypt SCrypt}).
   * Hashing parameters are appended to the returned result.
   *
   * @param password the password to hash.
   *
   * @return the hashed password.
   *
   * @throws NullPointerException if {@code password} is {@code null}.
   */
  public static byte[] hash(String password)
  {
    return hash(password, salt(), R, N, P);
  }

  /**
   * Verifies that the given password matches the hashed one.
   *
   * @param password the password to verify.
   * @param hash the hashed password.
   *
   * @return whether the given password matches the hashed one.
   *
   * @throws NullPointerException if one of the arguments is {@code null}.
   */
  public static boolean verify(String password, byte[] hash)
  {
    byte[] h = Arrays.copyOf(hash, HASH_LENGTH + SALT_LENGTH + 3);
    int n = 1 << (h[HASH_LENGTH + SALT_LENGTH] & 0xFF);
    int r = h[HASH_LENGTH + SALT_LENGTH + 1] & 0xFF;
    int p = h[HASH_LENGTH + SALT_LENGTH + 2] & 0xFF;
    if (n > N || n < N_MIN || r > R || r < R_MIN || p > P || p < P_MIN) {
      n = N;
      r = R;
      p = P;
    }
    byte[] salt = new byte[SALT_LENGTH];
    System.arraycopy(h, HASH_LENGTH, salt, 0, SALT_LENGTH);
    byte[] expected = hash(password, salt, r, n, p);
    int result = 0;
    for (int i = 0; i < h.length; i++) {
      result |= h[i] ^ expected[i];
    }
    return result == 0;
  }

  private static byte[] hash(String password, byte[] salt, int r, int n, int p)
  {
    KDF scrypt = KDFs.scrypt(r, n, p, HASH_LENGTH);
    ByteBuffer buf = new ByteBuffer(HASH_LENGTH + SALT_LENGTH + 3);
    buf.append(scrypt.deriveKey(UTF8.encode(password), salt));
    buf.append(salt);
    buf.append((byte) Math.round(Math.log(n) / Math.log(2)));
    buf.append((byte) r, (byte) p);
    return buf.toByteArray();
  }

  private static byte[] salt()
  {
    byte[] salt = new byte[SALT_LENGTH];
    PRNG.nextBytes(salt);
    return salt;
  }

  private Passwords()
  {
    /* ... */
  }
TOP

Related Classes of org.kocakosm.pitaya.security.Passwords

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.