package it.mice.voila.runtime.security.encoders;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;

import javax.xml.bind.DatatypeConverter;

public class PBEWithMD5AndDESPasswordEncryption extends MessageDigestPasswordEncoder implements PasswordDecoder, PasswordEncoder {
	public PBEWithMD5AndDESPasswordEncryption() {
		super("MD5");
	}
	
	private static final byte[] SALT = {
	        (byte) 0xde, (byte) 0x33, (byte) 0x15, (byte) 0x12,
	        (byte) 0xde, (byte) 0x33, (byte) 0x16, (byte) 0x12,
	};
	
	public String decodePassword(String encPass, Object password) {
		try {
	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
	        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(password.toString().toCharArray()));
	        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
	        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
	        return new String(pbeCipher.doFinal(base64Decode(encPass)), "UTF-8");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public String encodePassword(String rawPass, Object password) {
		try {
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
			SecretKey key = keyFactory.generateSecret(new PBEKeySpec(password.toString().toCharArray()));
			Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
			pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
			return base64Encode(pbeCipher.doFinal(rawPass.getBytes("UTF-8")));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	private static String base64Encode(byte[] bytes) {
		return DatatypeConverter.printBase64Binary(bytes);
//        return Base64.getEncoder().encodeToString(bytes);
    }
	private static byte[] base64Decode(String property) {
		return DatatypeConverter.parseBase64Binary(property);
//        return Base64.getDecoder().decode(property);
    }
	
	public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
		String rawPassEncoded = encodePassword(rawPass, salt);
		return encPass.equals(rawPassEncoded);
	}
}
