/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package framework.beans.security.passwords;
import framework.generic.ClipsServerConstants;
import framework.generic.ClipsServerException;
import java.io.Serializable;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.util.Arrays;
/**
*
* @author axe
*/
public class SessionPassword implements Serializable {
private static final int constRndSequenceLength = 64;
private static final int floatRndSequenceLength = 64;
private PrivateKey privateKey = null;
private PasswordEncryptorImpl encryptor = null;
/**
*
* @param useRSA
*/
public SessionPassword(boolean useRSA) {
SecureRandom r = new SecureRandom();
byte salt[] = new byte[constRndSequenceLength + r.nextInt(floatRndSequenceLength)];
r.nextBytes(salt);
KeyPair myPair = null;
if(useRSA) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048, r);
myPair = kpg.generateKeyPair();
privateKey = myPair.getPrivate();
} catch(Exception ex) {
//do nothing, just live keys null
}
}
encryptor = new PasswordEncryptorImpl(myPair != null ? myPair.getPublic() : null, salt);
}
/**
*
* @param encryption
* @param correctPassword
* @return
* @throws ClipsServerException
*/
public boolean verifyPassword(byte encryption[], char[] correctPassword)
throws ClipsServerException {
if(privateKey != null) {
return Arrays.equals(decryptPassword(encryption), correctPassword);
}
return verifyHash(encryption, SessionPassword.getPasswordHash(correctPassword));
}
public char[] decryptPassword(byte encryption[]) throws ClipsServerException {
return encryptor.decryptPasswd(encryption, privateKey);
}
/**
*
* @param encryption
* @param correctPasswordHash
* @return
* @throws framework.generic.ClipsServerException
*/
public boolean verifyHash(byte encryption[], byte[] correctPasswordHash)
throws ClipsServerException {
if(privateKey != null) {
char passwd[] = encryptor.decryptPasswd(encryption, privateKey);
byte[] passwdHash = SessionPassword.getPasswordHash(passwd);
return Arrays.equals(passwdHash, correctPasswordHash);
}
byte[] passwdHash = SessionPassword.getSaltHash(correctPasswordHash, encryptor.salt);
return MessageDigest.isEqual(passwdHash, encryption);
}
public PasswordEncryptor getEncryptor() {
return encryptor;
}
/**
*
* @param aPassword
* @return
* @throws ClipsServerException
* @deprecated Используйте loginBean.getEncryptor().encryptPasswd(aPassword)
*/
@Deprecated
public static byte[] getPasswordHash(char[] aPassword) throws ClipsServerException {
if (aPassword == null) {
aPassword = new char[16];
}
try {
MessageDigest md = MessageDigest.getInstance(ClipsServerConstants.PASSWORD_DIGEST_ALGORITHM);
md.update(char2byte(aPassword));
return md.digest();
} catch (NoSuchAlgorithmException ex) {
throw new ClipsServerException("Не поддерживается алгоритм " + ClipsServerConstants.PASSWORD_DIGEST_ALGORITHM);
}
}
public static byte[] getSaltPassword(char[] passwd, byte[] salt) throws ClipsServerException {
return SessionPassword.getSaltHash(SessionPassword.getPasswordHash(passwd), salt);
}
public static byte[] getSaltHash(byte[] passwordHash, byte[] salt) throws ClipsServerException {
try {
MessageDigest md = MessageDigest.getInstance(ClipsServerConstants.PASSWORD_DIGEST_ALGORITHM);
md.update(passwordHash);
md.update(salt);
return md.digest();
} catch (NoSuchAlgorithmException ex) {
throw new ClipsServerException("Не поддерживается алгоритм " + ClipsServerConstants.PASSWORD_DIGEST_ALGORITHM);
}
}
/**
* разупаковывает байты и символов (в каждом символе по 2 байта)
* @param ch
* @return
*/
public static byte[] char2byte(char[] ch) {
if (ch == null) {
return null;
}
byte b[] = new byte[ch.length * 2];
for (int i = 0; i < ch.length; i++) {
int c = (int) ch[i];
b[i * 2] = (byte) c;
b[i * 2 + 1] = (byte) (c >> 8);
}
return b;
}
/**
* упаковывает байты в символы (в каждый символ по 2 байта)
* @param ch
* @return
*/
public static char[] byte2char(byte[] a) {
if (a == null) {
return null;
}
char p[] = new char[a.length / 2 + a.length % 2];
int i;
for (i = 0; i < p.length - 1; i++) {
p[i] = (char) (((a[2 * i] & 0xFF) + (a[2 * i + 1] << 8)) & 0xFFFF);
}
i = p.length - 1;
if (a.length % 2 == 0) {
p[p.length - 1] = (char) (((a[2 * i] & 0xFF) + (a[2 * i + 1] << 8)) & 0xFFFF);
}
else {
p[p.length - 1] = (char) (a[2 * i] & 0xFF);
}
return p;
}
}