3

We need to perform encryption/decryption of some string message in java using EC key pair. key pair has been generated using secp256r1 Elliptical Curve. We just want to use java core utilities.

Encrypting code - in java server side Decryption code - it suppose to be at android and ios Key - Asymmetric EC key pair, public key readily available at java encryption side and private key readily available at android/ios decryption side. We need not to worry about key distribution, mechanism already there.

Due to encryption and decryption code present at cross platform, we want to avoid any third party library as it might not available across all three platforms - java, android, ios

ECIES, kind of encryption will work for us but how to do it in plain java utilities or with some library whihc is available across all three platforms - java, android, ios

My Sample Code(java encryption and decryption) -

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.util.encoders.Hex;

public class Main {
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
        keyGen.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
        KeyPair ecKeyPair = keyGen.generateKeyPair();
        

        Cipher iesCipher = Cipher.getInstance("AES/CBC/NoPadding");
        Cipher iesDecipher = Cipher.getInstance("AES/CBC/NoPadding");
        iesCipher.init(Cipher.ENCRYPT_MODE, ecKeyPair.getPublic());

        String message = "Hello World";

        byte[] ciphertext = iesCipher.doFinal(message.getBytes());
        System.out.println(Hex.toHexString(ciphertext));

        iesDecipher.init(Cipher.DECRYPT_MODE, ecKeyPair.getPrivate(), iesCipher.getParameters());
        byte[] plaintext = iesDecipher.doFinal(ciphertext);

        System.out.println(new String(plaintext));
    }

    public void testEncryptDecrypt() throws Exception {}

}

but above code throwing me error -

Exception in thread "main" java.security.InvalidKeyException: No installed provider supports this key: sun.security.ec.ECPublicKeyImpl 

at line - iesCipher.init(Cipher.ENCRYPT_MODE, ecKeyPair.getPublic());

Please suggest what i am missing here.

prashant sindhu
  • 1,231
  • 1
  • 13
  • 21

1 Answers1

1

You can't just use an EC key for AES.

One way to encrypt in the EC context is ECIES, a hybrid encryption scheme, which essentially uses ECDH to agree on a symmetric key that is used to symmetrically encrypt/decrypt the data. As far as I know ECIES is not possible in Java with built-in functionalities alone, i.e. you need a third party library like BouncyCastle.

Unlike ECIES, ECDH can be implemented with Java onboard means. This allows the agreement on a symmetric key, as in ECIES, which is then used to perform symmetric encryption/decryption. Since you don't want to use a third-party library, this would be a possible way:

// Generate EC keys for Alice and Bob
// as already implemented in your code

// Exchange public keys

// Derive AES key for Alice
SecretKey secretKeyAlice = getKeyViaECDH(ecKeyPairAlice.getPrivate(), ecKeyPairBob.getPublic());  // identical with secretKeyBob
System.out.println(Base64.getEncoder().encodeToString(secretKeyAlice.getEncoded()));
    
// Derive AES key for Bob
SecretKey secretKeyBob = getKeyViaECDH(ecKeyPairBob.getPrivate(), ecKeyPairAlice.getPublic()); // identical with secretKeyAlice
System.out.println(Base64.getEncoder().encodeToString(secretKeyBob.getEncoded()));

// Symmetric encryption/decryption with AES/CBC
// as already implemented in your code, but 
// - use secretKeyAlice and secretKeyBob for encryption/decryption
// - apply PKCS5Padding if the plaintext size is not an integer multiple of the block size, 16 bytes for AES

with

private static SecretKey getKeyViaECDH(PrivateKey privKey, PublicKey pubKey) throws Exception {
    KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
    keyAgreement.init(privKey);
    keyAgreement.doPhase(pubKey, true);
    byte[] sharedSecret = keyAgreement.generateSecret();
    byte[] key = MessageDigest.getInstance("SHA-256").digest(sharedSecret); // Derive key as SHA256 hash from shared secret
    SecretKey secretKey = new SecretKeySpec(key, "AES");
    return secretKey;
}

Please note that this implementation does not yet include the authentication of the ciphertext (as e.g. ECIES does). This can be implemented with a MAC, alternatively a mode like GCM can be used which performs authentication implicitly.

Topaco
  • 18,591
  • 2
  • 12
  • 39
  • at encryption side we will have public key and decryption side(android/ios) we will have private key readily available. we want to do ECIES kind of encryption and decryption and want to do in plain java utilities because decryption part will done at android and ios side and any third part library can make it complex cross platforms. – prashant sindhu Mar 02 '21 at 05:00
  • Encrypting code - in java server side Decryption code - it suppose to be at android and ios Key - Asymmetric EC key pair, public key readily available at java encryption side and private key readily available at android/ios decryption side. We need not to worry about key distribution, mechanism already there. Due to encryption and decryption code present at cross platform, we want to avoid any third party library as it might not available across all three platforms - java, android, ios – prashant sindhu Mar 02 '21 at 05:15
  • @prashantsindhu - ECIES is a great scheme, I just don't know if it can be accomplished with your requirements. I am not aware of any ECIES implementation for Java without BouncyCastle (or any other third-party library). But have a look on the web yourself. The same might be true for Android. Regarding iOS I don't know. Also, there are [several ECIES standards](https://www.researchgate.net/publication/251958691_A_comparison_of_the_standardized_versions_of_ECIES), so there might be cross-platform problems. ECDH is generally less critical in this regard. – Topaco Mar 02 '21 at 14:50