Sunday, August 17, 2014

Encryption and Decryption Using Elliptical curve cryptography(ECC)


                  The problem with using java's SunEC provider is that it is not properly implemented.While on other hand you can find various provider like bouncycastle,flexiprovider who implemented the Elliptical curve cryptography very well.Here I am using BouncyCastle provider package to implement this demo ECC encryption and Decryption algoritham.If you are interested to implement this in android then you should SpongyCastle provider package as it is android compiled version of BouncyCastle.

           Below is the code for generating the key pair and Storing it into a file like public key in public.key file and private key in private.key file.I am storing this file in my folder d:/rp/ folder.

/* Code for Generating key Pair */
import java.io.*;
import java.security.*;
import java.security.spec.*;

public class Rahul {

public static void main(String args[]) {
Rahul rahul = new rahul();
try {
String path = "D:\\rp";

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");

keyGen.initialize(1024);
KeyPair generatedKeyPair = keyGen.genKeyPair();

System.out.println("Generated Key Pair");
rahul.dumpKeyPair(generatedKeyPair);
rahul.SaveKeyPair(path, generatedKeyPair);

KeyPair loadedKeyPair = rahul.LoadKeyPair(path, "DSA");
System.out.println("Loaded Key Pair");
rahul.dumpKeyPair(loadedKeyPair);
} catch (Exception e) {
e.printStackTrace();
return;
}
}

private void dumpKeyPair(KeyPair keyPair) {
PublicKey pub = keyPair.getPublic();
System.out.println("Public Key: " + getHexString(pub.getEncoded()));

PrivateKey priv = keyPair.getPrivate();
System.out.println("Private Key: " + getHexString(priv.getEncoded()));
}

private 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 void SaveKeyPair(String path, KeyPair keyPair) throws IOException {
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

// Store Public Key.
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
publicKey.getEncoded());
FileOutputStream fos = new FileOutputStream(path + "/public.key");
fos.write(x509EncodedKeySpec.getEncoded());
fos.close();

// Store Private Key.
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
privateKey.getEncoded());
fos = new FileOutputStream(path + "/private.key");
fos.write(pkcs8EncodedKeySpec.getEncoded());
fos.close();
}

public KeyPair LoadKeyPair(String path, String algorithm)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException {
// Read Public Key.
File filePublicKey = new File(path + "/public.key");
FileInputStream fis = new FileInputStream(path + "/public.key");
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();

// Read Private Key.
File filePrivateKey = new File(path + "/private.key");
fis = new FileInputStream(path + "/private.key");
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();

// Generate KeyPair.
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

return new KeyPair(publicKey, privateKey);
}
}

Once you execute above code you will get two file namely private,key and public.key in your given path, on my system it is in d:/rp/ folder.Now you got two keys let say this key is are for user ABC.Copy this keys in another folder called ABC.
Now again execute above code and copy generated two files in folder called XYZ this is for user XYZ.
Let think that ABC & XYZ exchanges there public key with each Other.To do this Make two folder "A" and "X".This two folder will contain following data

1.Folder "A" will contain public key of XYZ and Private key of ABC.

2.Folder "X" will contain public key of ABC and Private key of XYZ.




Once you get this file you can head to following encryption and decryption code.

Below is code for Encryption of your message.For encryption use the keys from Folder "A"
and we will decrypt this by using keys from folder "X" in next code.
  

/* Code for Encryption */
import java.io.File;
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.ECParameterSpec;
import java.security.spec.EllipticCurve;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Scanner;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;





