In ECC encryption process, I (as a sender) am assuming that I would do following:
- Use an elliptical curve (identified as say, NIST P-256) to generate ephemeral (temporary) public and private key pair
- Get hold of public key of the receiver (i.e. the other party) some how
- Use a scheme (say Elliptic Curve Diffie-Hellman, also known as ECDH) to derive a shared secret using other party's public key and ephemeral private key from step 1 above
- Use the shared secret key to derive a symmetric key using a Key Derivation Function (KDF) (say NIST Single-step KDF as documented in http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf)
- Finally use this symmetric key to encrypt the message by using AES.
Q1: Are there any issues with above procedure?
In .net framework 4.7, here is my first stab at it:
var curve = ECCurve.NamedCurves.nistP256;
var ecdhSender = ECDiffieHellman.Create(curve);
X509Certificate2 otherPartyPublicCert = null; //TODO: Get some how from other party and populate this variable
byte[] otherPartyPublicKey = otherPartyPublicCert.GetPublicKey();
ECDiffieHellmanPublicKey otherPartyECDHPublicKey = ECDiffieHellmanCngPublicKey.FromByteArray(otherPartyPublicKey, CngKeyBlobFormat.GenericPublicBlob);
//The DeriveKeyMaterial seem to generate secret agreement, generate key and throw away the secrete agreement
var symmetricKey = ecdhSender.DeriveKeyMaterial(otherPartyECDHPublicKey);
// Or
//The DeriveKeyFromHash seem to generate same key as above because SHA256 was probably implicit in above call
var symmetricKey2 = ecdhSender.DeriveKeyFromHash(otherPartyECDHPublicKey, HashAlgorithmName.SHA256);
//TODO: Perform encryption with above key (either symmetricKey or symmetricKey2, depending on which call we choose) using AES etc.
Q2: Does above code flow seem correct (including my comments in the code)?
Q3: Is there a difference in using either DeriveKeyMaterial or DeriveKeyFromHash? (Note: When I compared the symmetricKey and symmetricKey2, they are identical)
Q4: To properly implement NIST Single-step KDF (which calls for kdf(Z, OtherInput) where Z is the secret agreement, OtherInput consists of keydatalen and OtherInfo), should be using DeriveKeyFromHash method that has secretPrepend and secretAppend bytes signature but only populate secreteAppend bytes?
Q5: If answer is yes to Q4 and if OtherInfo includes say info "AlgorithmIDStuff", "PartyUInfoStuff", "PartyVInfoStuff" (and if I choose to implement The Concatenation Format), should I use following values following byte sequence (i.e. bit string) (Z byte values used by DeriveKeyFromHash method) in secretAppend argument:
- 256 value in unsigned bytes (for keydatalen)
- len("AlgorithmIDStuff") which is 16, in unsigned value bytes
- "AlgorithmIDStuff" in unsigned ASCII value bytes => Decimal Byte Values: 65 108 103 111 114 105 116 104 109 73 68 83 116 117 102 102
- "PartyUInfoStuff" in unsigned ASCII value bytes => Decimal Byte Values: 80 97 114 116 121 85 73 110 102 111 83 116 117 102 102
- "PartyVInfoStuff" in unsigned ASCII value bytes => Decimal Byte Values: 80 97 114 116 121 86 73 110 102 111 83 116 117 102 102