ECDiffieHellman - mbedTLS 与 C#
ECDiffieHellman - mbedTLS vs C#
我需要在 ARM cortex M3 和 PC 之间使用椭圆曲线 Diffie Hellman。
在 ARM 上,我使用 mbed TLS. On the PC side I want to us C# and the ECDiffieHellman(Cng) class.
我可以在 ARM 和 ARM 上做 ECDH,但是当我尝试用 PC 替换一侧时我确实遇到了麻烦。
- 问题出在密钥交换上。
我发现,密钥由 mbed TLS 导出为
<LEN><0x04><X><Y>
.
因此,在 C# 中,我使用
导入 public 密钥
私有静态EC
DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
{
var keyLength = 32;
if (publicKey[0] != (2 + 2 * keyLength) - 1)
throw new ArgumentException("Invalid key length", nameof(publicKey));
if (publicKey[1] != 0x04)
throw new ArgumentException("Invalid key format", nameof(publicKey));
var parameters = new ECParameters()
{
Curve = ECCurve.NamedCurves.brainpoolP256r1,
Q = new ECPoint()
{
X = publicKey.Skip(2).Take(keyLength).ToArray(),
Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
}
};
using (var tmp = ECDiffieHellman.Create(parameters))
{
return tmp.PublicKey;
}
}
- 生成我试过的密钥
var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);
ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Tls;
ecdh.Seed = new byte[32];
ecdh.Label = Encoding.ASCII.GetBytes("ECDiffieHellman");
new RNGCryptoServiceProvider().GetBytes(ecdh.Seed);
// ...
var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);
我的问题是生成的共享密钥与 mbed TLS 生成的共享密钥长度不同,不匹配。
有人已经解决了这个问题吗?
谢谢!
编辑 1:
我忘了说,我在 ARM 上使用裸 ECDH。所以我认为没有任何密钥派生函数在执行。对结果进行散列 (SHA256) 以匹配 C# 端是否足够(在此处将 SHA256 配置为 KDF 时)?
我解决了这个问题。简而言之:只需散列 ECDH 结果。
C/C++边:
- EC 迪菲赫尔曼
mbedtls_ecdh_init(...);
mbedtls_ecdh_setup(...);
mbedtls_ecdh_make_public(...); //make own public key and send it to peer
mbedtls_ecdh_read_public(...); //reed peers public key
mbedtls_ecdh_calc_secret(...); //note: i pass in my own RND func because of no OS
mbedtls_ecdh_free(...);
- SHA256
mbedtls_sha256_init(...);
mbedtls_sha256_starts_ret(...);
mbedtls_sha256_update_ret(...);
mbedtls_sha256_finish_ret(...);
mbedtls_sha256_free(...);
C# 端:
private void EllipticCurveDiffieHellman()
{
var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);
ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
ecdh.HashAlgorithm = CngAlgorithm.Sha256;
//get relevant point from own public key
var ownPublicKey = ecdh.PublicKey.ExportExplicitParameters().Q;
var peersPublicKey = SendPublicKey(ownPublicKey); //key exchange
var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);
Console.WriteLine("Key: " + HexValue.Parse(sharedSecret.ToArray()));
}
DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
{
var keyLength = 32;
if (publicKey[0] != (2 + 2 * keyLength) - 1)
throw new ArgumentException("Invalid key length", nameof(publicKey));
if (publicKey[1] != 0x04)
throw new ArgumentException("Invalid key format", nameof(publicKey));
var parameters = new ECParameters()
{
Curve = ECCurve.NamedCurves.brainpoolP256r1,
Q = new ECPoint()
{
X = publicKey.Skip(2).Take(keyLength).ToArray(),
Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
}
};
using (var tmp = ECDiffieHellman.Create(parameters))
{
return tmp.PublicKey;
}
}
我需要在 ARM cortex M3 和 PC 之间使用椭圆曲线 Diffie Hellman。 在 ARM 上,我使用 mbed TLS. On the PC side I want to us C# and the ECDiffieHellman(Cng) class.
我可以在 ARM 和 ARM 上做 ECDH,但是当我尝试用 PC 替换一侧时我确实遇到了麻烦。
- 问题出在密钥交换上。
我发现,密钥由 mbed TLS 导出为
<LEN><0x04><X><Y>
.
因此,在 C# 中,我使用
导入 public 密钥私有静态EC
DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
{
var keyLength = 32;
if (publicKey[0] != (2 + 2 * keyLength) - 1)
throw new ArgumentException("Invalid key length", nameof(publicKey));
if (publicKey[1] != 0x04)
throw new ArgumentException("Invalid key format", nameof(publicKey));
var parameters = new ECParameters()
{
Curve = ECCurve.NamedCurves.brainpoolP256r1,
Q = new ECPoint()
{
X = publicKey.Skip(2).Take(keyLength).ToArray(),
Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
}
};
using (var tmp = ECDiffieHellman.Create(parameters))
{
return tmp.PublicKey;
}
}
- 生成我试过的密钥
var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);
ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Tls;
ecdh.Seed = new byte[32];
ecdh.Label = Encoding.ASCII.GetBytes("ECDiffieHellman");
new RNGCryptoServiceProvider().GetBytes(ecdh.Seed);
// ...
var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);
我的问题是生成的共享密钥与 mbed TLS 生成的共享密钥长度不同,不匹配。
有人已经解决了这个问题吗?
谢谢!
编辑 1:
我忘了说,我在 ARM 上使用裸 ECDH。所以我认为没有任何密钥派生函数在执行。对结果进行散列 (SHA256) 以匹配 C# 端是否足够(在此处将 SHA256 配置为 KDF 时)?
我解决了这个问题。简而言之:只需散列 ECDH 结果。
C/C++边:
- EC 迪菲赫尔曼
mbedtls_ecdh_init(...);
mbedtls_ecdh_setup(...);
mbedtls_ecdh_make_public(...); //make own public key and send it to peer
mbedtls_ecdh_read_public(...); //reed peers public key
mbedtls_ecdh_calc_secret(...); //note: i pass in my own RND func because of no OS
mbedtls_ecdh_free(...);
- SHA256
mbedtls_sha256_init(...);
mbedtls_sha256_starts_ret(...);
mbedtls_sha256_update_ret(...);
mbedtls_sha256_finish_ret(...);
mbedtls_sha256_free(...);
C# 端:
private void EllipticCurveDiffieHellman()
{
var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);
ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
ecdh.HashAlgorithm = CngAlgorithm.Sha256;
//get relevant point from own public key
var ownPublicKey = ecdh.PublicKey.ExportExplicitParameters().Q;
var peersPublicKey = SendPublicKey(ownPublicKey); //key exchange
var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);
Console.WriteLine("Key: " + HexValue.Parse(sharedSecret.ToArray()));
}
DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
{
var keyLength = 32;
if (publicKey[0] != (2 + 2 * keyLength) - 1)
throw new ArgumentException("Invalid key length", nameof(publicKey));
if (publicKey[1] != 0x04)
throw new ArgumentException("Invalid key format", nameof(publicKey));
var parameters = new ECParameters()
{
Curve = ECCurve.NamedCurves.brainpoolP256r1,
Q = new ECPoint()
{
X = publicKey.Skip(2).Take(keyLength).ToArray(),
Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
}
};
using (var tmp = ECDiffieHellman.Create(parameters))
{
return tmp.PublicKey;
}
}