ECIES encryption and EC key generation in Swift

646 views Asked by At

Backend uses this java implementation for encrypting the data using public key(generated from iOS App in swift),

        Cipher iesCipher = Cipher.getInstance("ECIESwithAES-CBC");
        byte[] derivation = Hex.decode(derivationString);
        byte[] encoding = Hex.decode(encodingString);
        byte[] nonce = Hex.decode(nonceString);
        IESParameterSpec params = new IESParameterSpec(derivation, encoding, 128, 128, nonce, true);
        iesCipher.init(Cipher.ENCRYPT_MODE, publicKey, params);
        byte[] ciphertext = iesCipher.doFinal(data.getBytes());

But in swift I could not find any equivalent library to decrypt it. I am using the SwiftECC for generating the EC key-pair and sending the public key to server. Then server encrypts the data using that public key as mentioned in above implementation code. But SwiftECC has no any decrypt function which accepts the arguments like derivation, encoding, nonce. And I could not find anything similar to above java implementation in swift.

2

There are 2 answers

1
Maarten Bodewes On

ECIES is using ephemeral static-ECDH + key derivation + encryption, where the public key of the ephemeral key pair is stored with the ciphertext. So if you find ECDH + the right key derivation + AES-CBC encryption (probably using PKCS#7 padding) then you'd be in business. Apparently BC uses KDF2 with SHA-1 for key derivation. I've asked and answered what KDF2 is here.

1
Sajjon On

I’ve implemented ECIES in EllipticCurveKit, feel free to use it as inspiration. Should be straightening enough to port it to SwiftECC if you don’t want to use EllipticCurveKits EC implementation.

I've hard coded the curve to be Secp256k1 (aka "the bitcoin curve"), but you could easily make it generic, by passing in a generic Curve type, just change:

func seal<Plaintext>(
    _ message: Plaintext,
    whitePublicKey: PublicKey<Secp256k1>,
    blackPrivateKey: PrivateKey<Secp256k1>,
    nonce: SealedBox.Nonce? = nil
) -> Result<SealedBox, EncryptionError> where Plaintext: DataProtocol

into (which should work in EllipticCurveKit, and should be possible in other EC libs too):

func seal<Plaintext, Curve>(
    _ message: Plaintext,
    whitePublicKey: PublicKey<Curve>,
    blackPrivateKey: PrivateKey<Curve>,
    nonce: SealedBox.Nonce? = nil
) -> Result<SealedBox, EncryptionError> where Plaintext: DataProtocol, Curve: EllipticCurve