Cryptography 如何在.NET Framework中读取ES512私钥

Cryptography 如何在.NET Framework中读取ES512私钥,cryptography,jwt,.net-framework-version,ecdsa,Cryptography,Jwt,.net Framework Version,Ecdsa,我正在尝试读取ES512私钥以在.NETFramework 4.7.2中创建JWT令牌,但在创建ECDsa对象时,它会引发验证异常 System.Security.Cryptography.CryptographicException: 'The specified key parameters are not valid. Q.X and Q.Y are required fields. Q.X, Q.Y must be the same length. If D is specified i

我正在尝试读取ES512私钥以在.NETFramework 4.7.2中创建JWT令牌,但在创建ECDsa对象时,它会引发验证异常

System.Security.Cryptography.CryptographicException: 'The specified key parameters are not valid. Q.X and Q.Y are required fields. Q.X, Q.Y must be the same length. If D is specified it must be the same length as Q.X and Q.Y for named curves or the same length as Order for explicit curves.'
这里怎么了?我上网查了查,找不到任何解决办法。在NetCore3中,它正在使用ImportECPrivateKey方法,但我不知道如何在我需要的.NETFramework中实现这一点

class Program
{
    static string privateKey = @"MIHcAgEBBEIBiyAa7aRHFDCh2qga9sTUGINE5jHAFnmM8xWeT/uni5I4tNqhV5Xx0pDrmCV9mbroFtfEa0XVfKuMAxxfZ6LM/yKgBwYFK4EEACOhgYkDgYYABAGBzgdnP798FsLuWYTDDQA7c0r3BVk8NnRUSexpQUsRilPNv3SchO0lRw9Ru86x1khnVDx+duq4BiDFcvlSAcyjLACJvjvoyTLJiA+TQFdmrearjMiZNE25pT2yWP1NUndJxPcvVtfBW48kPOmvkY4WlqP5bAwCXwbsKrCgk6xbsp12ew==";

    static void Main(string[] args)
    {
        var derArray = Convert.FromBase64String(privateKey);
        LoadPrivateKey(derArray);
    }

    private static ECDsa LoadPrivateKey(byte[] key)
    {
        var privKeyInt = new Org.BouncyCastle.Math.BigInteger(+1, key);
        var parameters = SecNamedCurves.GetByName("secp521r1");
        var ecPoint = parameters.G.Multiply(privKeyInt);
        var privKeyX = ecPoint.Normalize().XCoord.ToBigInteger().ToByteArrayUnsigned();
        var privKeyY = ecPoint.Normalize().YCoord.ToBigInteger().ToByteArrayUnsigned();

        return ECDsa.Create(new ECParameters
        {
            Curve = ECCurve.NamedCurves.nistP521,
            D = privKeyInt.ToByteArrayUnsigned(),
            Q = new ECPoint
            {
                X = privKeyX,
                Y = privKeyY
            }
        });
    }
}
这是PKCS#8/DER编码的私钥。DER编码不仅仅包含私有元素。在这种情况下,它也有一个版本号,曲线的名称和可能的EC公共点。您可以查看内容。重新计算公钥的速度相对较快,因此您可能不需要可选的公钥

要解码它,您需要专门的类,例如。在那之后你可以。请注意,它是一个大端编码的数字,因此部分代码需要保持完整


事实上,使用私钥作为字节,我认为整个
LoadPrivateKey
仍然是正确的(除了名称,我希望在名称中看到
load
时会出现某种IO)。

而.NET Core直接支持导入密钥格式,如PKCS#1、PKCS#8、SEC1和X.509/SPKI,对于.NET Framework,情况并非如此。这里有一种使用方法。例如,对于已发布的密钥:

BouncyCastle的
SignerUtilities
类支持签名/验证,例如:

byte[] message = Encoding.UTF8.GetBytes("The quick brown fox jumps over the lazy dog");
ISigner signer = SignerUtilities.GetSigner("SHA-512withECDSA");
signer.Init(true, ecPrivateKeyParams);
signer.BlockUpdate(message, 0, message.Length);
byte[] signature = signer.GenerateSignature();
生成的签名以ASN.1格式返回。较新的BC版本还支持
SHA-512withPLAIN-ECDSA
,它以r|s格式返回签名。这在JWT的上下文中很有趣,因为JWT使用r|s格式

或者,可以应用一个实例进行签名/验证(如问题中发布的代码中所述):

其中,
Create()
方法需要一个
System.Security.Cryptography.ECParameters
实例。后者可以从
ECPrivateKeyParameters
/
ECPublicKeyParameters
实例中派生,详细描述见

byte[] message = Encoding.UTF8.GetBytes("The quick brown fox jumps over the lazy dog");
ISigner signer = SignerUtilities.GetSigner("SHA-512withECDSA");
signer.Init(true, ecPrivateKeyParams);
signer.BlockUpdate(message, 0, message.Length);
byte[] signature = signer.GenerateSignature();
ECDsa ecdsa = ECDsa.Create(ecParams);