Im using flexiprovider to encrypt/de with asymmetric algorithm based on Elliptic Curve following this tutorial. With a little modification, i'm gonna convert the public and the private key into Base64 for personal purpose (like storing into the database or text file). I'm also looking at this question and the answer is refer to this thread. But my code are running for dekstop not in android device, android and dekstop version in java i think is a really big difference (just for clean up my question information). Ok, in my code when im going to create the formatted public key from a generated public key i got an error (i think the same problem will happen when i try to do that for the private key). Now, here's my code:
- Keypair generator class.
import org.jivesoftware.smack.util.Base64; //or whatever to convert into Base64
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.KeyFactory;
import javax.crypto.Cipher;
import de.flexiprovider.common.ies.IESParameterSpec;
import de.flexiprovider.core.FlexiCoreProvider;
import de.flexiprovider.ec.FlexiECProvider;
import de.flexiprovider.ec.parameters.CurveParams;
import de.flexiprovider.ec.parameters.CurveRegistry.BrainpoolP160r1;
import de.flexiprovider.pki.PKCS8EncodedKeySpec;
import de.flexiprovider.pki.X509EncodedKeySpec;
...
Security.addProvider(new FlexiCoreProvider());
Security.addProvider(new FlexiECProvider());
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECIES","FlexiEC");
CurveParams ecParams = new BrainpoolP160r1();
kpg.initialize(ecParams, new SecureRandom());
KeyPair keyPair = kpg.generateKeyPair();
PublicKey pubKey = keyPair.getPublic();
byte[] encod_pubK = pubKey.getEncoded();
String publicKey = Base64.encodeBytes(encod_pubK);
System.out.println("Public Key :" +publikKey);
PrivateKey privKey = keyPair.getPrivate();
byte[] encod_privK = privKey.getEncoded();
String privateKey = Base64.encodeBytes(encod_privK);
System.out.println("Private Key :" +privateKey);
From that code above im going to store the string "privateKey" and "publicKey". Now im going to encrypt the message.
- Sender Side
import (same as code above)
...
Security.addProvider(new FlexiCoreProvider());
Security.addProvider(new FlexiECProvider());
Cipher cipher = Cipher.getInstance("ECIES","FlexiEC");
IESParameterSpec iesParams = new IESParameterSpec ("AES128_CBC","HmacSHA1", null, null);
byte[] decodedPubKey = Base64.decode(publicKey);
X509EncodedKeySpec formatted_public = new X509EncodedKeySpec(decodedPubKey);
KeyFactory kf = KeyFactory.getInstance("ECIES","FlexiEC");
PublicKey publicKey = kf.generatePublic(formatted_public); // <--- I got error when hit this row
cipher.init(Cipher.ENCRYPT_MODE, publicKey, iesParams);
byte[] block = "this my message".getBytes();
System.out.println("Plaintext: "+ new String(block));
byte [] Ciphered = cipher.doFinal(block);
System.out.println("Ciphertext : "+ Base64.encodeBytes(Ciphered));
The error from that sender code above is:
Exception in thread "main" de.flexiprovider.api.exceptions.InvalidKeySpecException: java.lang.RuntimeException: java.security.InvalidAlgorithmParameterException: Caught IOException("Unknown named curve: 1.3.36.3.3.2.8.1.1.1")
at de.flexiprovider.ec.keys.ECKeyFactory.generatePublic(ECKeyFactory.java:205)
at de.flexiprovider.api.keys.KeyFactory.engineGeneratePublic(KeyFactory.java:39)
at java.security.KeyFactory.generatePublic(KeyFactory.java:328)
How can i generate that public key with that named curve: 1.3.36.3.3.2.8.1.1.1 ?
- Recipient Side (just for another information)
If the sender has been succesfully encrypt the message, now im going to decrypt the message, here's my code (but not sure if this running without an error like the sender code above):
byte[] decodedPrivateKey = Base64.decode(privateKey);
PKCS8EncodedKeySpec formatted_private = new PKCS8EncodedKeySpec(decodedPrivateKey);
cipher.init(Cipher.DECRYPT_MODE, privKey, iesParams);
byte[] decryptedCipher = cipher.doFinal(Ciphered);
System.out.println("Decrypted message : "+ new String (decryptedCipher));
Due to unsolved error with my code above because i think this flexiprovider aren't compatible with jdk-8 where the bug is in "KeyFactory kf = KeyFactory.getInstance("ECIES","FlexiEC")" line which can't find that named curve, i change and decide to use BouncyCastle provider for doing the EC encryption (ECIES) and it works. But there's a question again come in to my mind, as i can see in the Flexiprovider which is use ("AES128_CBC","HmacSHA1", null, null); as the IESParameterSpec. But for bouncycastle provider i can't find where is the IESParameterSpec which using AES128_CBC as the iesparameterspec, how can i do that if want to change the iesparam into AES128_CBC when i'm using this bouncy provider ? Somebody please explain about this iesparam spec in bouncy provider i'm new about this.
Here's my code for information:
- Key Pair Generator Class
import codec.Base64; // or whatever which can use to base64 encoding
import static java.lang.System.out;
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.ECGenParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECIES", "BC");
ECGenParameterSpec brainpoolP160R1 = new ECGenParameterSpec("brainpoolP160R1");
// I'm Still using this 160 bit GF(*p*) to keep the algorithm running fast rather than 256 or above
kpg.initialize(brainpoolP160R1);
KeyPair kp = kpg.generateKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
byte[] PublicKey = publicKey.getEncoded();
byte[] PrivateKey = privateKey.getEncoded();
out.println("Encoded Public : "+Base64.encode(PublicKey));
out.println("\nEncoded Private : "+Base64.encode(PrivateKey));
...
- The Encryption class (sender side)
import codec.Base64;
import codec.CorruptedCodeException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
// Assume that we know the encoded public key then return it by decode the public key
byte[] decodedPublic = Base64.decode("MEIwFAYHKoZIzj0CAQYJKyQDAwIIAQEBAyoABNXclcmtUt8/rlGN47pc8ZpxkWgNgtKeeHdsVD0kIWLUMEULnchGZPA=".getBytes());
X509EncodedKeySpec formatted_public = new X509EncodedKeySpec(decodedPublic);
KeyFactory kf = KeyFactory.getInstance("EC","BC");
PublicKey pubKey = kf.generatePublic(formatted_public);
Cipher c = Cipher.getInstance("ECIES", "BC");
c.init(Cipher.ENCRYPT_MODE, pubKey); // How can i put the AES128_CBC for ies parameter ? is that possible
byte[] cipher = c.doFinal("This is the message".getBytes());
System.out.println("Ciphertext : "+ Base64.encode(cipher));
...
- The decryption class (recipient side)
import codec.Base64;
import codec.CorruptedCodeException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
// Assume that we know the encoded private key
byte[] decodedPrivate = Base64.decode("MHECAQAwFAYHKoZIzj0CAQYJKyQDAwIIAQEBBFYwVAIBAQQUQmA9ifs472gNHBc5NSGYq56TlOKgCwYJKyQDAwIIAQEBoSwDKgAE1dyVya1S3z+uUY3julzxmnGRaA2C0p54d2xUPSQhYtQwRQudyEZk8A==".getBytes());
PKCS8EncodedKeySpec formatted_private = new PKCS8EncodedKeySpec(decodedPrivate);
KeyFactory kf = KeyFactory.getInstance("EC", "BC");
PrivateKey privKey = kf.generatePrivate(formatted_private);
Cipher c = Cipher.getInstance("ECIES");
c.init(Cipher.DECRYPT_MODE, privKey); //How can i adding the **AES128_CBC** ies param ?
// Assume that we know the encoded cipher text
byte[] plaintext = c.doFinal(Base64.decode("BKbCsKY7gDPld+F4jauQXvKSayYCt6vOjIGbsyXo5fHWo4Ax+Nt5BQ5FlkAGksFNRQ46agzfxjfuoxWkVfnt4gReDmpPYueUbiRiHp1Gwp0="));
System.out.println("\nPlaintext : "+ new String (plaintext));
...
Any help would be appriciate !
来源:https://stackoverflow.com/questions/27938781/flexiprovider-how-to-encrypt-de-with-formatted-keypair