terça-feira, 23 de outubro de 2012

Elliptic curve Diffie–Hellman - Key exchange

Elliptic curve Diffie–Hellman (ECDH) is an anonymous key agreement protocol that allows two parties, each having an elliptic curve public-private key pair, to establish a shared secret over an insecure channel. This shared secret may be directly used as a key, or better yet, to derive another key which can then be used to encrypt subsequent communications using a symmetric key cipher. It is a variant of the Diffie–Hellman protocol using elliptic curve cryptography.

 Key establishment protocol

Suppose Alice wants to establish a shared key with Bob, but the only channel available for them may be eavesdropped by a third party. Initially, the domain parameters (that is, (p,a,b,G,n,h) in the prime case or (m,f(x),a,b,G,n,h) in the binary case) must be agreed upon. Also, each party must have a key pair suitable for elliptic curve cryptography, consisting of a private key d (a randomly selected integer in the interval [1, n-1]) and a public key Q (where Q = d G). Let Alice's key pair be (d_A, Q_A) and Bob's key pair be (d_B, Q_B). Each party must have the other party's public key (an exchange must occur).
Alice computes (x_k, y_k) = d_A Q_B. Bob computes (x_k, y_k) = d_B Q_A. The shared secret is x_k (the x coordinate of the point). Most standardized protocols based on ECDH derived a symmetric key from x_k using some hash-based key derivation function.
The shared secret calculated by both parties is equal, because d_A Q_B = d_A d_B G = d_B d_A G = d_B Q_A.

The only information about her private key that Alice initially exposes is her public key. So, no party other than Alice can determine Alice's private key, unless that party can solve the elliptic curve Discrete Logarithm problem. Bob's private key is similarly secure. No party other than Alice or Bob can compute the shared secret, unless that party can solve the elliptic curve Diffie-Hellman problem.
The public keys are either static (and trusted, say via a certificate) or ephemeral. Ephemeral keys are temporary and not necessarily authenticated, so if authentication is desired, authenticity assurances must be obtained by other means. Authentication is necessary to avoid Man in the Middle attacks. If one of Alice or Bob's public key is static then Man in the Middle attacks are thwarted. Static public keys provide neither forward secrecy nor key-compromise impersonation resilience, among other advanced security properties. Holders of static private keys should validate the other public key, and should apply a secure key derivation function to the raw Diffie–Hellman shared secret to avoid leaking information about the static private key. For schemes with more advanced security properties, see ECMQV and FHMQV.
While the shared secret may be used directly as a key, it is often desirable to hash the secret to remove weak bits due to the Diffie-Hellman exchange.


Source: http://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman

Implementing code in C#

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Example

{

    class Program
    {

        static CngKey aliceKey;
        static CngKey bobKey;
        static byte[] alicePubKeyBlob;
        static byte[] bobPubKeyBlob;

        static void Main()
        {
            CreateKeys();
            byte[] encrytpedData = AliceSendsData("secret message");
            BobReceivesData(encrytpedData);
            Console.Read();
        }


        private static void CreateKeys()
        {
            aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
            bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
            alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);
            bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);
        }


        private static byte[] AliceSendsData(string message)
        {
            Console.WriteLine("Alice sends message: {0}", message);
            byte[] rawData = Encoding.UTF8.GetBytes(message);
            byte[] encryptedData = null;


            using (var aliceAlgorithm = new ECDiffieHellmanCng(aliceKey))
            using (CngKey bobPubKey = CngKey.Import(bobPubKeyBlob,
                 CngKeyBlobFormat.EccPublicBlob))
            {

                byte[] symmKey = aliceAlgorithm.DeriveKeyMaterial(bobPubKey);
                Console.WriteLine("Alice creates this symmetric key with " +
                      "Bobs public key information: {0}",
                      Convert.ToBase64String(symmKey));


               using (var aes = new AesCryptoServiceProvider())
                {

                    aes.Key = symmKey;
                    aes.GenerateIV();
                    using (ICryptoTransform encryptor = aes.CreateEncryptor())
                    using (MemoryStream ms = new MemoryStream())
                    {
                        // create CryptoStream and encrypt data to send
                        var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);

                        // write initialization vector not encrypted
                        ms.Write(aes.IV, 0, aes.IV.Length);
                        cs.Write(rawData, 0, rawData.Length);
                        cs.Close();
                        encryptedData = ms.ToArray();
                    }
                    aes.Clear();
                }
            }

           Console.WriteLine("Alice: message is encrypted: {0}",
                  Convert.ToBase64String(encryptedData)); ;
            Console.WriteLine();
            return encryptedData;
        }


       private static void BobReceivesData(byte[] encryptedData)
        {

            Console.WriteLine("Bob receives encrypted data");
            byte[] rawData = null;


            var aes = new AesCryptoServiceProvider();
            int nBytes = aes.BlockSize >> 3;
            byte[] iv = new byte[nBytes];
            for (int i = 0; i < iv.Length; i++)
                iv[i] = encryptedData[i];


            using (var bobAlgorithm = new ECDiffieHellmanCng(bobKey))
            using (CngKey alicePubKey = CngKey.Import(alicePubKeyBlob,
                  CngKeyBlobFormat.EccPublicBlob))
            {

                byte[] symmKey = bobAlgorithm.DeriveKeyMaterial(alicePubKey);
                Console.WriteLine("Bob creates this symmetric key with " +
                      "Alices public key information: {0}",
                      Convert.ToBase64String(symmKey));


               aes.Key = symmKey;
               aes.IV = iv;


                using (ICryptoTransform decryptor = aes.CreateDecryptor())
                using (MemoryStream ms = new MemoryStream())
                {
                    var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write);
                    cs.Write(encryptedData, nBytes, encryptedData.Length - nBytes);
                    cs.Close();
                     rawData = ms.ToArray();

                    Console.WriteLine("Bob decrypts message to: {0}",
                          Encoding.UTF8.GetString(rawData));

                }
                aes.Clear();
            }
        }
    }
}

Source: http://stackoverflow.com/questions/7539984/asymetric-cryptography-example-in-c-sharp

https://www.gamedev.net/forums/topic/654915-cryptography-am-i-doing-it-right/
Postar um comentário