使用 azure 的 SignAsync 方法签署自定义创建的 JWT 格式令牌并离线验证
Sign Custom created JWT format token using SignAsync method of azure and verify offline
var byteData = Encoding.Unicode.GetBytes( encodedSerializedHeader + "." + encodedPayload);
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await keyVaultClient.SignAsync("https://offline-token-api.vault.azure.net/keys/offlinetokenprime256v1cert/3e99b8ce5dkkk3d4fb8bc6a645e7c6aa5de",
SecurityAlgorithms.EcdsaSha256, digest);
var encodedSignature = Base64UrlEncoder.Encode(signature.Result);
Now to fetch the public key for verification i am using following:-
var secret = keyVaultClient.GetSecretAsync(vaultAddress, "offlinetokenprime256v1cert").GetAwaiter().GetResult();
X509Certificate2Collection exportedCertCollection = new X509Certificate2Collection();
exportedCertCollection.Import(Convert.FromBase64String(secret.Value));
X509Certificate2 certFromSecret = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);
var publickeybyte = certFromSecret.GetPublicKey();
var publicekeybyte = certFromSecret.GetPublicKeyString();
var privatek = certFromSecret.GetECDsaPrivateKey();
var publicECDsa = LoadPublicKey(FromHexString(publicekeybyte));
var pubpri = certFromSecret.GetECDsaPublicKey();
var privateECDsa = LoadPrivateKey(FromHexString(privateKey));
var publiccECDsa = LoadPublicKey(FromHexString(publicKey));
for offline verification -
var securityToken = new JwtSecurityToken(token);
var securityTokenHandler = new JwtSecurityTokenHandler();
IdentityModelEventSource.ShowPII = true;
var validationParameters = new TokenValidationParameters()
{
ValidIssuer = securityToken.Issuer,
ValidAudience = securityToken.Audiences.First(),
IssuerSigningKey = new ECDsaSecurityKey(eCDsa)
};
SecurityToken stoken;
var claims = securityTokenHandler.ValidateToken(token, validationParameters, out stoken);
return true;
但是我收到一个错误,这不起作用任何有相同解决方案的人?
我想在不从保险库中取出私钥的情况下签署我的令牌,并希望签署 jwt 令牌中包含的信息。
有什么方法可以使用 signasync 对令牌进行签名并离线验证?
据我所知,用户无法从 Azure 密钥保管库密钥中获取私钥。只能检索 public 键。
这是我用来签名和验证的示例:
KeyVaultClient kvc = new KeyVaultClient(AuthenticationCallback);
var key = kvc.GetKeyAsync(baseUrl, "ECDSA").GetAwaiter().GetResult();
var parameters = key.Key.ToECDsa().ExportParameters(false);
var pubKeyX = parameters.Q.X;
var pubKeyY = parameters.Q.Y;
// You can store X and Y, so that you may not need to get them from Azure Key Vault again
// Use X and Y to create ECDsa instance
var ecdsa = ECDsa.Create(new System.Security.Cryptography.ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint
{
X = pubKeyX,
Y = pubKeyY
}
});
// Generate JWT
var now = DateTime.UtcNow;
var claims = new List<Claim>()
{
new Claim(JwtRegisteredClaimNames.Sub, "jack"),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Email, "jack@hanxia.onmicrosoft.com", ClaimValueTypes.String)
};
var jwt = new JwtSecurityToken(
issuer: "aaa",
audience: "bbb",
claims: claims,
notBefore: now,
expires: now.AddHours(1)
);
var header = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(new Dictionary<string, string>()
{
{ JwtHeaderParameterNames.Alg, "ES256" },
{ JwtHeaderParameterNames.Kid, key.KeyIdentifier.ToString() },
{ JwtHeaderParameterNames.Typ, "JWT" }
}));
// Sign
var byteData = Encoding.UTF8.GetBytes($"{header}.{jwt.EncodedPayload}");
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var result = kvc.SignAsync(key.KeyIdentifier.ToString(), "ES256", digest).GetAwaiter().GetResult().Result;
var signature = Base64UrlEncoder.Encode(result);
// Verify
var tokenHandler = new JwtSecurityTokenHandler();
var claimsPrincipal = tokenHandler.ValidateToken($"{header}.{jwt.EncodedPayload}.{signature}", new TokenValidationParameters
{
ValidIssuer = "aaa",
ValidAudience = "bbb",
IssuerSigningKey = new ECDsaSecurityKey(ecdsa)
}, out var parsedToken);
var byteData = Encoding.Unicode.GetBytes( encodedSerializedHeader + "." + encodedPayload);
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await keyVaultClient.SignAsync("https://offline-token-api.vault.azure.net/keys/offlinetokenprime256v1cert/3e99b8ce5dkkk3d4fb8bc6a645e7c6aa5de",
SecurityAlgorithms.EcdsaSha256, digest);
var encodedSignature = Base64UrlEncoder.Encode(signature.Result);
Now to fetch the public key for verification i am using following:-
var secret = keyVaultClient.GetSecretAsync(vaultAddress, "offlinetokenprime256v1cert").GetAwaiter().GetResult();
X509Certificate2Collection exportedCertCollection = new X509Certificate2Collection();
exportedCertCollection.Import(Convert.FromBase64String(secret.Value));
X509Certificate2 certFromSecret = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);
var publickeybyte = certFromSecret.GetPublicKey();
var publicekeybyte = certFromSecret.GetPublicKeyString();
var privatek = certFromSecret.GetECDsaPrivateKey();
var publicECDsa = LoadPublicKey(FromHexString(publicekeybyte));
var pubpri = certFromSecret.GetECDsaPublicKey();
var privateECDsa = LoadPrivateKey(FromHexString(privateKey));
var publiccECDsa = LoadPublicKey(FromHexString(publicKey));
for offline verification -
var securityToken = new JwtSecurityToken(token);
var securityTokenHandler = new JwtSecurityTokenHandler();
IdentityModelEventSource.ShowPII = true;
var validationParameters = new TokenValidationParameters()
{
ValidIssuer = securityToken.Issuer,
ValidAudience = securityToken.Audiences.First(),
IssuerSigningKey = new ECDsaSecurityKey(eCDsa)
};
SecurityToken stoken;
var claims = securityTokenHandler.ValidateToken(token, validationParameters, out stoken);
return true;
但是我收到一个错误,这不起作用任何有相同解决方案的人? 我想在不从保险库中取出私钥的情况下签署我的令牌,并希望签署 jwt 令牌中包含的信息。 有什么方法可以使用 signasync 对令牌进行签名并离线验证?
据我所知,用户无法从 Azure 密钥保管库密钥中获取私钥。只能检索 public 键。
这是我用来签名和验证的示例:
KeyVaultClient kvc = new KeyVaultClient(AuthenticationCallback);
var key = kvc.GetKeyAsync(baseUrl, "ECDSA").GetAwaiter().GetResult();
var parameters = key.Key.ToECDsa().ExportParameters(false);
var pubKeyX = parameters.Q.X;
var pubKeyY = parameters.Q.Y;
// You can store X and Y, so that you may not need to get them from Azure Key Vault again
// Use X and Y to create ECDsa instance
var ecdsa = ECDsa.Create(new System.Security.Cryptography.ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint
{
X = pubKeyX,
Y = pubKeyY
}
});
// Generate JWT
var now = DateTime.UtcNow;
var claims = new List<Claim>()
{
new Claim(JwtRegisteredClaimNames.Sub, "jack"),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Email, "jack@hanxia.onmicrosoft.com", ClaimValueTypes.String)
};
var jwt = new JwtSecurityToken(
issuer: "aaa",
audience: "bbb",
claims: claims,
notBefore: now,
expires: now.AddHours(1)
);
var header = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(new Dictionary<string, string>()
{
{ JwtHeaderParameterNames.Alg, "ES256" },
{ JwtHeaderParameterNames.Kid, key.KeyIdentifier.ToString() },
{ JwtHeaderParameterNames.Typ, "JWT" }
}));
// Sign
var byteData = Encoding.UTF8.GetBytes($"{header}.{jwt.EncodedPayload}");
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var result = kvc.SignAsync(key.KeyIdentifier.ToString(), "ES256", digest).GetAwaiter().GetResult().Result;
var signature = Base64UrlEncoder.Encode(result);
// Verify
var tokenHandler = new JwtSecurityTokenHandler();
var claimsPrincipal = tokenHandler.ValidateToken($"{header}.{jwt.EncodedPayload}.{signature}", new TokenValidationParameters
{
ValidIssuer = "aaa",
ValidAudience = "bbb",
IssuerSigningKey = new ECDsaSecurityKey(ecdsa)
}, out var parsedToken);