RSA encryption in JAVA with custom key length

This code is written in three section which you can divide and use each one separately.
1. Generating custom RSA keys.
2. Use Java "security" and "crypto" API to encrypt and decrypt the text.
2. Use keys produced by API and use my algorithm to encrypt and decrypt.

-This program is written by Shooresh Sufiye. Feel free to copy and change it, But don't forget to mention the source.

// Written by Shooresh Sufiye 2017 Oct Halmstad

import java.io.File;
import java.io.FileInputStream;
import java.util.*;
import java.math.BigInteger;
import java.io.*;

import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import javax.crypto.*;

//import com.sun.java_cup.internal.runtime.Scanner;
//import com.sun.java_cup.internal.runtime.Symbol;


public class q467 {
   private final static BigInteger one = new BigInteger("1");
   private final static SecureRandom random = new SecureRandom();

   private BigInteger privateKey;
   private BigInteger publicKey;
   private BigInteger modulus;
   private BigInteger p;
   private BigInteger q;
   private BigInteger phi;

   // generate an N-bit (roughly) public and private key
   q467(int N) {
      BigInteger p = BigInteger.probablePrime(N/2, random);
      BigInteger q = BigInteger.probablePrime(N/2, random);
      BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));

      modulus    = p.multiply(q);                             
      publicKey  = new BigInteger("65537");
      privateKey = publicKey.modInverse(phi);
   }


   BigInteger encrypt(BigInteger message, BigInteger pubkey, BigInteger mod) {
   message = dopadding(message);
   return message.modPow(pubkey, mod);
   }

   BigInteger decrypt(BigInteger encrypted, BigInteger privkey, BigInteger mod) {
   encrypted = encrypted.modPow(privkey, mod);
   encrypted = removepadding(encrypted);
   //System.out.println("encrypted block size "+encrypted.bitLength());
   return encrypted;
   }
   public BigInteger dopadding(BigInteger m){   // for bigger messages should do mod 128
   byte[] b = new byte[128]; // and add to end of the last block
   for(int i=0;i<b.length;i++){
   b[i]= (byte) random.nextInt(); // 0;   // zero padding or random padding
   }
   byte[] mb = m.toByteArray();
   for(int i=0;i<mb.length;i++){
   b[i] = mb[i];
   }
   int len =  mb.length;
   b[127]= (byte) ( len );
   //System.out.println("b[127]"+b[127]+" int "+(int)b[127]);
   BigInteger rm = new BigInteger(b);

   return rm;
   }
   private BigInteger removepadding(BigInteger c){
   byte[] b  = new byte[128];
   byte[] b2 = new byte[128];
   b= c.toByteArray();
   int bval = ((int) b[127]);
   for(int i=0;i<bval;i++){
   b2[i] = b[i];
   }
   BigInteger rc = new BigInteger(b2);
   return rc;
   }

   public String toString() {
      String s = "";
      s += "public  = " + publicKey  + "\n";
      s += "private = " + privateKey + "\n";
      s += "modulus = " + modulus;
      return s;
   }
   public String to_string(BigInteger d){
   byte[] dbytes = d.toByteArray();
   String sback = "";
   for(int i =0; i< dbytes.length;i++){
   sback += (char) (dbytes[i]);
    }
   //System.out.println("sback: "+sback);
   return sback;
   }
   public String readfile(String fname) throws Exception{

  File f = new File(fname);
      FileInputStream fi = new FileInputStream(f);
      String s = "";
 
      byte[] b = new byte[fi.available()];
      int b1 = fi.read(b);
      for(int i=0;i<b1;i++){
      s += (char) b[i];
      }
 
      fi.close();
      return s;
   }

   public byte[] sercum(byte[] b){
   byte[] b2 = new byte[b.length-62];
   System.arraycopy(b, 32, b2, 0, b.length-62);
   return b2;
   }

   public KeyPair keygen() throws Exception{
   KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
   SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
   keyGen.initialize(1024, random);
   KeyPair pair = keyGen.generateKeyPair();
   PrivateKey priv = pair.getPrivate();
   PublicKey pub = pair.getPublic();
  // System.out.println("format: "+ priv.getFormat());getClass();
   return pair;
   }

   public String apiDecrypter( BigInteger encrypt, PrivateKey pk ) throws Exception{
   byte[] enb = encrypt.toByteArray();
   //System.out.println(enb.length);

   Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
   cipher.init(Cipher.DECRYPT_MODE, pk);
           String decrypted = new String(cipher.doFinal(enb));
           // remove padding
           byte[] bfin = decrypted.getBytes();
           BigInteger bigfin = new BigInteger(bfin);
           bigfin = removepadding(bigfin);
   decrypted = to_string(bigfin);

   return decrypted;
   }


  public static void main(String[] args) throws Exception {
  Scanner input = new Scanner(System.in);
  int key_len = 1024;
  System.out.print("Enter key length:(best<8500) ");
  int temp = input.nextInt();
  if (temp<8500){              // no problem with bigger keys, other than response time.
  key_len = temp;}
  else{
  System.out.println("Oops, your entered key-length is a too big, default 1024 bit will use!");
  }

  try{
  String line = "          ";
  String line2 = "\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
// System.out.println(line2+line + "  ---== MY GENERATED KEYS ==---    [EXERCISE 4]  " + line + "\n");

      q467 key = new q467(key_len);
     // System.out.println(key);
      key.keygen();
// read our plain text  
      String s = key.readfile("plain.txt");  //  "Hello Bob, How are you?"; // ALTERNATIVE text instead of file
      byte[] bytes = s.getBytes();
      BigInteger message = new BigInteger(bytes);
// encrypt our plain text with keys generated by probableprime (my keys)
      BigInteger encrypt = key.encrypt(message,key.publicKey, key.modulus);
// decrypt our plain text with my keys
      BigInteger decrypt = key.decrypt(encrypt,key.privateKey, key.modulus);
// plain text , encrypted and decrypted as numbers  
      //System.out.println("\nmessage   = " + message);
     // System.out.println("encrypted = " + encrypt);
    //  System.out.println("decrypted = " + decrypt);
 
// character representation of my decrytion:
      //System.out.println("\n"+line+"       ---== USE MY KEYS ==---  "+line+
    //      +"\n\nEncrypted:\n"+key.to_string(encrypt));
   //  System.out.println("\nDecrypted:\n"+key.to_string(decrypt)+"\n"+
//** capture time  **************************************************************************
long start1 = System.currentTimeMillis();
   System.out.println(line2+line + "     ---== USE API KEYS ==---      [EXERCISE 6]  "+ line + "\n");
//      use API to generate a new key pair
   System.out.println( "\nFile content:\n"+s );
      KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
      keyGen.initialize(key_len);
      KeyPair key3 = keyGen.generateKeyPair();
//  extract public exponrnt
      String moduluskeyString = key3.getPublic().toString();
      RSAPublicKey publi = (RSAPublicKey) key3.getPublic();
      moduluskeyString = publi.getModulus().toString(); // key.extract_modulus_key(moduluskeyString);
// extract private exponent and modulus
      RSAPrivateKey priv = (RSAPrivateKey) key3.getPrivate();     // golden function
      String privateExpoString = priv.getPrivateExponent().toString();

//  again by my code with API keys...
 
      BigInteger modulapi = new BigInteger(moduluskeyString);
      BigInteger publicapi = new BigInteger("65537");
// encryption with api keys  
      BigInteger encryptWapi = key.encrypt(message,publicapi, modulapi);
      System.out.println("Encrypted: \n"+key.to_string(encryptWapi));
      long end1 = System.currentTimeMillis();
      long start2 = System.currentTimeMillis();
//decrytion with api encrypted :
 
      BigInteger decryptWapi = key.decrypt(encryptWapi, priv.getPrivateExponent(), priv.getModulus());
      System.out.println("\nDecrypted:\n"+key.to_string(decryptWapi)+ "\n"+line
      + "  ---== I Encrypt API Decrypt ==---  "+line+"\n" );

// encrypt with my code decrypt with API
      String msg = "Hi Alice, I'm fine";
 
      System.out.println("Message:\n"+msg+"\n");
      BigInteger msgbig = new BigInteger(msg.getBytes());
 
      BigInteger myencrypt = key.encrypt(msgbig, publicapi, modulapi);
      System.out.println("Encrypted:\n"+key.to_string(myencrypt));
 
      String hybrid = key.apiDecrypter(myencrypt,priv);
      System.out.println("\nDecrypted by API:\n"+hybrid+"\n"+"\n"+line2+line+"      ---== RSA PERFORMANCE ==---  [EXERCISE 7]\n"+line+"\n");
// capture end of process time ********************************************************************************* 
  Long end2 = System.currentTimeMillis() ;
// exercise 7:  

      int duration1 = (int) (end1 - start1);
      int duration2 = (int) (end2 - start2);
      String record ="-> MY ALGORITHM "+ Integer.toString(duration1) +" mSec with a "+Integer.toString(key_len)+
      " bit keys. "+ "\n" + "-> API ALGORITHM "+ Integer.toString(duration2) +" mSec with a "+Integer.toString(key_len)+
      " bit keys. "+ "\n";  // (char) (13);
      System.out.println("Processing time for MY ALGORITH was "+duration1+" mSec and API "+duration2+" with a "+key_len+" bit key!"+
      "\nPrevious records:");
      File f = new File("time.txt");
      if(!f.exists()){
      f.createNewFile();
      }
      FileWriter timeW = new FileWriter("time.txt", true);
      timeW.append(record);
      timeW.close();
 
      System.out.println(key.readfile("time.txt"));
  }
  catch(Exception e){
  System.out.println("No Big Problem, just run it again. :D");
  }

      // the end.
   }
}

Comments

  1. This code is originally the solution to a university exercise, so some of prompts and comments are for the professor! but you can understand the aim.

    ReplyDelete

Post a Comment

Popular posts from this blog

One-Time Pad Encryption - In Python

RSA Public and Private key generation in Python