Jos*_*del 16 javascript c# cryptography bouncycastle cng
我正在寻找一种跨平台的方式来共享ECDSA签名的公钥.从CngKey和标准.NET加密库的性能角度来看,我有一个很棒的事情,但后来我无法弄清楚33(或65)字节的公钥(使用secp256r1/P256)是如何变成104字节的由MS .. Ergo,我无法支持跨平台签名和验证..
我现在正在使用BouncyCastle,但神圣的handgranade它很慢!
因此,寻找以下要求的建议:
客户端必须能够对消息进行签名,服务器必须能够使用在注册到服务时交换的公钥来验证签名.
无论如何,想法会很棒...谢谢
Jos*_*del 29
所以我想出了在ECCPublicKeyBlob和ECCPrivateKeyBlob中导出的CngKey的格式.这应该允许其他人在其他密钥格式和CngKey之间进行互操作以进行Elliptcal Curve签名等.
ECCPrivateKeyBlob格式化(对于P256)如下
ECCPublicKeyBlob格式化(对于P256)如下
因此,如果使用其他语言的Hex中未压缩的公钥,则可以修剪第一个字节,将这8个字节添加到前面并使用
CngKey.Import(key,CngKeyBlobFormat.EccPrivateBlob);
Run Code Online (Sandbox Code Playgroud)
注意:密钥blob格式由Microsoft记录.
KEY TYPE和KEY LENGTH在BCRYPT_ECCKEY_BLOB结构中定义为:
{ ulong Magic; ulong cbKey; }
Run Code Online (Sandbox Code Playgroud)
ECC公钥存储格式:
BCRYPT_ECCKEY_BLOB
BYTE X[cbKey] // Big-endian.
BYTE Y[cbKey] // Big-endian.
Run Code Online (Sandbox Code Playgroud)
ECC私钥内存格式:
BCRYPT_ECCKEY_BLOB
BYTE X[cbKey] // Big-endian.
BYTE Y[cbKey] // Big-endian.
BYTE d[cbKey] // Big-endian.
Run Code Online (Sandbox Code Playgroud)
.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,
...
...
}
Run Code Online (Sandbox Code Playgroud)
感谢您,我能够使用以下代码从证书导入 ECDSA_P256 公钥:
private static CngKey ImportCngKeyFromCertificate(X509Certificate2 cert)
{
var keyType = new byte[] {0x45, 0x43, 0x53, 0x31};
var keyLength = new byte[] {0x20, 0x00, 0x00, 0x00};
var key = cert.PublicKey.EncodedKeyValue.RawData.Skip(1);
var keyImport = keyType.Concat(keyLength).Concat(key).ToArray();
var cngKey = CngKey.Import(keyImport, CngKeyBlobFormat.EccPublicBlob);
return cngKey;
}
Run Code Online (Sandbox Code Playgroud)
65 字节的密钥(仅公钥)以0x04需要删除的开头。然后添加您描述的标题。
然后我能够验证这样的签名:
var crypto = ECDsaCng(cngKey);
var verify = crypto.VerifyHash(hash, sig);
Run Code Online (Sandbox Code Playgroud)