Package com.github.zathrus_writer.commandsex.helpers

Source Code of com.github.zathrus_writer.commandsex.helpers.Authentication

package com.github.zathrus_writer.commandsex.helpers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;

import com.github.zathrus_writer.commandsex.CommandsEX;
import com.github.zathrus_writer.commandsex.SQLManager;

public class Authentication {
  private final static int ITERATION_NUMBER = 1000;
 
  public static void init(CommandsEX plugin){
    SQLManager.query((SQLManager.sqlType.equals("mysql") ? "" : "BEGIN; ") + "CREATE TABLE IF NOT EXISTS "+ SQLManager.prefix +"userinfo (id_user integer " + (SQLManager.sqlType.equals("mysql") ? "unsigned " : "") +"NOT NULL" + (SQLManager.sqlType.equals("mysql") ? " AUTO_INCREMENT" : "") +", player_name varchar(32) NOT NULL" + (SQLManager.sqlType.equals("mysql") ? "" : " COLLATE 'NOCASE'") + ", creation_date " + (SQLManager.sqlType.equals("mysql") ? "TIMESTAMP" : "DATETIME") + " NOT NULL DEFAULT CURRENT_TIMESTAMP, expiration_date " + (SQLManager.sqlType.equals("mysql") ? "TIMESTAMP" : "DATETIME") + " NOT NULL DEFAULT '0000-00-00 00:00:00', creator VARCHAR(32) NOT NULL, reason VARCHAR(120) DEFAULT NULL, active BOOLEAN NOT NULL DEFAULT '1', PRIMARY KEY (id_ban)" + (SQLManager.sqlType.equals("mysql") ? ", KEY player_name (player_name), KEY expiration_date (expiration_date), KEY active (active)" : "" ) + ")" + (SQLManager.sqlType.equals("mysql") ? " ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='holds ban records for players along with reasons and ban expiration times' AUTO_INCREMENT=1" : "") + (SQLManager.sqlType.equals("mysql") ? "" : "; CREATE INDEX IF NOT EXISTS player_name ON "+ SQLManager.prefix +"bans (player_name); CREATE INDEX IF NOT EXISTS expiration_date ON "+ SQLManager.prefix +"bans (expiration_date); CREATE INDEX IF NOT EXISTS active ON "+ SQLManager.prefix +"bans (active); COMMIT;"));
    for(int i=0; i< ALPHABET.length; i++){
            toInt[ALPHABET[i]]= i;
        }
  }

   /**
      * Authenticates the user with a given login and password
      * If password and/or login is null then always returns false.
      * If the user does not exist in the database returns false.
      * @param con Connection An open connection to a databse
      * @param login String The login of the user
      * @param password String The password of the user
      * @return boolean Returns true if the user is authenticated, false otherwise
      * @throws SQLException If the database is inconsistent or unavailable (
      *           (Two users with the same login, salt or digested password altered etc.)
      * @throws NoSuchAlgorithmException If the algorithm SHA-1 is not supported by the JVM
      */
     public boolean authenticate(Connection con, String login, String password)
             throws SQLException, NoSuchAlgorithmException{
         @SuppressWarnings("unused")
         boolean authenticated = false;
         PreparedStatement ps = null;
         ResultSet rs = null;
         try {
             boolean userExist = true;
             // INPUT VALIDATION
             if (login==null||password==null){
                 // TIME RESISTANT ATTACK
                 // Computation time is equal to the time needed by a legitimate user
                 userExist = false;
                 login="";
                 password="";
             }
  
             ps = con.prepareStatement("SELECT PASSWORD, SALT FROM CREDENTIAL WHERE LOGIN = ?");
             ps.setString(1, login);
             rs = ps.executeQuery();
             String digest, salt;
             if (rs.next()) {
                 digest = rs.getString("PASSWORD");
                 salt = rs.getString("SALT");
                 // DATABASE VALIDATION
                 if (digest == null || salt == null) {
                     throw new SQLException("Database inconsistant Salt or Digested Password altered");
                 }
                 if (rs.next()) { // Should not append, because login is the primary key
                     throw new SQLException("Database inconsistent two CREDENTIALS with the same LOGIN");
                 }
             } else { // TIME RESISTANT ATTACK (Even if the user does not exist the
                 // Computation time is equal to the time needed for a legitimate user
                 digest = "000000000000000000000000000=";
                 salt = "00000000000=";
                 userExist = false;
             }
  
             byte[] bDigest = base64ToByte(digest);
             byte[] bSalt = base64ToByte(salt);
  
             // Compute the new DIGEST
             byte[] proposedDigest = getHash(ITERATION_NUMBER, password, bSalt);
  
             return Arrays.equals(proposedDigest, bDigest) && userExist;
         } catch (IOException ex){
             throw new SQLException("Database inconsistant Salt or Digested Password altered");
         }
         finally{
             close(rs);
             close(ps);
         }
     }
  
  
  
