[英]Signing token with ECC encryption certificate
我正在使用自簽名證書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 時出錯:我試圖遵循這種方式
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.
更新:
我也嘗試過這種方法來修復尺寸:
var d = FixSize(privKeyInt.ToByteArrayUnsigned(), privKeyX.Length);
但在這種情況下input[0] != 0
我得到了一個異常,我的input[0]
不是 0 還有input.Length
是 1250 並且預期大小是 48
我錯過了什么? 請有任何想法。
好的,經過一番搜索,我找到了一個簡單的解決方案,我把它作為答案放在這里:
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;
}
以下代碼將幫助您,您可以使用充氣城堡庫生成算法:
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));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.