// LEONARD KEVIN MCGUIRE JR
// 
// EXAMPLE OF RSA ENCRYPTION/DECRYPTION USING PRE-GENERATED PRIVATE PUBLIC OPENSSH KEY FILES
//
package projectx;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.LinkedList;

public class ProjectX {
    public static byte[] readFile(String path) throws FileNotFoundException, IOException {
        FileInputStream         fis;
        byte[]                  buf;

        fis = new FileInputStream(path);
        buf = new byte[fis.available()];
        fis.read(buf);
        fis.close();
        
        return buf;
    }

    public static BigInteger[] breakPrivateKeyIntoComponents(byte[] key) throws IOException {
        int                             len;
        BigInteger[]                    out;
        byte[]                          dat;
        ByteBuffer                      bb;
        LinkedList              fields;
        
        out = new BigInteger[2];
        
        bb = ByteBuffer.wrap(key);
        
        bb.getInt();
        
        fields = new LinkedList();
        
        while (bb.remaining() > 0) {
            // field type
            bb.get();
            // field length
            len = bb.get() & 0xff;
            if (len == 0x82) {
                len = bb.getShort() & 0xffff;
            }
            // data
            dat = new byte[len];
            bb.get(dat);
            fields.add(dat);
        }
        
        out = new BigInteger[2];
        
        out[1] = new BigInteger(1, fields.get(1));
        out[0] = new BigInteger(1, fields.get(3));
        
        return out;
    }
    
    public static BigInteger[] breakPublicKeyIntoComponents(byte[] key) throws IOException {
        int                             len;
        BigInteger[]                    out;
        byte[]                          dat;
        ByteBuffer                      bb;
        String                          test;
        
        out = new BigInteger[2];
        
        bb = ByteBuffer.wrap(key);
        
        // read type field
        len = bb.getInt();
        dat = new byte[len];
        bb.get(dat);
        test = new String(dat);
        // read exponent field
        len = bb.getInt();
        dat = new byte[len];
        bb.get(dat);
        out[0] = new BigInteger(1, dat);
        // read modulus field
        len = bb.getInt();
        dat = new byte[len];
        bb.get(dat);
        out[1] = new BigInteger(1, dat);
        
        return out;
    }
    
    public static String readKeyFile(String path) throws FileNotFoundException, IOException {
        byte[]          _data;
        String[]        lines;
        StringBuilder   sb;
        String          data;
        
        _data = readFile(path);
        data = new String(_data);
        
        lines = data.split("\\r?\\n");
        
        sb = new StringBuilder();
        
        for (int x = 0; x < lines.length; ++x) {
            if (lines[x].indexOf(":") < 0 && lines[x].indexOf("-") < 0) {
                sb.append(lines[x]);
            }
        }
        
        return sb.toString();
    }
    
    public static String[] readFilePPK(String path) throws FileNotFoundException, IOException {
        byte[]          _data;  
        String          data;
        String[]        lines;
        String          line;
        Integer         lcnt;
        String          pubkey;
        String          prikey;
        StringBuilder   sb;
        
        _data = readFile(path);
        data = new String(_data);
        
        lines = data.split("\\r?\\n");
        
        pubkey = null;
        prikey = null;
        
        for (int x = 0; x < lines.length; ++x) {
            // Public-Lines: 4
            if (lines[x].startsWith("Public-Lines:")) {
                lcnt = new Integer(lines[x].substring(lines[x].indexOf(":") + 1).trim());
                sb = new StringBuilder();
                for (int y = 0; y < lcnt; ++y) {
                    sb.append(lines[x + 1 + y].trim());
                }
                pubkey = sb.toString();
            }
            if (lines[x].startsWith("Private-Lines:")) {
                lcnt = new Integer(lines[x].substring(lines[x].indexOf(":") + 1).trim());
                sb = new StringBuilder();
                for (int y = 0; y < lcnt; ++y) {
                    sb.append(lines[x + 1 + y].trim());
                }
                prikey = sb.toString();
            }
        }
        
        lines = new String[2];
        lines[0] = prikey;
        lines[1] = pubkey;
        
        return lines;
    }
    
    public static void main(String[] args) {
        String              cb;
        byte[]              _cb;
        
        try {

            byte[]          _prikey;
            byte[]          _pubkey;
            BigInteger[]    prikey;
            BigInteger[]    pubkey;
            BigInteger      m, c;
            String          s;

            s = readKeyFile("c:\\users\\kmcguire\\.ssh\\kevin_public");
            _pubkey = new sun.misc.BASE64Decoder().decodeBuffer(s);
            pubkey = breakPublicKeyIntoComponents(_pubkey);
            
            s = readKeyFile("c:\\users\\kmcguire\\.ssh\\kevin_private");
            _prikey = new sun.misc.BASE64Decoder().decodeBuffer(s);
            prikey = breakPrivateKeyIntoComponents(_prikey);
            
            // c = m^e % n
            // m = c^d % n
            
            m = new BigInteger("hello world".getBytes());
            c = m.modPow(pubkey[0], pubkey[1]);
            m = c.modPow(prikey[0], prikey[1]);
            
            cb = new String(m.toByteArray());
            System.out.print("out:");
            System.out.println(cb);
        } catch (UnsupportedFlavorException ex) {
            cb = ex.getMessage();
        } catch (IOException ex) {
            cb = ex.getMessage();
        }
    }
}