     /**
      * Inserts a new user in the database
      * @param con Connection An open connection to a databse
      * @param login String The login of the user
      * @param password String The password of the user
      * @return boolean Returns true if the login and password are ok (not null and length(login)<=100
      * @throws SQLException If the database is unavailable
      * @throws NoSuchAlgorithmException If the algorithm SHA-1 or the SecureRandom is not supported by the JVM
   * @throws UnsupportedEncodingException
      */
     public boolean createUser(Connection con, String login, String password)
             throws SQLException, NoSuchAlgorithmException, UnsupportedEncodingException
     {
         PreparedStatement ps = null;
         try {
             if (login!=null&&password!=null&&login.length()<=100){
                 // Uses a secure Random not a simple Random
                 SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
                 // Salt generation 64 bits long
                 byte[] bSalt = new byte[8];
                 random.nextBytes(bSalt);
                 // Digest computation
                 byte[] bDigest = getHash(ITERATION_NUMBER,password,bSalt);
                 String sDigest = byteToBase64(bDigest);
                 String sSalt = byteToBase64(bSalt);
  
                 ps = con.prepareStatement("INSERT INTO CREDENTIAL (LOGIN, PASSWORD, SALT) VALUES (?,?,?)");
                 ps.setString(1,login);
                 ps.setString(2,sDigest);
                 ps.setString(3,sSalt);
                 ps.executeUpdate();
                 return true;
             } else {
                 return false;
             }
         } finally {
             close(ps);
         }
     }
  
  
     /**
      * From a password, a number of iterations and a salt,
      * returns the corresponding digest
      * @param iterationNb int The number of iterations of the algorithm
      * @param password String The password to encrypt
      * @param salt byte[] The salt
      * @return byte[] The digested password
      * @throws NoSuchAlgorithmException If the algorithm doesn't exist
   * @throws UnsupportedEncodingException
      */
     public byte[] getHash(int iterationNb, String password, byte[] salt) throws NoSuchAlgorithmException, UnsupportedEncodingException {
         MessageDigest digest = MessageDigest.getInstance("SHA-1");
         digest.reset();
         digest.update(salt);
         byte[] input = digest.digest(password.getBytes("UTF-8"));
         for (int i = 0; i < iterationNb; i++) {
             digest.reset();
             input = digest.digest(input);
         }
         return input;
     }
  
  
     public void creerTable(Connection con) throws SQLException{
         Statement st = null;
         try {
             st = con.createStatement();
             st.execute((SQLManager.sqlType.equals("mysql") ? "" : "BEGIN;") + "CREATE TABLE CREDENTIAL (LOGIN VARCHAR(100) PRIMARY KEY, PASSWORD VARCHAR(32) NOT NULL, SALT VARCHAR(32) NOT NULL)");
         } finally {
             close(st);
         }
     }
  
  
  
     /**
      * Closes the current statement
      * @param ps Statement
      */
     public void close(Statement ps) {
         if (ps!=null){
             try {
                 ps.close();
             } catch (SQLException ignore) {
             }
         }
     }
  
     /**
      * Closes the current resultset
      * @param ps Statement
      */
     public void close(ResultSet rs) {
         if (rs!=null){
             try {
                 rs.close();
             } catch (SQLException ignore) {
             }
         }
     }
  
    
     private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
     private static int[]  toInt   = new int[128];
  
     /**
      * From a base 64 representation, returns the corresponding byte[]
      * @author GeorgeK (http://stackoverflow.com/users/518568/georgek)
      * @param data String The base64 representation
      * @return byte[]
      * @throws IOException
      */
     public static byte[] base64ToByte(String data) throws IOException {
       int delta = data.endsWith( "==" ) ? 2 : data.endsWith( "=" ) ? 1 : 0;
         byte[] buffer = new byte[data.length()*3/4 - delta];
         int mask = 0xFF;
         int index = 0;
         for(int i=0; i< data.length(); i+=4){
             int c0 = toInt[data.charAt( i )];
             int c1 = toInt[data.charAt( i + 1)];
             buffer[index++]= (byte)(((c0 << 2) | (c1 >> 4)) & mask);
             if(index >= buffer.length){
                 return buffer;
             }
             int c2 = toInt[data.charAt( i + 2)];
             buffer[index++]= (byte)(((c1 << 4) | (c2 >> 2)) & mask);
             if(index >= buffer.length){
                 return buffer;
             }
             int c3 = toInt[data.charAt( i + 3 )];
             buffer[index++]= (byte)(((c2 << 6) | c3) & mask);
         }
         return buffer;
     }
  
     /**
      * From a byte[] returns a base 64 representation
      * @author GeorgeK (http://stackoverflow.com/users/518568/georgek)
      * @param data byte[]
      * @return String
      * @throws IOException
      */
     public static String byteToBase64(byte[] data) {
       int size = data.length;
       char[] ar = new char[((size + 2) / 3) * 4];
       int a = 0;
       int i=0;
       while(i < size){
           byte b0 = data[i++];
           byte b1 = (i < size) ? data[i++] : 0;
           byte b2 = (i < size) ? data[i++] : 0;
               int mask = 0x3F;
             ar[a++] = ALPHABET[(b0 >> 2) & mask];
             ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask];
             ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask];
             ar[a++] = ALPHABET[b2 & mask];
         }
         switch(size % 3){
             case 1: ar[--a= '=';
             case 2: ar[--a= '=';
         }
         return new String(ar);
  }
}
TOP

Related Classes of com.github.zathrus_writer.commandsex.helpers.Authentication

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.