public class encryec {
KeyPairGenerator kpg;
EllipticCurve curve;
ECParameterSpec ecSpec;
KeyPair aKeyPair;
static KeyAgreement aKeyAgree;
KeyPair bKeyPair;
KeyAgreement bKeyAgree;
KeyFactory keyFac;
static String msg;
public static void main(String args[])
{
Security.addProvider(new BouncyCastleProvider());
Scanner ss=new Scanner(System.in);

try{
String path = "D:\\A";
File filePublicKey = new File(path+"\\public.key");
FileInputStream fis = new FileInputStream(path+"\\public.key");
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
 
// Read Private Key.
File filePrivateKey = new File(path+"\\private.key");
fis = new FileInputStream(path+"\\private.key");
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
 
// Generate KeyPair.
KeyFactory keyFactory = KeyFactory.getInstance("ECDH");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
 
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
 
  aKeyAgree = KeyAgreement.getInstance("ECDH", "BC");
  aKeyAgree.init(privateKey);
  aKeyAgree.doPhase(publicKey, true);
  
  byte[] aBys = aKeyAgree.generateSecret(); 
  KeySpec aKeySpec = new DESKeySpec(aBys);
  SecretKeyFactory aFactory = SecretKeyFactory.getInstance("DES");
  Key aSecretKey = aFactory.generateSecret(aKeySpec);

  Cipher aCipher = Cipher.getInstance(aSecretKey.getAlgorithm());   
  aCipher.init(Cipher.ENCRYPT_MODE, aSecretKey);  
  byte[] encText = aCipher.doFinal("Its Rahul".getBytes());
  
  System.out.println(Base64.encodeBase64String(encText));
   
  System.out.println(encText);
  
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

Take the output of above code and paste it at below line in code in place of yellow words
byte[]decText=aCipher.doFinal(Base64.decodeBase64("0wwerdjkHbVhYI+YPxUnmw==".getBytes()));

Below is code for Decryption of your output.For encryption we have used the keys from Folder "A"
and now we will decrypt this by using keys from folder "X" in below code.

/* code for Decryption */
import java.io.File;
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.ECParameterSpec;
import java.security.spec.EllipticCurve;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;



public class decryec {
KeyPairGenerator kpg;
EllipticCurve curve;
ECParameterSpec ecSpec;
KeyPair aKeyPair;
static KeyAgreement aKeyAgree;
KeyPair bKeyPair;
KeyAgreement bKeyAgree;
KeyFactory keyFac;
public static void main(String args[])
{
Security.addProvider(new BouncyCastleProvider());
try{
String path = "D:\\X";
File filePublicKey = new File(path +"\\public.key");
FileInputStream fis = new FileInputStream(path + "\\public.key");
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
 
// Read Private Key.
File filePrivateKey = new File(path + "\\private.key");
fis = new FileInputStream(path + "\\private.key");
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
 
// Generate KeyPair.
KeyFactory keyFactory = KeyFactory.getInstance("ECDH");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
 
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
  aKeyAgree = KeyAgreement.getInstance("ECDH", "BC");
  aKeyAgree.init(privateKey);
  aKeyAgree.doPhase(publicKey, true);    
  byte[] aBys = aKeyAgree.generateSecret(); 
  KeySpec aKeySpec = new DESKeySpec(aBys);
  SecretKeyFactory aFactory = SecretKeyFactory.getInstance("DES");
  Key aSecretKey = aFactory.generateSecret(aKeySpec);

  Cipher aCipher = Cipher.getInstance(aSecretKey.getAlgorithm());   
  aCipher.init(Cipher.DECRYPT_MODE, aSecretKey);  
  byte[] decText = aCipher.doFinal(Base64.decodeBase64("0wwerdjkHbVhYI+YPxUnmw==".getBytes()));
  String text = new String(decText);
  
  System.out.println("Decoded="+text);
  
}
catch(Exception e)
{
e.printStackTrace();
}
}
}



Thanks for reading feel free to comment....................

30 comments:

  1. Thanks for the code. I'm getting java.security.spec.InvalidKeySpecException: encoded key spec not recognised in encryec. how to resolve it??

    ReplyDelete
  2. Check you have right key pair in their folders as specified..

    ReplyDelete
    Replies
    1. I have the keys in specified folders but I get the same exceptions.

      Delete
    2. Even I am facing same exception. I placed the keys in specified folders only. Need your help sir. Its urgent

      Delete
    3. Even I am facing same exception. I placed the keys in specified folders only. Need your help sir. Its urgent

      Delete
    4. Even I got the same issue. Did anyone, who tried this code, get the solution for this?

      Delete
  3. What if I want to input all my own values, and am using extremely large integers?

    ReplyDelete
    Replies
    1. it doesnt matters how large the values are...it treats them as string..

      Delete
  4. I am getting the below error while executing the encryption code plz help!!!!

    C:\New folder>javac encryec.java
    encryec.java:23: error: package org.apache.commons.codec.binary does not exist
    import org.apache.commons.codec.binary.Base64;
    ^
    encryec.java:24: error: package org.bouncycastle.jce.provider does not exist
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    ^
    encryec.java:42: error: cannot find symbol
    Security.addProvider(new BouncyCastleProvider());
    ^
    symbol: class BouncyCastleProvider
    location: class encryec
    encryec.java:83: error: cannot find symbol
    System.out.println(Base64.encodeBase64String(encText));
    ^
    symbol: variable Base64
    location: class encryec

    ReplyDelete
    Replies
    1. you must do some additional import like base64 library, you can get this Base64 from jdk or bouncy castle provider,
      or you can visit my answer at stackoverflow http:bit.ly/1u3B2lM

      Delete
  5. rahul sir ..pls resolve my error .


    encryec.java:23: error: package org.apache.commons.codec.binary does not exist
    import org.apache.commons.codec.binary.Base64;
    ^
    encryec.java:24: error: package org.bouncycastle.jce.provider does not exist
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    ^
    encryec.java:42: error: cannot find symbol
    Security.addProvider(new BouncyCastleProvider());
    ^
    symbol: class BouncyCastleProvider
    location: class encryec
    encryec.java:83: error: cannot find symbol
    System.out.println(Base64.encodeBase64String(encText));
    ^
    symbol: variable Base64
    location: class encryec

    ReplyDelete
    Replies
    1. download the JAR files and them to your libraries

      Delete
  6. java.security.InvalidKeyException: ECKeyAgreement requires ECPrivateKey
    at org.bouncycastle.jce.provider.JCEECDHKeyAgreement.engineInit(JCEECDHKeyAgreement.java:136)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:467)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:441)
    at encryec.main(encryec.java:69)

