【问题标题】:Signing token with ECC encryption certificate使用 ECC 加密证书签署令牌
【发布时间】:2020-07-14 14:11:03
【问题描述】:

我正在使用自签名证书ECDH_secP384r1 来签署令牌。 这是我创建证书的 PowerShell:

$Cert = New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname $Certname -NotAfter $ExpireDate -KeyAlgorithm ECDH_secP384r1

现在我首先在我的 .net 核心应用程序中加载证书:

private readonly string _certificateSubjectName;

public X509Certificate2 GetSigningCertificate()
{

    using (var store = new X509Store(StoreLocation.LocalMachine))
    {
        store.Open(OpenFlags.ReadOnly);
        var certificates = store.Certificates.Find(X509FindType.FindBySubjectName, _certificateSubjectName, false);
        return certificates[0];

    }
}

现在有了证书,我在创建 SigningCredentials 时遇到了错误: 我试着关注this way

public string GetSignedToken(IEnumerable<Claim> claims)
{
    var signingCertificate = GetSigningCertificate();
    byte[] certBytes = signingCertificate.Export(X509ContentType.Pkcs12);

    var privateECDsa = LoadPrivateKey(certBytes);
    var signingCredentials = new SigningCredentials(new ECDsaSecurityKey(privateECDsa), SecurityAlgorithms.EcdsaSha384);

    var token = new JwtSecurityToken(
                issuer: _issuer,
                audience: _audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(_expiryMinutes),
                signingCredentials: signingCredentials);

    var securityTokenHandler = new JwtSecurityTokenHandler();
    var rawJwtToken = securityTokenHandler.WriteToken(token);
    return rawJwtToken ;
}


private static ECDsa LoadPrivateKey(byte[] key)
{

    var privKeyInt = new Org.BouncyCastle.Math.BigInteger(+1, key);
    var parameters = SecNamedCurves.GetByName("secP384r1");
    var ecPoint = parameters.G.Multiply(privKeyInt);
    var privKeyX = ecPoint.Normalize().XCoord.ToBigInteger().ToByteArrayUnsigned();
    var privKeyY = ecPoint.Normalize().YCoord.ToBigInteger().ToByteArrayUnsigned();

    var curve = ECCurve.NamedCurves.nistP384;
    var d = privKeyInt.ToByteArrayUnsigned();
    var q = new ECPoint
    {
        X = privKeyX,
        Y = privKeyY
    };

    var eCParameters = new ECParameters
    {
        Curve = curve,
        D = d,
        Q = q
    };


    var eCDsa = ECDsa.Create(eCParameters); //In this line I got an exception
    return eCDsa;

}

但我在 ECDsa.Create 中遇到了异常:

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.

更新

我也试过this way to fix sizes

var d = FixSize(privKeyInt.ToByteArrayUnsigned(), privKeyX.Length);

但在这种情况下input[0] != 0 我有一个异常,我的input[0] 不是 0 input.Length 也是 1250,预期大小是 48

我错过了什么?请有任何想法。

【问题讨论】:

  • Q.X 和 Q.Y 长度一样吗?它们和D一样长吗? Bouncy Castle 可能正在消除 ECParameters 认为重要的前导零字节。
  • 这能回答你的问题吗? Translating Elliptic Curve parameters (BC to MS)
  • @bartonjs 请检查我更新的问题。修复尺寸不适用于我
  • 很难说没有上下文中的代码。对于 secp384r1,预期大小为 384/8 (48)。
  • @bartonjs 我正在尝试根据您的回答来弄清楚,但是在我加载的证书的第一步中:signingCertificate 我在signingCertificate.PrivateKey 中遇到了异常,这是正常行为吗?我应该以不同的方式加载证书吗?

标签: c# asp.net-core x509certificate2 ecdh


【解决方案1】:

好的,经过一番搜索,我找到了an easy solution,我把它作为答案放在这里:

using System.Security.Cryptography.X509Certificates;

public string GetSignedToken(IEnumerable<Claim> claims)
{
    var signingCertificate = GetSigningCertificate();
    var securityKey = new ECDsaSecurityKey(signingCertificate.GetECDsaPrivateKey());
    var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.EcdsaSha384);

     var token = new JwtSecurityToken(
          issuer: _issuer,
          audience: _audience,
          claims: claims,
          expires: DateTime.Now.AddMinutes(_expiryMinutes),
          signingCredentials: signingCredentials);

    var securityTokenHandler = new JwtSecurityTokenHandler();
    var rawJwtToken = securityTokenHandler.WriteToken(token);

    return rawJwtToken;
}

为了验证:

using System.Security.Cryptography.X509Certificates;

public TokenValidationParameters GetTokenValidationParameters()
{
    var signingCertificate = GetSigningCertificate();
    var securityKey = new ECDsaSecurityKey(signingCertificate.GetECDsaPublicKey());

    var validationParameters = new TokenValidationParameters()
    {
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = securityKey,
        ValidateIssuer = true,
        ValidIssuer = _issuer,
        ValidateAudience = true,
        ValidAudience = _audience
    };

    return validationParameters;
}

【讨论】:

    【解决方案2】:

    以下代码将帮助您,您可以使用充气城堡库生成算法:

    private static ECDsa GetEllipticCurveAlgorithm(string privateKey)
    {
        var keyParams = (ECPrivateKeyParameters)PrivateKeyFactory
            .CreateKey(Convert.FromBase64String(privateKey));
    
        var normalizedECPoint = keyParams.Parameters.G.Multiply(keyParams.D).Normalize();
    
        return ECDsa.Create(new ECParameters
        {
            Curve = ECCurve.CreateFromValue(keyParams.PublicKeyParamSet.Id),
            D = keyParams.D.ToByteArrayUnsigned(),
            Q =
        {
            X = normalizedECPoint.XCoord.GetEncoded(),
            Y = normalizedECPoint.YCoord.GetEncoded()
        }
        });
    }
    

    并通过以下方式生成令牌:

    var signatureAlgorithm = GetEllipticCurveAlgorithm(privateKey);
    
                ECDsaSecurityKey eCDsaSecurityKey = new ECDsaSecurityKey(signatureAlgorithm)
                {
                    KeyId = settings.Apple.KeyId
                };
    
                var handler = new JwtSecurityTokenHandler();   
                var token = handler.CreateJwtSecurityToken(
                    issuer: iss,
                    audience: AUD,
                    subject: new ClaimsIdentity(new List<Claim> { new Claim("sub", sub) }),
                    expires: DateTime.UtcNow.AddMinutes(5), 
                    issuedAt: DateTime.UtcNow,
                    notBefore: DateTime.UtcNow,
                    signingCredentials: new SigningCredentials(eCDsaSecurityKey, SecurityAlgorithms.EcdsaSha256));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-02
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      相关资源
      最近更新 更多