ECDH between C# and javascript

Asked

Viewed 156 times

2

I’m creating a web API and need to implement ECDH for end-to-end encryption. On the server side I have a C# application and on the client side a javascript application.

I can switch keys, generate private keys and encrypt a message, but I can’t decrypt it.

I think the problem is in the exchange of public keys. In javascript the keys start with a byte "4" and in . NET keys start with 8 bytes identifying the type and size of the key, to be able to import the keys I need to modify those initial bytes (Information I found here). Maybe this causes some inconsistency.

On the client side I am using the Web Cryptography API to perform ECDH. And I am implementing as below.

Generating the keys

await window.crypto.subtle.generateKey(
        {
            name: "ECDH",
            namedCurve: "P-256",
        },
        false,
        ["deriveKey", "deriveBits"]
    );

Exporting the public keys:

await window.crypto.subtle.exportKey(
        "raw",
        publicKey
    );

Importing external public keys

await window.crypto.subtle.importKey(
        "raw",
        {
            name: "ECDH",
            namedCurve: "P-256",
        },
        false,
        ["deriveKey", "deriveBits"]
    )

And finally generating the private keys

await window.crypto.subtle.deriveKey(
        {
            name: "ECDH",
            namedCurve: "P-256",
            public: publicKey,
        },
        privateKey,
        {
            name: "AES-CBC",
            length: 256,
        },
        false,
        ["encrypt", "decrypt"]
    )

On the server side I am doing the same steps as follows. Generating public key

private static ECDiffieHellmanCng ecdh = new ECDiffieHellmanCng(256);

public static void GeneratePublicKey()
{
    ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    ecdh.HashAlgorithm = CngAlgorithm.Sha256;
    publicKey = ecdh.PublicKey.ToByteArray();
}

Exporting public key. Note that I am changing the first bytes

public static byte[] GetPublicKey()
    {
        var auxKey = publicKey.Skip(7).ToArray();
        auxKey[0] = 4;

        return auxKey;
    }

Importing the public key and generating the private key. Note that I am changing the first bytes

public static void GerarChavePrivada(byte[] bobPublicKey)
{
    byte[] aux = new byte[bobPublicKey.Length + 7];

    aux[0] = 0x45;
    aux[1] = 0x43;
    aux[2] = 0x4B;
    aux[3] = 0x31;
    aux[4] = 0x20;
    aux[5] = 0x00;
    aux[6] = 0x00;
    aux[7] = 0x00;

    for (int i = 1; i < bobPublicKey.Length; i++)
    {
        aux[7 + i] = bobPublicKey[i];
    }

    var importedKey = CngKey.Import(aux, CngKeyBlobFormat.EccPublicBlob);
    privateKey = ecdh.DeriveKeyMaterial(importedKey);
}

I believe the problem lies in these keys. Anyway I am encrypting and decrypting as follows:

Javascript

async function encrypt2(iv, key, data){
    var mensagemCriptografada;

    await window.crypto.subtle.encrypt(
        {
            name: "AES-CBC",
            iv: iv,
        },
        key,
        str2ab(data) //Data é uma string e estou convertendo em base64 usando o método str2ab.
    )

    .then(function(encrypted){
        mensagemCriptografada = encrypted;
    })
    .catch(function(err){
        console.error(err);
    });

    return mensagemCriptografada;
}

function str2ab (str) {
    var array = new Uint8Array(str.length);     
    for(var i = 0; i < str.length; i++) {
        array[i] = str.charCodeAt(i);
    }
    return array.buffer
}

C#

string decMessage = "";

        using (Aes aes = new AesCryptoServiceProvider())
        {
            aes.Key = privateKey;
            aes.IV = iv; //O IV é o mesmo usado pelo javascript
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.None;

            var dec = aes.CreateDecryptor(privateKey, iv);

            var plain = dec.TransformFinalBlock(message, 0, message.Length);

            //Tentei todos os Encodings possíveis.
            decMessage = Encoding.UTF8.GetString(plain); 
        }

        return decMessage;

I really have no idea how to solve this problem.

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.