[Fact]
public async Task VerfiyJwtTokenUseJwks()
{ var jwt = @"your jwt token"; var wellKnownAddress = "http://your-openid-host/.well-known/openid-configuration";
var httpClientFactory = this.ServiceProvier.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient(); var response = await httpClient.GetAsync(wellKnownAddress);
response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync();
var jObj = (JObject)JsonConvert.DeserializeObject(json);
var jwks_uri = jObj["jwks_uri"].ToString();
Console.WriteLine($"Jwks_uri: {jwks_uri}"); var keySet = await httpClient.GetStringAsync(jwks_uri);
Console.WriteLine($"keySets: {keySet}"); var ketSets = (JObject)JsonConvert.DeserializeObject(keySet);
var keys = (JArray)ketSets["keys"]; var jwtArray = jwt.Split('.');
var headerObj = (JObject)JsonConvert.DeserializeObject(DecodeJwtToken(jwtArray[0]));
Console.WriteLine($"Token Header: {headerObj}"); var jwtSign = jwtArray[2]; foreach (var key in keys)
{
var kid = headerObj["kid"];
if (key["kid"].ToString() == kid.ToString())
{
var e = key["e"].ToString();
var n = key["n"].ToString();
using (var rsa = System.Security.Cryptography.RSA.Create())
{
var rsaKeyInfo = new RSAParameters
{
Modulus = DecodeBase64ToByteArray(n),
Exponent = DecodeBase64ToByteArray(e)
}; rsa.ImportParameters(rsaKeyInfo);
var d = $"{jwtArray[0]}.{jwtArray[1]}"; var success = rsa.VerifyData(
Encoding.UTF8.GetBytes(d),
DecodeBase64ToByteArray(jwtSign), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); Console.WriteLine($"verfiy: {success}"); var publicKeyPem = ExportPublicKey(rsa); Console.WriteLine($"PublicKey PEM: \r\n{publicKeyPem}"); } } }
} private string DecodeJwtToken(string base64Token)
{
var bytes = DecodeBase64ToByteArray(base64Token);
var json = Encoding.UTF8.GetString(bytes);
return json;
} private byte[] DecodeBase64ToByteArray(string b64String)
{
var m = (b64String.Length % 4);
if (m > 0)
{
if (m == 2)
{
b64String += "==";
}
else
{
b64String += "=";
}
}
return Convert.FromBase64String(b64String.Replace("-", "+").Replace("_", "/"));
} public static string ExportPublicKey(RSA csp)
{
StringWriter outputStream = new StringWriter();
var parameters = csp.ExportParameters(false);
using (var stream = new MemoryStream())
{
var writer = new BinaryWriter(stream);
writer.Write((byte)0x30); // SEQUENCE
using (var innerStream = new MemoryStream())
{
var innerWriter = new BinaryWriter(innerStream);
innerWriter.Write((byte)0x30); // SEQUENCE
EncodeLength(innerWriter, 13);
innerWriter.Write((byte)0x06); // OBJECT IDENTIFIER
var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
EncodeLength(innerWriter, rsaEncryptionOid.Length);
innerWriter.Write(rsaEncryptionOid);
innerWriter.Write((byte)0x05); // NULL
EncodeLength(innerWriter, 0);
innerWriter.Write((byte)0x03); // BIT STRING
using (var bitStringStream = new MemoryStream())
{
var bitStringWriter = new BinaryWriter(bitStringStream);
bitStringWriter.Write((byte)0x00); // # of unused bits
bitStringWriter.Write((byte)0x30); // SEQUENCE
using (var paramsStream = new MemoryStream())
{
var paramsWriter = new BinaryWriter(paramsStream);
EncodeIntegerBigEndian(paramsWriter, parameters.Modulus); // Modulus
EncodeIntegerBigEndian(paramsWriter, parameters.Exponent); // Exponent
var paramsLength = (int)paramsStream.Length;
EncodeLength(bitStringWriter, paramsLength);
bitStringWriter.Write(paramsStream.GetBuffer(), 0, paramsLength);
}
var bitStringLength = (int)bitStringStream.Length;
EncodeLength(innerWriter, bitStringLength);
innerWriter.Write(bitStringStream.GetBuffer(), 0, bitStringLength);
}
var length = (int)innerStream.Length;
EncodeLength(writer, length);
writer.Write(innerStream.GetBuffer(), 0, length);
} var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
// WriteLine terminates with \r\n, we want only \n
outputStream.Write("-----BEGIN PUBLIC KEY-----\n");
for (var i = 0; i < base64.Length; i += 64)
{
outputStream.Write(base64, i, Math.Min(64, base64.Length - i));
outputStream.Write("\n");
}
outputStream.Write("-----END PUBLIC KEY-----");
} return outputStream.ToString();
} private static void EncodeLength(BinaryWriter stream, int length)
{
if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
if (length < 0x80)
{
// Short form
stream.Write((byte)length);
}
else
{
// Long form
var temp = length;
var bytesRequired = 0;
while (temp > 0)
{
temp >>= 8;
bytesRequired++;
}
stream.Write((byte)(bytesRequired | 0x80));
for (var i = bytesRequired - 1; i >= 0; i--)
{
stream.Write((byte)(length >> (8 * i) & 0xff));
}
}
} private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
{
stream.Write((byte)0x02); // INTEGER
var prefixZeros = 0;
for (var i = 0; i < value.Length; i++)
{
if (value[i] != 0) break;
prefixZeros++;
}
if (value.Length - prefixZeros == 0)
{
EncodeLength(stream, 1);
stream.Write((byte)0);
}
else
{
if (forceUnsigned && value[prefixZeros] > 0x7f)
{
// Add a prefix zero to force unsigned if the MSB is 1
EncodeLength(stream, value.Length - prefixZeros + 1);
stream.Write((byte)0);
}
else
{
EncodeLength(stream, value.Length - prefixZeros);
}
for (var i = prefixZeros; i < value.Length; i++)
{
stream.Write(value[i]);
}
}
}

