Web Crypto API implement ECIES like in Javascript

To implement ECIES Like (Elliptic Curve Integrated Encryption Scheme) using the Web Crypto API, we can follow a structured approach that involves generating key pairs, deriving a shared secret, and then using that secret for symmetric encryption. Below is a complete example that demonstrates how to do this in JavaScript.

Steps:

Step 1: Create Elliptic Curve Key Pairs

First, we generate an elliptic curve key pair using the generateKey method.

async function generateKeyPair() {
  const keyPair = await crypto.subtle.generateKey(
    {
      name: "ECDH",
      namedCurve: "P-256", // You can also use "P-384" or "P-521"
    },
    true,
    ["deriveKey", "deriveBits"],
  );
  return keyPair;
}

Step 2: Compute Shared Secret and Derive Symmetric Key

Next, we need to derive a symmetric key from the private key and the public key of the recipient.

async function deriveKey(privateKey, publicKey) {
  const sharedSecret = await crypto.subtle.deriveBits(
    {
      name: "ECDH",
      public: publicKey,
    },
    privateKey,
    256, // Length of the derived key in bits
  );

  const aesKey = await crypto.subtle.importKey(
    "raw",
    sharedSecret,
    { name: "AES-GCM" },
    false,
    ["encrypt", "decrypt"],
  );

  return aesKey;
}

Step 3: Encrypt Data with AES-GCM

Now, we can encrypt data using the derived symmetric key.

async function encryptData(aesKey, data) {
  const iv = crypto.getRandomValues(new Uint8Array(12)); // Initialization vector
  const encryptedData = await crypto.subtle.encrypt(
    {
      name: "AES-GCM",
      iv: iv,
    },
    aesKey,
    new TextEncoder().encode(data), // Convert string to Uint8Array
  );

  return { iv, encryptedData };
}

Step 4: Decrypt Data with AES-GCM

To decrypt the data, we can use the same symmetric key and the initialization vector.

async function decryptData(aesKey, iv, encryptedData) {
  const decryptedData = await crypto.subtle.decrypt(
    {
      name: "AES-GCM",
      iv: iv,
    },
    aesKey,
    encryptedData,
  );

  return new TextDecoder().decode(decryptedData); // Convert Uint8Array back to string
}

Step 5: Putting It All Together

Here’s how we can use the above functions to encrypt and decrypt a message:

(async () => {
  const aliceKeyPair = await generateKeyPair();
  const bobKeyPair = await generateKeyPair();

  // Alice derives a symmetric key using her private key and Bob's public key
  const aliceSharedKey = await deriveKey(aliceKeyPair.privateKey, bobKeyPair.publicKey);

  // Bob derives a symmetric key using his private key and Alice's public key
  const bobSharedKey = await deriveKey(bobKeyPair.privateKey, aliceKeyPair.publicKey);

  // Encrypt data using Alice's derived key
  const { iv, encryptedData } = await encryptData(aliceSharedKey, "Hello, ECIES!");

  console.log(encryptedData) // Output: ArrayBuffer
  console.log(String.fromCharCode(...new Uint8Array(encryptedData))) // convert Uint8Array to String

  // Decrypt data using Bob's derived key
  const decryptedMessage = await decryptData(bobSharedKey, iv, encryptedData);
  console.log(decryptedMessage); // Output: Hello, ECIES!
})();

Additional Notes

However, the code lacks a few key components that are part of a complete ECIES standard implementation:

Our code demonstrates the key exchange and encryption/decryption parts of ECIES but doesn’t fully implement the ECIES standard.

Conclusion

This example demonstrates how to use the Web Crypto API to implement ECIES-like functionality by generating elliptic curve key pairs, deriving symmetric keys using ECDH, and encrypting/decrypting data using AES-GCM. While the Web Crypto API does not provide a direct ECIES implementation, this approach effectively combines asymmetric and symmetric encryption techniques to achieve secure data transmission.

Latest blog posts

Explore the world of programming and cybersecurity through our curated collection of blog posts. From cutting-edge coding trends to the latest cyber threats and defense strategies, we've got you covered.