/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package rsa;

import java.math.BigInteger;
import java.util.ArrayList;


/**
 *
 * @author Dimitri SEGARD
 */
public class RSA {

    private BigInteger n;
    private BigInteger d;
    private BigInteger e;
    

    public RSA(BigInteger n, BigInteger d, BigInteger e) {
        this.n = n;
        this.d = d;
        this.e = e;        
    }

    private ArrayList<String> decoupe(String texte) {
        int taille = texte.length();
        ArrayList<String> liste = new ArrayList<String>();
        String mot;

        int i = 0;

        while (i + 5 < taille) {
            mot = "";
            for (int j = i; j < i + 5; j++) {
                mot = mot + texte.charAt(j);
            }

            liste.add(mot);
            i = i + 5;
        }

        mot = "";

        for (int j = i; j < taille; j++) {
            mot = mot + texte.charAt(j);
        }

        liste.add(mot);

        return liste;
    }

    private int[] charToAscii(String texte) {
        char[] t = texte.toCharArray();

        int[] liste = new int[texte.length()];
        for (int i = 0; i < t.length; i++) {
            liste[i] = (int) t[i];
        }

        return liste;
    }

    private long stringToBase10(String texte) {
        int[] t = charToAscii(texte);
        long nombre = 0;
        int j = 0;

        for (int i = (t.length - 1); i >= 0; i--) {
            nombre += (long) (t[i] * (Math.pow(256, j)));
            j++;
        }

        return nombre;
    }

    private String base10ToString(long base10) {
        int puissance = 0;
        String texte = "";
        long cp2;
        long cp1 = base10;
        while (cp1 / 256 >= 1) {
            puissance++;
            cp1 = cp1 / 256;
        }

        for (int i = 0; i <= puissance; i++) {
            cp2 = (long) base10 / (long) Math.pow(256, puissance - i);
            texte += (char) cp2;

            base10 = (long) base10 - (cp2 * (long) Math.pow(256, puissance - i));
        }

        return texte;
    }

    public ArrayList<BigInteger> chiffrer(String message) {
        ArrayList<String> listeChaine = decoupe(message);

        for (int i = 0; i < listeChaine.size(); i++) {
            listeChaine.set(i, Long.toString(stringToBase10(listeChaine.get(i))));
        }

        ArrayList<BigInteger> listeBigInteger = new ArrayList<BigInteger>();

        BigInteger texte;


        for (int i = 0; i < listeChaine.size(); i++) {
            texte = new BigInteger(listeChaine.get(i));
            listeBigInteger.add(texte.modPow(this.e, this.n));
        }

        return listeBigInteger;
    }

    public ArrayList<BigInteger> chiffrer(String message, BigInteger n, BigInteger e) {
        ArrayList<String> listeChaine = decoupe(message);

        for (int i = 0; i < listeChaine.size(); i++) {
            listeChaine.set(i, Long.toString(stringToBase10(listeChaine.get(i))));
        }

        ArrayList<BigInteger> listeBigInteger = new ArrayList<BigInteger>();

        BigInteger texte;

        for (int i = 0; i < listeChaine.size(); i++) {
            texte = new BigInteger(listeChaine.get(i));
            listeBigInteger.add(texte.modPow(e, n));
        }

        return listeBigInteger;
    }

    public String dechiffrer(ArrayList<BigInteger> messageChiffre) {
        ArrayList<Long> listeBase10 = new ArrayList<Long>();
        String messageDechiffre = "";

        for (int i = 0; i < messageChiffre.size(); i++) {
            listeBase10.add(messageChiffre.get(i).modPow(this.d, this.n).longValue());
        }

        for (int j = 0; j < listeBase10.size(); j++) {
            messageDechiffre += base10ToString(listeBase10.get(j));
        }

        return messageDechiffre;
    }

    public BigInteger[] getPublicKeys() {
        BigInteger[] t = {this.n, this.e};
        return t;
    }


}