    ReplyDelete
  7. java.security.InvalidKeyException: ECKeyAgreement requires ECPrivateKey
    at org.bouncycastle.jce.provider.JCEECDHKeyAgreement.engineInit(JCEECDHKeyAgreement.java:136)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:467)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:441)
    at encryec.main(encryec.java:69)

    ReplyDelete
  8. java.security.InvalidKeyException: ECKeyAgreement requires ECPrivateKey
    at org.bouncycastle.jce.provider.JCEECDHKeyAgreement.engineInit(JCEECDHKeyAgreement.java:121)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:462)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:436)
    at encryec.main(encryec.java:65)

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. Please remove my error
    java.security.spec.InvalidKeySpecException: java.lang.ClassCastException: org.bouncycastle.jce.provider.JDKDSAPublicKey cannot be cast to org.bouncycastle.jce.provider.JCEECPublicKey
    at org.bouncycastle.jce.provider.JDKKeyFactory$EC.engineGeneratePublic(JDKKeyFactory.java:613)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
    at encryec.decryec.main(decryec.java:74)
    BUILD SUCCESSFUL (total time: 3 seconds)

    ReplyDelete
  11. please resolve my problem
    java.security.spec.InvalidKeySpecException: java.lang.ClassCastException: org.bouncycastle.jce.provider.JDKDSAPublicKey cannot be cast to org.bouncycastle.jce.provider.JCEECPublicKey
    at org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory.engineGeneratePublic(KeyFactory.java:140)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
    at rahul.encryec.main(encryec.java:79)

    ReplyDelete
  12. This comment has been removed by the author.

    ReplyDelete
  13. The class name was changed in the above example and the path is different. The important bits are the 4 lines after the three lines quoted out!

    ReplyDelete
  14. how to resolve this class cast

    java.security.spec.InvalidKeySpecException: java.lang.ClassCastException: org.bouncycastle.jce.provider.JDKDSAPublicKey cannot be cast to org.bouncycastle.jce.provider.JCEECPublicKey
    at org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory.engineGeneratePublic(Unknown Source)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
    at com.hotelmanagement.ecc.encryec.main(encryec.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

    ReplyDelete
  15. Sir how can i solve the problem below.
    java.security.spec.InvalidKeySpecException: encoded key spec not recognized: algorithm identifier 1.2.840.10040.4.1 in key not recognised
    at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePublic(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:328)
    at com.mycompany.ecc.EncryptMessage.main(EncryptMessage.java:91)
    ------------------------------------------------------------------------

    ReplyDelete
  16. Sir Could you please provide the base64 library file. I could not find them. It is urgent sir

    ReplyDelete
    Replies
    1. Sir could you please drop the link of video for implementation of this code in java,,,thanks

      Delete
  17. Sir could you please drop the link of video for implementation of this code in java,,,thanks

    ReplyDelete
  18. sir i need source code for encryption image using Ecc pleas help me.

    ReplyDelete
  19. so, you code used des to do the encrypt and decrypt actually?

    ReplyDelete
  20. how i can fix this exception?

    java.security.InvalidKeyException: ECKeyAgreement requires ECPrivateKey
    at org.bouncycastle.jce.provider.JCEECDHKeyAgreement.engineInit(JCEECDHKeyAgreement.java:121)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:467)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:441)
    at co.eccencryption.ecc_encryption.main(ecc_encryption.java:79)

    ReplyDelete
  21. getting the following error...

    encoded key spec not recognized: algorithm identifier 1.2.840.10040.4.1 in key not recognised

    ReplyDelete
  22. You have to fix the code.
    Error:
    public key: [B@44e81672
    provate key: [B@60215eee
    java.security.spec.InvalidKeySpecException: encoded key spec not recognized: algorithm identifier 1.2.840.10040.4.1 in key not recognised

    ReplyDelete