Reputation: 3069
Party B computes ECDiffieHellmanPublicKey from this cert
var cert = new X509Certificate2(certBytes);
var bytesWithFormatIndicator = cert.PublicKey.EncodedKeyValue.RawData;
var bytesWithoutFormatIndicator = bytesWithFormatIndicator.Skip(1).ToArray();
var preBytes = "45434b3120000000".HexToBytes(); // First 8 bytes are specific to elliptic curve P-256
var rawBytes = bytesWithoutFormatIndicator;
var fullBytes = new byte[preBytes.Length + rawBytes.Length];
Buffer.BlockCopy(preBytes, 0, fullBytes, 0, preBytes.Length);
Buffer.BlockCopy(rawBytes, 0, fullBytes, preBytes.Length, rawBytes.Length);
ECDiffieHellmanPublicKey senderPublicKey = ECDiffieHellmanCngPublicKey.FromByteArray(fullBytes, CngKeyBlobFormat.EccPublicBlob);
Party B creates ECDH implementation (i.e. ephemeral public and private key pair)
var ecdhReceiver = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256);
Party B used above ECDH implementation along with Party A ECC cert public key (and some prepend and append bytes) and computes symmetric key
var prependBytes = "00000001".HexToBytes();
var appendBytes = "00000002".HexToBytes();
var derivedSymmetricKey = ecdhReceiver.DeriveKeyFromHash(senderPublicKey, HashAlgorithmName.SHA256, prependBytes, appendBytes);
Party B sends the ephemeral public key (from above ECDH implementation) to Party A
var ephemeralKeyBytesWithoutFormat = ecdhReceiver.PublicKey.ToByteArray().Skip(8).ToArray()
The goal for Party A now is to compute the same symmetric key using Party B's ephemeral public key and Party A's ECC cert (and its private key).
I am stuck at (7). Any help is appreciated.
Thanks.
Upvotes: 2
Views: 254
Reputation: 3069
This turned out to be easier than I thought:
1) Party A can dump out private and public key info from open ssl command.
openssl ec -in chris\key.pem -text -noout
2) Party A gets the output that will look like following.
Private-Key: (256 bit)
priv:
36:aa:94:67:66:2c:c5:3a:6b:44:da:af:2b:af:69:
eb:83:e1:f6:b2:43:52:b5:b4:82:4f:bb:a7:64:71:
68:3f
pub:
04:e7:b2:14:ce:a1:66:0a:2f:1f:3d:5e:af:95:be:
e4:4b:00:27:fd:1a:06:f7:14:10:88:2a:ed:2c:51:
1b:54:13:16:3e:05:f5:5b:bc:48:30:4a:49:32:46:
7f:ca:fe:cc:b1:a0:09:91:6b:fd:8f:01:7f:41:ba:
35:50:6e:a4:da
ASN1 OID: prime256v1
NIST CURVE: P-256
3) Party A constructs ECDH implementation with the above info (the leading byte 0x04 in the public key is a format indicator, ignore it):
var ecParamsReceiver = new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
D = "36aa9467662cc53a6b44daaf2baf69eb83e1f6b24352b5b4824fbba76471683f".HexToBytes(),
Q = new ECPoint()
{
X = "e7b214cea1660a2f1f3d5eaf95bee44b0027fd1a06f71410882aed2c511b5413".HexToBytes(),
Y = "163e05f55bbc48304a4932467fcafeccb1a009916bfd8f017f41ba35506ea4da".HexToBytes(),
}
};
ecParamsReceiver.Validate();
var receiverEcdh = ECDiffieHellman.Create(ecParamsReceiver);
4) Party A constructs Party B public key from the Party B ephemeral public key
var senderEphemeralPublicKey = ephemeralKeyBytesWithoutFormat;
var ecParams = new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint()
{
X = senderEphemeralPublicKey.Take(senderEphemeralPublicKey.Length / 2).ToArray(),
Y = senderEphemeralPublicKey.Skip(senderEphemeralPublicKey.Length / 2).Take(senderEphemeralPublicKey.Length / 2).ToArray(),
}
};
ecParams.Validate();
var senderEcdh = ECDiffieHellman.Create(ecParams);
5) Party A uses the same prepend and append bytes to compute the same symmetric key
var prependBytes = "00000001".HexToBytes();
var appendBytes = "00000002".HexToBytes();
var derivedSymmetricKey = receiverEcdh.DeriveKeyFromHash(senderEcdh.PublicKey, HashAlgorithmName.SHA256, prependBytes, appendBytes);
Upvotes: 0