I need to connect to Snowflake using Java using Key File in format P8
class JustTheCode {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
String path = "/<path>/app_rsa_key.p8";
String passphrase = "myKey";//System.getenv("PRIVATE_KEY_PASSPHRASE");
bcParcer(path,passphrase);
}
private static PrivateKey bcParcer(String keyFilePath, String password)
throws IOException, OperatorCreationException, PKCSException, Exception {
PEMParser pemParser = new PEMParser(new FileReader(Paths.get(keyFilePath).toFile()));
PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemParser.readObject();
pemParser.close();
InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(
password.toCharArray());
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(
BouncyCastleProvider.PROVIDER_NAME);
PrivateKeyInfo decryptedPrivateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(
pkcs8Prov);
PrivateKey privateKey = converter.getPrivateKey(decryptedPrivateKeyInfo);
System.out.println(privateKey);
return privateKey;
}
}
When I run the code, I'm getting the error:
Exception in thread "main" net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: 1.2.840.113549.1.5.3 not available: requires PBE parameters
at net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source)
at configmgmt.snowflake.reader.impl.JustTheCode.bcParcer(PrivateKeyReader.java:122)
at configmgmt.snowflake.reader.impl.JustTheCode.main(PrivateKeyReader.java:102)
Caused by: net.snowflake.client.jdbc.internal.org.bouncycastle.operator.OperatorCreationException: 1.2.840.113549.1.5.3 not available: requires PBE parameters
at net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder$1.get(Unknown Source)
... 3 more
Caused by: java.security.InvalidKeyException: requires PBE parameters
at java.base/com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(PBEWithMD5AndDESCipher.java:186)
at java.base/javax.crypto.Cipher.implInit(Cipher.java:867)
at java.base/javax.crypto.Cipher.chooseProvider(Cipher.java:929)
at java.base/javax.crypto.Cipher.init(Cipher.java:1299)
at java.base/javax.crypto.Cipher.init(Cipher.java:1236)
... 4 more
Caused by: java.security.InvalidAlgorithmParameterException: Parameters missing
at java.base/com.sun.crypto.provider.PBES1Core.init(PBES1Core.java:214)
at java.base/com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(PBEWithMD5AndDESCipher.java:220)
at java.base/com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(PBEWithMD5AndDESCipher.java:184)
... 8 more
I am searching but in the documentation there is no information about this configuration: Caused by: java.security.InvalidKeyException: requires PBE parameters
I found the fix changing the imports:
Previously:
import net.snowflake.client.jdbc.internal.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import net.snowflake.client.jdbc.internal.org.bouncycastle.jce.provider.BouncyCastleProvider;
import net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.PEMParser;
import net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import net.snowflake.client.jdbc.internal.org.bouncycastle.operator.InputDecryptorProvider;
import net.snowflake.client.jdbc.internal.org.bouncycastle.operator.OperatorCreationException;
import net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCSException;
new:
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
And the pom:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
Besides having correct imports as in the accepted answer, it's also worth checking if the Security provider registered from the Snowflake jdbc driver is not saved in the Java Security Providers, as it contains different parameters and amount of them - for me it was:
2727 parameters for net.snowflake.client.jdbc.internal.org.bouncycastle.jcajce.provider
2944 parameters for org.bouncycastle.jcajce.provider
Checking Bouncy Castle Security Provider:
Security.getProvider("BC"); //or Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
Removing existing and registering a new Bouncy Castle Provider from the bcprov-ext-jdk15on library:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
Related
I have a Quarkus application which implements the server side of a ProtoBuf-over-TLS communications channel and loads a PFX/P12 file at runtime to get the server certificate and private key.
The application runs fine as a when run from the built jar, but when I try running the native image, I get an error indicating that the PKCS12 algorithm cannot be found. It seems like native images expect to have the security artifact pulled-in at build time. Do I have this correct? Is there any way to work-around this?
Example code:
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
#QuarkusMain
public class KeystoreTest implements QuarkusApplication {
String keystoreFile = "/home/sm-dp/... server.pfx";
String keystoreSecret = "secret";
#Override
public int run(String... args) throws Exception {
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (InputStream fis = new FileInputStream(new File(keystoreFile))) {
keystore.load(fis, keystoreSecret.toCharArray());
}
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
keyManagerFactory.init(keystore, keystoreSecret.toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
return 0;
}
}
Stacktrace:
java.security.KeyStoreException: PKCS12 not found
at java.security.KeyStore.getInstance(KeyStore.java:851)
at com.mcleodnet.KeystoreTest.run(KeystoreTest.java:21)
at com.mcleodnet.KeystoreTest_ClientProxy.run(KeystoreTest_ClientProxy.zig:157)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:112)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:61)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:38)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:30)
Caused by: java.security.NoSuchAlgorithmException: class configured for KeyStore (provider: SunJSSE) cannot be found.
at java.security.Provider$Service.getImplClass(Provider.java:1649)
at java.security.Provider$Service.newInstance(Provider.java:1592)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
at java.security.Security.getImpl(Security.java:695)
at java.security.KeyStore.getInstance(KeyStore.java:848)
... 6 more
Caused by: java.lang.ClassNotFoundException: sun.security.pkcs12.PKCS12KeyStore
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
at java.lang.Class.forName(DynamicHub.java:1194)
at java.security.Provider$Service.getImplClass(Provider.java:1634)
... 11 more
Try to add quarkus.native.enable-all-security-services=true to your configuration.
If it's not working, you can add a #RegisterForReflection(targets = sun.security.pkcs12.PKCS12KeyStore.class) to one of your application class.
Our application is deployed in Websphere(in solaris Os) which uses IBM java 1.6.0_26, this java version not supports TLSv1.2 protocol.
i added bouncy castle provider in my code for that i added bcprov-jdk15on-164 and bctls-jdk15on-164 jars in /opt/IBM/WebSphere/AppServer/java/jre/lib and /opt/IBM/WebSphere/AppServer/java/jre/lib/ext.
and also i tried by adding the bouncy castle security providers in java.security file at top positions like below,
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider;
security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
Note: the below code is working fine in my local machine with the Oracle java 1.6.0_26 version but not working for IBM 1.6.0_26 version.**
Below is my code
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.Security;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import org.apache.commons.io.IOUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
public class TestClient{
public static void main(String[] args) throws IOException {
try {
System.out.println("java version---"+System.getProperty("java.version"));
System.out.println("java path---"+System.getProperty("java.home"));
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
Security.insertProviderAt(new BouncyCastleProvider(), 1);
Security.removeProvider(BouncyCastleJsseProvider.PROVIDER_NAME);
Security.insertProviderAt(new BouncyCastleJsseProvider(), 2);
SSLContext sslContext= SSLContext.getInstance("TLSv1.2", BouncyCastleJsseProvider.PROVIDER_NAME);
sslContext.init(null, null , null);
String https_url = "xxxxxxxxxxxxxxxx";
String json = "xxxxxxxxxxxxxxxx";
URL url = new URL(https_url);
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
OutputStream os = conn.getOutputStream();
os.write(json.getBytes("UTF-8"));
os.close();
InputStream in = new BufferedInputStream(conn.getInputStream());
String response = IOUtils.toString(in, "UTF-8");
System.out.println("\nWebService Response:\n\n");
System.out.println("\n\n"+response+"\n\n");
in.close();
conn.disconnect();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Output of above code:
-bash-3.2$ javac TestClient.java
-bash-3.2$ java TestClient
java version---1.6.0_26
java path---/opt/IBM/WebSphere/AppServer/java/jre
java.security.KeyManagementException: java.security.NoSuchAlgorithmException: IbmX509 KeyManagerFactory not available
at org.bouncycastle.jsse.provider.ProvSSLContextSpi.selectKeyManager(Unknown Source)
at org.bouncycastle.jsse.provider.ProvSSLContextSpi.engineInit(Unknown Source)
at javax.net.ssl.SSLContext.init(SSLContext.java:27)
at Testtt.main(Testtt.java:40)
Caused by: java.security.NoSuchAlgorithmException: IbmX509 KeyManagerFactory not available
at sun.security.jca.GetInstance.getInstance(GetInstance.java:142)
at javax.net.ssl.KeyManagerFactory.getInstance(KeyManagerFactory.java:16)
... 4 more
-bash-3.2$
Please help me how to solve this problem!....
Edit 1:
i added the below two lines in the code:
Security.setProperty("ssl.KeyManagerFactory.algorithm","PKIX");
Security.setProperty("ssl.TrustManagerFactory.algorithm","PKIX");
But now the error is at outputstream:
java path---/opt/IBM/WebSphere/AppServer/java/jre
Mar 1, 2020 11:33:39 AM org.bouncycastle.jsse.provider.PropertyUtils getStringSecurityProperty
WARNING: String security property [jdk.tls.disabledAlgorithms] defaulted to: SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL
Mar 1, 2020 11:33:39 AM org.bouncycastle.jsse.provider.PropertyUtils getStringSecurityProperty
WARNING: String security property [jdk.certpath.disabledAlgorithms] defaulted to: MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
Mar 1, 2020 11:33:39 AM org.bouncycastle.jsse.provider.ProvTrustManagerFactorySpi getDefaultTrustStore
INFO: Initializing with trust store at path: /opt/IBM/WebSphere/AppServer/java/jre/lib/security/cacerts
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at com.ibm.jsse2.a.a(a.java:148)
at com.ibm.jsse2.a.a(a.java:96)
at com.ibm.jsse2.tc.a(tc.java:302)
at com.ibm.jsse2.tc.g(tc.java:208)
at com.ibm.jsse2.tc.a(tc.java:482)
at com.ibm.jsse2.tc.startHandshake(tc.java:597)
at com.ibm.net.ssl.www2.protocol.https.c.afterConnect(c.java:44)
at com.ibm.net.ssl.www2.protocol.https.d.connect(d.java:36)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1014)
at com.ibm.net.ssl.www2.protocol.https.b.getOutputStream(b.java:66)
at Testtt.main(Testtt.java:38)
BCJSSE should be used with its own KeyManagerFactory and TrustManagerFactory. It can be helpful to modify these options as follows in java.security:
ssl.KeyManagerFactory.algorithm=PKIX
ssl.TrustManagerFactory.algorithm=PKIX
However, the stack trace you showed comes from some BC version before 1.61. You report trying to use 1.64, so you must have extra jars in your class path somewhere (e.g. sometimes application servers include BC jars). Please locate the extras and remove them, or you will likely run into all sorts of other problems.
I am trying to bind to a very simple jar file in a xamarin android project, but I am getting the warning:
JARTOXML : warning J2X9001: Couldn't load class GetCerts : java.lang.UnsupportedClassVersionError: GetCerts : Unsupported major.minor version 52.0
BINDINGSGENERATOR : warning BG8601: No packages found.
if I add the picasso-2.5.2.jar to the same bindings project, it is accessible perfectly, just as in the documentation for binding a jar from xamarin (http://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/binding-a-java-library/binding-a-jar/)
the code in the jar is extremely simple:
package com.mgw;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
class GetCerts {
public static X509Certificate GetCert(byte[] bytes) throws Exception
{
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(bytes);
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);
return cert;
}
}
Problem was that the class was not public. I changed the code to be:
package com.sage;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class GetCerts {
public static X509Certificate GetCert(byte[] bytes) throws Exception
{
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(bytes);
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);
return cert;
}
public static boolean DoSomething()
{
return true;
}
}
change the file name to match the class name, rebuilt using JDK6 and it all worked.
Note that the JDK version used to build the library should not be higher than that used by Xamarin or you may get issues.
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 !
I'm using the FlexiEC provider to generate an elliptic curve public key. Then I convert the key into a byte array. After that I want to get an instance of this public key from this byte array. Whenever I do this I get an exception.
The code is as follows:
import java.security.KeyPair;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
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.X509EncodedKeySpec;
[...]
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECIES", "FlexiEC");
CurveParams ecParams = new BrainpoolP160r1();
kpg.initialize(ecParams, new SecureRandom());
KeyPair keyPair = kpg.generateKeyPair();
byte[] pubKey = keyPair.getPublic().getEncoded();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKey);
KeyFactory keyFactory = KeyFactory.getInstance("ECIES", "FlexiEC");
PublicKey pk = keyFactory.generatePublic(pubKeySpec);
The exception 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)
at com.test.App.test(App.java:68)
at com.test.App.main(App.java:76)
How can I recover the key correctly from the byte array?
I have some "ECIES", "FlexiEC" code which may be of reference for you. Here is the link:
BadPaddingException: invalid ciphertext
If this helps, the credit goes to owlstead who answered the question for me which enabled me to complete the implementation.