/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * This software is the proprietary information of Sun Microsystems, Inc.
 * Use is subject to license terms.
 * 
 * Copyright 2004 Sun Microsystems, Inc.  Tous droits réservés.
 * Ce logiciel est propriété de Sun Microsystems, Inc.
 * Distribué par des licences qui en restreignent l'utilisation.
 *
 * ident        "@(#)MfCrypto.java 1.6     04/05/19 SMI"
 *
 */

/*
 * MfCrypto.java
 *
 * Created on April 14, 2004, 9:20 AM
 */
package com.sun.mfwk.security.crypto;

import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.security.spec.*;


/**
 *
 * @author  ooudghir
 */

/**
 * This class is used to encrypt and decrypt blocs of data using the DES algorithm.<p>
 * The key management can be managed by the class itself (by providing a file path which
 * contains the key)<br>
 * or can be handled by the caller (by providing the key as a SecretKey object or a byte[]).
 */
public class MfCrypto {
    private String transform = new String("DES");
    private Cipher myCipher = null;
    private SecretKey key = null;
    
    private void setCipher() {
        try {
            myCipher = Cipher.getInstance(transform);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /** Creates a new instance of MfCrypto */
    public MfCrypto() {
        setCipher();
    }
    
    /** Creates a new instance of MfCrypto and initialises the secret key with the argument
     * @exception InvalidKeyException if the key is null or invalid for DES algorithm
     * @param k The key as a byte array.
     */
    public MfCrypto(byte[] k)
    throws InvalidKeyException  {
        setCipher();
        setKey(k);
    }
    
    /** Creates a new instance of MfCrypto and initialises the secret key with the argument
     * @param k The key as a SecretKey object.
     */
    public MfCrypto(SecretKey k) 
    throws InvalidKeyException {
        setCipher();
        setKey(k);
    }
    
    /** sets the key with the argument
     * @param k The key as a SecretKey object.
     */
    public void setKey(SecretKey k) 
    throws  InvalidKeyException {
        if (key == null) {
            InvalidKeyException ike = new InvalidKeyException("Java ES-MF Symetric key must not be null");
            throw(ike);
        }
        key = k;
    }
    
    /** sets the key with the argument
     * @exception InvalidKeyException if the key is null or invalid for DES algorithm
     * @param keybuf the key as a byte array.
     */
    public void setKey(byte[] keybuf)
    throws InvalidKeyException {        
        if (keybuf == null) {
            InvalidKeyException ike = new InvalidKeyException("Java ES-MF Symetric key must not be null");
            throw(ike);
        }
        
        DESKeySpec spec = null;
        spec = new DESKeySpec(keybuf);
        
        SecretKeyFactory factory = null;
        try {
            factory = SecretKeyFactory.getInstance("DES");
        } catch(NoSuchAlgorithmException e) {
            e.printStackTrace();
            return;
        }
        
        SecretKey secret = null;
        try {
            key = factory.generateSecret(spec);
        } catch(InvalidKeySpecException e) {
            e.printStackTrace();
            return;
        }
    }
    
    /** Get the key  as Key object
     *
     * @return a SecretKey object holding the Key
     */
    public SecretKey getKeyObject() {
        return key;
    }
    
    /** Get the key as a byte[]
     * @return The key as a byte array
     */
    public byte[] getKeyBytes() {
        return key.getEncoded();
    }
    
    /** Takes a byte array as input and return a byte array which is encrypted using the symetric key
     * @return the encrypted byte array
     * @exception InvalidKeyException if the key  is null (not initialised) or invalid for DES algorithm
     * @param buf The buffer to encrypt.
     */
    public byte[] encrypt(byte[] buf)
    throws InvalidKeyException {
        if (key == null) {
            InvalidKeyException ike = new InvalidKeyException("Java ES-MF Symetric key must not be null");
            throw(ike);
        }
        
        if (buf == null) {
            NullPointerException npe = new NullPointerException("Java ES-MF buffer to encrypt must not be null");
            throw(npe);
        }
        
        byte[] encrypted = null;
        
        myCipher.init(Cipher.ENCRYPT_MODE, key);
        try {
            encrypted= myCipher.doFinal(buf);
        } catch (Exception e) {
            InvalidKeyException ike = null;
            if (e instanceof IllegalStateException) {
                ike = new InvalidKeyException("Invalid key (illegal state)");
            }
            
            if (e instanceof IllegalBlockSizeException) {
                ike = new InvalidKeyException("Invalid key (illegal block size)");
            }
            
            if (e instanceof BadPaddingException) {
                ike = new InvalidKeyException("Invalid key (bad padding)");
            }
            throw(ike);
        }   
        return(encrypted);
    }
    
    /** Takes a byte array as input and return a byte array which is decrypted using the symetric key
     * @return the decrypted byte array
     * @exception InvalidKeyException if the key is null (not initialised) or invalid for DES algorithm
     * @param buf The buffer to decrypt.
     */
    public byte[] decrypt(byte[] buf)
    throws InvalidKeyException {
        if (key == null) {
            InvalidKeyException e = new InvalidKeyException("Java ES-MF Symetric key must not be null");
            throw(e);
        }
        
        if (buf == null) {
            NullPointerException npe = new NullPointerException("Java ES-MF buffer to decrypt must not be null");
            throw(npe);
        }
        
        byte[] decrypted = null;
        try {
            myCipher.init(Cipher.DECRYPT_MODE, key);
            decrypted = myCipher.doFinal(buf);
        } catch (Exception e) {
            InvalidKeyException ike = null;
            if (e instanceof IllegalStateException) {
                ike = new InvalidKeyException("Invalid key (illegal state)");
            }
            
            if (e instanceof IllegalBlockSizeException) {
                ike = new InvalidKeyException("Invalid key (illegal block size)");
            }
            
            if (e instanceof BadPaddingException) {
                ike = new InvalidKeyException("Invalid key (bad padding)");
            }
            throw(ike);
        }   
        return decrypted;
    }
    
}
