import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class Kryptomodul {
    public static String AESPassphrase = "";
    public static byte[] encrypt(String msg, PublicKey pubKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] cipherData = cipher.doFinal(msg.getBytes());
            return cipherData;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static byte[] decrypt(byte[] enc_msg, PrivateKey privKey) {
        try {
          Cipher cipher = Cipher.getInstance("RSA");
          cipher.init(Cipher.DECRYPT_MODE, privKey);
          byte[] cipherData = cipher.doFinal(enc_msg);
          return cipherData;
        } catch(IllegalBlockSizeException err) {
            err.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static PublicKey readPublicKeyFromFile(File f) {
        try {
            // Read Public Key.
            BufferedReader br = new BufferedReader(new FileReader(f));
            byte[] encodedPublicKey = hexStringToByteArray(br.readLine());
            br.close();
     
            // Generate KeyPair.
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
                    encodedPublicKey);
            PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
         
            return publicKey;
        } catch(IOException err) {
            err.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    public static PrivateKey readPrivateKeyFromFile(File f) {
        // Private Key lesen
        try {     
            // Read Private Key.
            BufferedReader br = new BufferedReader(new FileReader(f));
            String line = br.readLine();
            line = AESModul.getDecrypted(line, AESPassphrase);
            if(line == null) {
                br.close();
                return null;
            }
            byte[] encodedPrivateKey = hexStringToByteArray(line);
            br.close();
     
            // Generate KeyPair.
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");     
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
                    encodedPrivateKey);
            PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
            return privateKey;
        } catch(IOException err) {
            err.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    public static PublicKey getKeyFromString(String keystring) {
        try {
            // Read Public Key.
            byte[] encodedPublicKey = hexStringToByteArray(keystring); 
            // Generate KeyPair.
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
                    encodedPublicKey);
            PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
         
            return publicKey;
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;        
    }
    public static String getHexString(byte[] b) {
        String result = "";
        for (int i = 0; i < b.length; i++) {
            result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
        }
        return result;
    }
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                                 + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
    public static void savePrivateKey(PrivateKey privKey, String filename) {
        //mit AES verschlüsseln:
        File f = new File(Konstanten.EXTERNAL_STORAGE+Konstanten.DIR+filename);
        
        try {
            // Store Private Key.
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
                    privKey.getEncoded());
            BufferedWriter bw = new BufferedWriter(new FileWriter(f));
            bw.write(AESModul.getEncrypted(getHexString(pkcs8EncodedKeySpec.getEncoded()),AESPassphrase));
            bw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void savePublicKey(PublicKey pubKey, String filename) {
        File f = new File(Konstanten.EXTERNAL_STORAGE+Konstanten.DIR+filename);
        // Public Key sichern
        try {
            // Store Public Key.
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
                    pubKey.getEncoded());
            BufferedWriter bw = new BufferedWriter(new FileWriter(f));
            bw.write(getHexString(x509EncodedKeySpec.getEncoded()));
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static KeyPair generateKeyPair() {
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(2048);
            return kpg.genKeyPair();
        } catch(NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
}