package krypto;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * @author kama
 */
public class KeyIO {

    private String algorithm = null;
    private KeyFactory keyFactory = null;
    private SecretKeyFactory secretKeyFactory = null;

    public KeyIO() throws NoSuchAlgorithmException {
    }
    //pobiera binarne dane o kluczu ze wskazanego pliku, zwraca bajty

    public byte[] getKey(String file) throws NoSuchAlgorithmException, FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream(file);
        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        int b;
        while ((b = fis.read()) != -1) {
            bas.write(b);
        }
        fis.close();
        bas.flush();
        bas.close();
        return bas.toByteArray();
    }
//z wczytanych danych robi klucz prywatny i zwraca PrivateKey

    public PrivateKey readPrivateKey(String file, String algo) throws NoSuchAlgorithmException, NoSuchAlgorithmException, FileNotFoundException, IOException, InvalidKeySpecException {
        byte[] dat = getKey(file);
        PKCS8EncodedKeySpec encodekey = new PKCS8EncodedKeySpec(dat);
        if (algo.equals("DSA")) {
            DSAPrivateKey privKey = (DSAPrivateKey) keyFactory.generatePrivate(encodekey);
            return privKey;
        } else if (algo.equals("RSA")) {
            RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(encodekey);
            return privKey;
        } else {
            return null;
        }
    }

    public PublicKey readPubliKey(String file, String algo) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, IOException {
        byte[] data = getKey(file);
        X509EncodedKeySpec enckey = new X509EncodedKeySpec(data);
        if (algo.equals("DSA")) {
            keyFactory = KeyFactory.getInstance(algo);
            DSAPublicKey pubKey = (DSAPublicKey) keyFactory.generatePublic(enckey);
            return pubKey;
        } else if (algo.equals("RSA")) {
            keyFactory = KeyFactory.getInstance(algo);
            RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(enckey);
            return pubKey;
        } else {
            return null;
        }
    }

    public SecretKey readSecretKey(String file, String algo) throws NoSuchAlgorithmException, FileNotFoundException, IOException, InvalidKeyException, InvalidKeySpecException {
        byte[] bin = getKey(file);
        KeySpec ks = null;
        SecretKey sek = null;
        if (algo.equals("DES")) {
            ks = new DESKeySpec(bin);
            this.secretKeyFactory = SecretKeyFactory.getInstance("DES");
            sek = secretKeyFactory.generateSecret(ks);
            return sek;

        } else if (algo.equals("DESede")) {
            ks = new DESedeKeySpec(bin);
            this.secretKeyFactory = SecretKeyFactory.getInstance("DESede");
            sek = secretKeyFactory.generateSecret(ks);
            return sek;
        } else {
            ks = new SecretKeySpec(bin, this.algorithm);
            sek = new SecretKeySpec(bin, this.algorithm);
            return sek;
        }
    }


    public void saveKey(String file, byte[] key) throws FileNotFoundException, IOException {
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(key);
        fos.flush();
        fos.close();
    }
}