.NET (Core 3.1) は ECC でカスタム カーブをサポートしているようです。したがって、 Curve25519を定義し、以下のコードでキーペアを生成しました:
using System;
using System.Security.Cryptography;
namespace Curve25519
{
class Program
{
static void Main(string[] args)
{
ECCurve ecCurve = new ECCurve() // Curve25519, 32 bytes, 256 bit
{
CurveType = ECCurve.ECCurveType.PrimeMontgomery,
B = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
A = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x07, 0x6d, 0x06 }, // 486662
G = new ECPoint()
{
X = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
Y = new byte[] { 0x20, 0xae, 0x19, 0xa1, 0xb8, 0xa0, 0x86, 0xb4, 0xe0, 0x1e, 0xdd, 0x2c, 0x77, 0x48, 0xd1, 0x4c,
0x92, 0x3d, 0x4d, 0x7e, 0x6d, 0x7c, 0x61, 0xb2, 0x29, 0xe9, 0xc5, 0xa2, 0x7e, 0xce, 0xd3, 0xd9 }
},
Prime = new byte[] { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed },
//Prime = new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
Order = new byte[] { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed },
Cofactor = new byte[] { 8 }
};
using (ECDiffieHellman ecdhOwn = ECDiffieHellman.Create())
{
// generate the key pair
ecdhOwn.GenerateKey(ecCurve);
// save ECDiffieHellman implicit parameters including private key
ECParameters ecdhParamsOwn = ecdhOwn.ExportParameters(true);
// print key pair
Console.WriteLine(BitConverter.ToString(ecdhParamsOwn.D) + "\r\n" + BitConverter.ToString(ecdhParamsOwn.Q.X) + "\r\n" + BitConverter.ToString(ecdhParamsOwn.Q.Y));
}
}
}
}
出力例は次のとおりです。
90-54-A7-71-C0-03-D9-69-40-21-A4-CF-8C-81-7C-09-C4-CD-7A-44-77-2E-19-AD-B7-09-82-C9-AC-6E-AF-46
80-32-26-BD-C3-85-BC-35-17-98-B1-6C-C7-31-EF-BE-21-91-BA-CD-4A-BD-87-5B-FB-EC-4B-6B-02-C9-07-46
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
次に、別のライブラリ/プラットフォーム、つまり x-cube-cryptolib/stm32f103c8 とクロスチェックしたいと思いました。ECDiffieHellman によって生成された秘密鍵 (1 行目) を指定すると、コントロール ライブラリは同じ公開鍵を計算し (2 行目)、ペアを検証します (万歳)。
鍵交換フェーズに進む前に、私はそれで遊んでみたかったので、コードでコメントアウトされたプライムのように、Curve25519 のパラメーターを変更しました。2 つのプラットフォームで、同じ秘密鍵から異なる公開鍵のエラーまたは計算が発生することを期待していました。しかし、いいえ、ECDiffieHellman は常に制御ライブラリが確認するキー ペアを計算します。曲線パラメーターを間違ったもの、スワップまたはゼロに変更し、すべてのパラメーターに対してこれを行い、プロジェクトをクリーンアップして再構築しましたが、ケースは毎回同じでした。鍵交換フェーズに進んでも、ECDiffieHellman はコントロール ライブラリと同じ共有秘密鍵マテリアルを計算しました。
なぜ ECDiffieHellman/Curve25519 は、制御ライブラリと一貫性のある正しいキー ペアと共有シークレットを生成するのですか? それとも、これは .Net Core の ECDH 実装に関するものでしょうか?