I encypted the session Id at server side but when I am trying to decrypt the session id at client side some error is coming. please can anyone help resolving the error.
public static String decrypt(String sessionId)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
final String decryptedSessionId = new String(cipher.doFinal(Base64.decodeBase64(sessionId)));
return decryptedSessionId;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
The error that is coming is :
Class 'javax.crypto.Cipher' is not present in JRE Emulation Library so it cannot be used in client code of "some" GWT module.
This inspection reports usages in client code of JDK classes which is not present in JRE Emulation Library.
The method for encryption that I used is :
public static String encrypt(String sessionId)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
final String encryptedSessionId = Base64.encodeBase64String(cipher.doFinal(sessionId.getBytes()));
return encryptedSessionId;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
I am new to this stuff please help me resolving the errors
Well, you cannot use java standard encryption library in GWT coding on client side. It's not supported.
Use gwt-crypto to encrypt/decrypt the necessary stuff.
AES is not be supported on client side for GWT in GWT-crypto, but you can use TripleDES. TripleDES is also very much secure implementation.
Related
When running my keycloak application, the following error appears:
java.security.NoSuchAlgorithmException: ECDSA KeyFactory not available
at java.base/java.security.KeyFactory.<init>(KeyFactory.java:138) ~[na:na]
at java.base/java.security.KeyFactory.getInstance(KeyFactory.java:183) ~[na:na]
at org.keycloak.jose.jwk.JWKParser.createECPublicKey(JWKParser.java:107) ~[keycloak-core-15.0.2.jar:15.0.2]
... 61 common frames omitted
After doing some digging, found out KeyFactory cannot settle "ECDSA" as an algorithm and therefore I should use the "EC" algorithm to generate public key.
But if KeyFactory doesnt support "ECDSA" as an algorithm, why does Keycloak-15.0.2 JWKParser class' createECPublicKey func remain trying to generate a public key with ECDSA?
try {
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name);
ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());
ECPoint point = new ECPoint(x, y);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
KeyFactory kf = KeyFactory.getInstance("ECDSA");
return kf.generatePublic(pubKeySpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
Is this a bug? or am I juts completely missing something?
Your main problem is that you forgot to tell KeyFactory.getInstance that ECDSA is from BouncyCastle provider.
You add this, KeyFactory.getInstance("ECDSA"); will work:
public static final Provider BC = new BouncyCastleProvider();
...
public static void myMethod() {
...
KeyFactory kf = KeyFactory.getInstance("ECDSA", BC);
}
Alternatively you can add BouncyCastleProvider to your list of providers:
Security.addProvider(new BouncyCastleProvider());
I have a Diffie–Hellman security class like this:
public class AESSecurityCap {
private PublicKey publicKey;
KeyAgreement keyAgreement;
byte[] sharedsecret;
AESSecurityCap() {
makeKeyExchangeParams();
}
private void makeKeyExchangeParams() {
KeyPairGenerator kpg = null;
try {
kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(128);
KeyPair kp = kpg.generateKeyPair();
publicKey = kp.getPublic();
keyAgreement = KeyAgreement.getInstance("ECDH");
keyAgreement.init(kp.getPrivate());
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
}
public void setReceiverPublicKey(PublicKey publickey) {
try {
keyAgreement.doPhase(publickey, false); // <--- Error on this line
sharedsecret = keyAgreement.generateSecret();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}
and implemented this class:
public class Node extends AESSecurityCap {
}
Sometimes I need to reinitialize DH keyAgreement:
public class TestMainClass {
public static void main(String[] args) {
Node server = new Node();
Node client = new Node();
server.setReceiverPublicKey(client.getPublicKey());
client.setReceiverPublicKey(server.getPublicKey());
// My problem is this line ,
// Second time result exception
server.setReceiverPublicKey(client.getPublicKey());
}
}
but receive this exception:
Exception in thread "main" java.lang.IllegalStateException: Phase already executed
at jdk.crypto.ec/sun.security.ec.ECDHKeyAgreement.engineDoPhase(ECDHKeyAgreement.java:91)
at java.base/javax.crypto.KeyAgreement.doPhase(KeyAgreement.java:579)
at ir.moke.AESSecurityCap.setReceiverPublicKey(AESSecurityCap.java:37)
at ir.moke.TestMainClass.main(TestMainClass.java:13)
Is there any way to reinitialize ECDH KeyAgreement multiple time?
This is my test case:
Client initialize DH and generate public key.
Client sent public key to server.
Server initialize DH with client key and generate own public key and generate shared secret key.
Server send public key to client.
Client generate shared secret key with server public key.
In this step client and server has public keys and shared secret.
My problem is client disconnected() and KeyAgreement initialized by singleton object and don't reinitialized second time.
Sometimes I need to do this subject.
Please guide me to fix this problem.
The IllegalStateException (Phase already executed) seems to be especially caused by the ECDH-implementation of the SunEC-provider. The exception doesn't occur if an (additional) init is executed immediately before the doPhase. However, this init-call shouldn't be necessary, since after the doPhase-call generateSecret is executed, which should reset the KeyAgreement-instance to the state after the init-call, at least according to the generateSecret-documentation:
This method resets this KeyAgreement object to the state that it was in after the most recent call to one of the init methods...
Possibly it's a bug in the SunEC-provider. If DH is used instead of ECDH (and the SunJCE-provider instead of the SunEC-provider) the behavior is as expected, i.e. repeated doPhase-calls are possible (without additional init-calls). The same applies to ECDH using the BouncyCastle-provider. Therefore, you could take the BouncyCastle-provider instead of the SunEC-provider to run ECDH with your code.
Note: The second parameter (lastPhase) in doPhase should be set to true, otherwise an IllegalStateException (Only two party agreement supported, lastPhase must be true) is generated (at least for ECDH).
EDIT:
The bug is already known and fixed in JDK 12, see JDK-8205476: KeyAgreement#generateSecret is not reset for ECDH based algorithmm.
I'm trying to implement ECDH in Android using a private generated by Android KeyStore Provider.
public byte[] ecdh(PublicKey otherPubKey) throws Exception {
try {
ECPublicKey ecPubKey = (ECPublicKey) otherPubKey;
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
PrivateKey pk = (PrivateKey) LoadPrivateKey("Backend");
keyAgreement.init(pk);
keyAgreement.doPhase(ecPubKey, true);
return (keyAgreement.generateSecret());
}
catch (Exception e)
{
Log.e("failure", e.toString());
return null;
}
}
However, this exception is catched in keyAgreement.init(pk) :
E/failure: java.security.InvalidKeyException: cannot identify EC private key: java.security.InvalidKeyException: no encoding for EC private key
I generated before successfully the "Backend" Public/Private key pair using:
public void GenerateNewKeyPair(String alias)
throws Exception {
if (!keyStore.containsAlias(alias)) {
// use the Android keystore
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, ANDROID_KEYSTORE);
keyGen.initialize(
new KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY | KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
.setDigests(KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512)
.setRandomizedEncryptionRequired(true)
.build());
// generates the keypair
KeyPair keyPair = keyGen.generateKeyPair();
}
}
And I load the private key using:
public PrivateKey LoadPrivateKey(String alias) throws Exception {
PrivateKey key = (PrivateKey) keyStore.getKey(alias, null);
return key;
}
Anyone has an idea what is happening and can help me to understand how to fix it? Thanks!
As far as I know through research and trial and error, this is not currently supported.
I believe the best you can do is sign the public key of an EC key pair you generate outside of the AndroidKeyStore with an EC key pair that is stored in AndroidKeyStore. You can then send this signed public key over to the other party with your signing key certificate, generate a shared secret (outside of AndroidKeyStore), then store the SecretKey that is derived using a KDF on the generated secret. I recommend using this non-AndroidKeyStore generated key pair once (so only for the purpose of deriving the secret) and repeating this process to re-key when deemed necessary.
EDIT: When I said 'store the SecretKey', I meant in AndroidKeyStore. That key will initially be in what is called 'normal world' in this context, but its the best you can do for now.
ECDH is supported in API level 23. Please refer android documentation on Android Keystore System
Sample code is also available in this link..
I am trying to open an SSLServerSocket with custom keystore/truststore and with only TLSv1.2 enabled.
Here is my related code for opening such socket:
SSLContext sslContext = null;
ServerSocket serverSocket = null;
KeyManagerFactory kmf = null;
KeyStore keystore = loadKeyStore(KEYSTORE_FILE);
if (keystore == null) {
// throw exception
}
char[] psw = System.console().readPassword("Enter password for the key materials in file \"%s\":", KEYSTORE_FILE);
try {
kmf = KeyManagerFactory.getInstance("PKIX");
kmf.init(keystore, psw);
} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
e.printStackTrace();
kmf = null;
// throw exception
}
try {
sslContext = SSLContext.getInstance("TLSv1.2");
System.out.println(kmf==null); // prints false
sslContext.init(kmf==null?null:kmf.getKeyManagers(), null, null);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
// throw exception
}
try {
serverSocket = sslContext.getServerSocketFactory().createServerSocket(PORT, BACKLOG, HOST);
((SSLServerSocket)serverSocket).setEnabledProtocols(new String[]{"TLSv1.2"});
} catch (IOException e) {
// throw exception
}
the loadKeyStore function is,
private static KeyStore loadKeyStore(String filename) {
KeyStore keystore = null;
FileInputStream fis = null;
try {
keystore = KeyStore.getInstance("JKS");
char[] psw = System.console().readPassword("Enter password for the KeyStore file \"%s\":", filename);
if (psw != null) {
fis = new FileInputStream(filename);
keystore.load(fis, psw);
}
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
keystore = null;
LogManager.getLogger().fatal("cannot load KeyStore from file \"" + filename + "\".", e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
LogManager.getLogger().error("cannot close file " + filename, e);
}
fis = null;
}
}
return keystore;
}
I accept connections in a different thread as
while (!stopped) {
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (IOException e) {
if (!stopped) {
logger.error("exception while accepting connections.", e);
}
break;
}
// start new threads to handle this connection
}
The problem is, when I enter https://HOST:PORT at Firefox, it says:
Firefox cannot guarantee the safety of your data on HOST because it
uses SSLv3, a broken security protocol. Advanced info:
ssl_error_no_cypher_overlap
How can I open a server socket that accepts only TLSv1.2 connections?
P.S. I have tried changing "TLSv1.2" strings in the code to "TLS", one by one, but nothing changed.
EDIT: I edited the code as follows:
serverSocket = sslContext.getServerSocketFactory().createServerSocket(port, backlog, host);
((SSLServerSocket)serverSocket).setEnabledProtocols(new String[]{"TLSv1.2"});
for (String s: ((SSLServerSocket)serverSocket).getEnabledCipherSuites()) {
System.out.println(s);
}
and the output is,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
TLS_ECDHE_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_SHA
TLS_ECDH_ECDSA_WITH_RC4_128_SHA TLS_ECDH_RSA_WITH_RC4_128_SHA
SSL_RSA_WITH_RC4_128_MD5 TLS_EMPTY_RENEGOTIATION_INFO_SCSV
I am not sure, but it seems the problem is not about missing enabled cipher suites. Right?
EDIT2: I have tried openssl s_client -connect HOST:PORT, and the result is
(There's a very similar question which I've answered here.)
Essentially, SSLContext.getInstance("TLSv1.2") can return an instance that supports other protocols too.
If you want to use a specific set of protocols, you need to use setEnabledProtocols(...), which is what you've done following your first edit. You now get some cipher suites with a name starting with SSL_, but that's just the name, these are still valid for TLS 1.2. As the Java Cryptography Architecture
Standard Algorithm Name Documentation for JDK 8 says:
Some JSSE cipher suite names were defined before TLSv1.0 was finalized, and were therefore given the SSL_ prefix. The names mentioned in the TLS RFCs prefixed with TLS_ are functionally equivalent to the JSSE cipher suites prefixed with SSL_.
Your last problem ("no peer certificate available", along with the handshake failure) seems to suggest there is no certificate (with its private key) found in the keystore you're trying to use.
Indeed, although the cipher suites you're mentioning are enabled, they will be automatically disabled if they cannot be used. All are either RSA or DSS cipher suites, meaning they need a certificate with an RSA or DSA key with its private key to be usable. If such a certificate with private key entry cannot be found in the keystore, it won't be usable by the KeyManager and SSLContext. Hence, they will be disabled when the handshake is actually attempted. This would typically result in an exception being thrown in the middle of the handshake on the server side ("javax.net.ssl.SSLHandshakeException: no cipher suites in common"), and the error messages you get on the client side via OpenSSL.
I'm using JUnit 4 [C:\eclipse\plugins\org.junit_4.11.0.v201303080030\junit.jar] in combination with Eclipse (MARS, Version: Mars Milestone 3 (4.5.0M3) Build id: 20141113-0320.
I have some tests that test a simple class and which work well. But now arrived at the point where I wanted to test my encryption class, which implements the following encrypt function:
public String encrypt(String data) {
try {
SecretKeySpec KS = new SecretKeySpec(mKeyData, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding"); // PKCS5Padding
cipher.init(Cipher.ENCRYPT_MODE, KS, new IvParameterSpec(mIv));
return bytesToHex(cipher.doFinal(data.getBytes()));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
The Crypto class is not sub classed...
public class Crypto {
So to test this Class and more the encrypt function I have designed the following unit test:
package my.junit4.example;
import static org.junit.Assert.*;
import org.junit.Test;
public class CryptoTest {
#Test
public void testEncryption() {
Crypto myCrypto = new Crypto();
String encodedString = myCrypto.encrypt("Secret");
assertTrue("The decrypted encrypted word should deliver the original string", encodedString.equals(myCrypto.decrypt(encodedString)));
}
}
This test is failing with a stack trace:
java.security.NoSuchAlgorithmException: Cannot find any provider supporting Blowfish/CBC/ZeroBytePaddingnull
at javax.crypto.Cipher.getInstance(Cipher.java:535) at
my.junit.example.encrypt(Crypto.java:35) at
my.junit.example.CryptoTest.testEncrypt(CryptoTest.java:14) at
This didn't make much sense to me. But being relatively new to JUnit I suspect the issue is with me not understanding how to formulate these tests. The code works well encryption - decryption in my debugger is giving me the desired outcome. But how can I get this to work with JUnit. What obvious mistake I have made?
The problem is with this line:
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding");
The algorithm you're requesting is not supported on your system. Any particular reason you want that specific one?
The docs specify the following default implementations:
AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA/ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
You need to add the Bouncy Castle provider to the Java runtime. You can see how to install the provider by looking at the Bouncy Castle wiki page. Neither the Blowfish algorithm nor zero padding is supported out of the box by Java installations.
The following runs fine on my box:
Security.addProvider(new BouncyCastleProvider());
byte[] mKeyData = new byte[16];
byte[] mIv = new byte[8];
SecretKeySpec KS = new SecretKeySpec(mKeyData, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding");
cipher.init(Cipher.ENCRYPT_MODE, KS, new IvParameterSpec(mIv));
Make sure that the provider is also available to the test framework when it is run. You'll need to put the bcprov-jdk15on-[version].jar in the class path of the runtime before you can install the provider.