DotnetCore 使用Jwks验证JwtToken签名的更多相关文章

  1. OpenSSL库验证PKCS7签名

    使用Crypto库签名和验证签名请参考Crypto库实现PKCS7签名与签名验证,可以使用OpenSSL库验证Crypto签名,OpenSSL验证签名可使用简单的代码描述如下: //signature ...

  2. ubuntu16.04 apt-get update出错:由于没有公钥,无法验证下列签名

    问题: W: 校验数字签名时出错.此仓库未被更新,所以仍然使用此前的索引文件.GPG 错误:https://packagecloud.io/github/git-lfs/ubuntu xenial I ...

  3. 由于没有公钥,无法验证下列签名 Ubuntu

    问题:执行 apt-get update 时错误 W: GPG 错误:https://apt.dockerproject.org ubuntu-trusty InRelease: 由于没有公钥,无法验 ...

  4. 树莓派 Learning 002 装机后的必要操作 --- 04 添加软件源 之 添加公钥 --- 解决“由于没有公钥,无法验证下列签名”问题

    树莓派 装机后的必要操作 - 添加软件源 解决 添加公钥 时会遇到的问题 当你添加完Debian的软件源后,在终端中执行sudo apt-get update时,会出现下面的错误:(这里我添加了3个软 ...

  5. sudo apt-get update 没有公钥,无法验证下列签名

    在更新系统源后,输入sudo apt-get update之后出现提示: W: GPG 错误:http://archive.ubuntukylin.com:10006 xenial InRelease ...

  6. ”W: GPG 错误:http://ppa.launchpad.net lucid Release: 由于没有公钥,无法验证下列签名:“的问题

    在安装更新时,即在运行,命令行sudo apt-get update 或者运行更新管理器的时候,出现如下错误: W: GPG 错误:http://ppa.launchpad.net lucid Rel ...

  7. 更新linux时候提示“由于没有公钥,无法验证下列签名".

    本文链接:https://blog.csdn.net/loovejava/article/details/21837935 新安装的Ubuntu在使用sudo apt-get update更新源码的时 ...

  8. 乌班图14更新软件提示错误:https://mirrors.aliyun.com kubernetes-xenial InRelease: 由于没有公钥,无法验证下列签名: NO_PUBKEY 6A030B21BA07F4FB

    提示如下 获取: https://mirrors.aliyun.com kubernetes-xenial InRelease 忽略 https://mirrors.aliyun.com kubern ...

  9. .net mvc 微信公众号 验证微信签名

    官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN ...

随机推荐

  1. 方法(定义、调用、重载)—Java

    一. 什么是方法 不可能所有的功能都放到main中,需要定义其他方法完成指定功能,需要时调用方法即可 封装在一起来执行操作语句的集合,用来完成某个功能操作 封装在一起来执行操作语句的集合,用来完成某个 ...

  2. 用友UAP NC 单据节点_打开参照字段的问题_从打不开参照放大镜_到成功打开了但是取不到值_到修复成功

    项目的这个功能是17年开发的,但是当时没有测试通过,今年拿出来测试(通过后会上线). 有两个表数据一开始只打算用来计算时查询,没打算放到目标单据中做表体参照字段.后来改细节问题后放到目标单据中做参照字 ...

  3. JavaSE学习笔记(8)---常用类

    JavaSE学习笔记(8)---常用类 1.Object类 java.lang.Object类是Java语言中的根类,即所有类的父类.它中描述的所有方法子类都可以使用.在对象实例化的时候,最终找的父类 ...

  4. Spring学习笔记-面向切面(AOP)-04

    什么是面向切面编程 先大概了解一下部分术语 横切关注点:软件开发中,散布于多出的功能称为横切关注点(cross-cutting concern),简单的可以描述为可以影响应用多处的功能,比如日志.安全 ...

  5. JMeter-显示调试日志log

    JMeter-调试日志记录 参考文档:https://jmeter.apache.org/usermanual/hints_and_tips.html 大多数测试元素包括调试日志记录. 如果从GUI运 ...

  6. django cookie session 自定义分页

    cookie cookie的由来 http协议是无状态的,犹如人生若只如初见,每次都是初次.由此我们需要cookie来保持状态,保持客户端和服务端的数据通信. 什么是cookie Cookie具体指的 ...

  7. python3包、模块、类、方法的认识

    包>>模块>>类>> 函数 包:就是一个目录,import time from+import导入包中的部分模块 直接到类 from budaoguan.common ...

  8. VsCode开发Java SpringBoot遇到的问题

    报错截图 报错一:Build failed, Do you want to continue? 编译失败,你想继续吗? 报错二:ConfigError:The Project "Demo&q ...

  9. ipa文件信息检查工具

    项目地址:https://github.com/ryjwinner/softwares/raw/master/iOS-checkIPA.jar 项目简介: 针对近期大量iOS app需要签名,但多家签 ...

  10. PP: Think globally, act locally: A deep neural network approach to high-dimensional time series forecasting

    Problem: high-dimensional time series forecasting ?? what is "high-dimensional" time serie ...