我正在寻找一种跨平台的方式来共享ECDSA签名的公钥.从CngKey和标准.NET加密库的性能角度来看,我有一个很棒的事情,但后来我无法弄清楚33(或65)字节的公钥(使用secp256r1/P256)是如何变成104字节的由MS .. Ergo,我无法支持跨平台签名和验证..
我现在正在使用BouncyCastle,但神圣的handgranade它很慢!
因此,寻找以下要求的建议:
跨平台/语言(服务器是.NET,但这是通过JSON/Web.API接口提供的)
JavaScript,Ruby,Python,C++等.
在服务器上并不疯狂
不那么痛苦的慢人们不能在客户端上使用它.
客户端必须能够对消息进行签名,服务器必须能够使用在注册到服务时交换的公钥来验证签名.
无论如何,想法会很棒...谢谢
所以我想出了在ECCPublicKeyBlob和ECCPrivateKeyBlob中导出的CngKey的格式.这应该允许其他人在其他密钥格式和CngKey之间进行互操作以进行Elliptcal Curve签名等.
ECCPrivateKeyBlob格式化(对于P256)如下
[密钥类型(4字节)] [密钥长度(4字节)] [公共密钥(64字节)] [私钥(32字节)]
HEX中的KEY TYPE为45-43-53-32
HEX的关键长度是20-00-00-00
PUBLIC KEY是未压缩格式减去前导字节(在其他库中始终为04表示未压缩密钥)
ECCPublicKeyBlob格式化(对于P256)如下
[密钥类型(4字节)] [密钥长度(4字节)] [公共密钥(64字节)]
HEX中的KEY TYPE为45-43-53-31
HEX的关键长度是20-00-00-00
PUBLIC KEY是未压缩格式减去前导字节(在其他库中始终为04表示未压缩密钥)
因此,如果使用其他语言的Hex中未压缩的公钥,则可以修剪第一个字节,将这8个字节添加到前面并使用
CngKey.Import(key,CngKeyBlobFormat.EccPrivateBlob);
注意:密钥blob格式由Microsoft记录.
KEY TYPE和KEY LENGTH在BCRYPT_ECCKEY_BLOB结构中定义为:
{ ulong Magic; ulong cbKey; }
ECC公钥存储格式:
BCRYPT_ECCKEY_BLOB BYTE X[cbKey] // Big-endian. BYTE Y[cbKey] // Big-endian.
ECC私钥内存格式:
BCRYPT_ECCKEY_BLOB BYTE X[cbKey] // Big-endian. BYTE Y[cbKey] // Big-endian. BYTE d[cbKey] // Big-endian.
.NET中提供的MAGIC值在Microsoft的官方GitHub dotnet/corefx BCrypt/Interop.Blobs中.
internal enum KeyBlobMagicNumber : int { BCRYPT_ECDH_PUBLIC_P256_MAGIC = 0x314B4345, BCRYPT_ECDH_PRIVATE_P256_MAGIC = 0x324B4345, BCRYPT_ECDH_PUBLIC_P384_MAGIC = 0x334B4345, BCRYPT_ECDH_PRIVATE_P384_MAGIC = 0x344B4345, BCRYPT_ECDH_PUBLIC_P521_MAGIC = 0x354B4345, BCRYPT_ECDH_PRIVATE_P521_MAGIC = 0x364B4345, BCRYPT_ECDSA_PUBLIC_P256_MAGIC = 0x31534345, BCRYPT_ECDSA_PRIVATE_P256_MAGIC = 0x32534345, BCRYPT_ECDSA_PUBLIC_P384_MAGIC = 0x33534345, BCRYPT_ECDSA_PRIVATE_P384_MAGIC = 0x34534345 BCRYPT_ECDSA_PUBLIC_P521_MAGIC = 0x35534345, BCRYPT_ECDSA_PRIVATE_P521_MAGIC = 0x36534345, ... ... }