.net C#使用私钥sign公钥验证 验证JWS signature data

xiaoxiao2021-02-28  88

回顾:项目数据安全需要,对数据使用私钥签名,公钥验证。'RSA-SHA256'加密方式。

1.   读取证书有两种方法,第一种是直接把.pfx 安装到server里直接然后code里直接读取,第二种是直接根据证书物理物理路径和密码直接读取证书信息。推荐第一种会速度更快一些。 第一种,从server读取证书,可以根据subject名字,也可以导入时设置friendly name,查找该证书,然后一定要在管理key的属性中给iis_iusrs读取操作权限。不然private key 没有权限读取,会有error. 

        public string SignatureFormatter(string privateKeyPath, string SignatureData, string certPassword)         {                                              //第一种                                                                                       //第二种

            X509Certificate2 c3 = DataCertificate.GetCertificateFromStore("证书subject");//new X509Certificate2(privateKeyPath, certPassword, X509KeyStorageFlags.Exportable);

            string keyPrivate3 = c3.PrivateKey.ToXmlString(true);             byte[] signData = System.Text.Encoding.UTF8.GetBytes(SignatureData);              RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();             RSA.FromXmlString(keyPrivate3);             byte[] inArray = RSA.SignData(signData, CryptoConfig.MapNameToOID("SHA256"));             return Convert.ToBase64String(inArray);         }

 public static X509Certificate2 GetCertificateFromStore(string subjectName)             {                 subjectName = "CN=" + subjectName;                 X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);                 store.Open(OpenFlags.ReadOnly);                 X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;                 foreach (X509Certificate2 x509 in storecollection)                 {                     if (x509.Subject.StartsWith(subjectName))                     {                         return x509;                     }                 }                 store.Close();                 store = null;                 storecollection = null;                 return null;             }

2. 证书导入server.

 在运行中输入,mmc, 到证书管理控制台,工具栏file->add/remove snap-in->选择证书 本地电脑账户。然后导入pfx 或者 cert 证书。

 

3.验证签名。从第一步生成的signature,使用public key进行验证。我试了这两种方法都成功的。 parametersStr 是做sign之前的数据。就是元数据与signature进行比对。如果验证成功就会返回true。

                //byte[] DeFormaterSingature = Convert.FromBase64String(signature);                 //X509Certificate2 c3 = DataCertificate.GetCertificateFromStore("证书subject")                 //verify signature method 1                  //RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();                 //var publicKey = c3.PublicKey.Key.ToXmlString(false);                 //RSA.FromXmlString(publicKey);                 //RSAParameters rasPara = RSA.ExportParameters(true);                 //var test1 = RSA.VerifyData(Encoding.Unicode.GetBytes(parametersStr), "SHA256", DeFormaterSingature);                 // verify signature method 2                 //var key = (RSACryptoServiceProvider)c3.PublicKey.Key;                 //var test2 = key.VerifyData(System.Text.Encoding.Unicode.GetBytes(parametersStr), CryptoConfig.MapNameToOID("SHA256"), DeFormaterSingature);

4. 验证JWS signature. 因为项目传回来的是jws(json web signature)格式的数据。https://tools.ietf.org/html/rfc7515 这是介绍可以了解。

格式像这样,分三段,第一部分是头,是加密类型,第二部分是json数据,第三部分是返回的signature的。我们需要用第三方给的公钥进行验证。当然不验证也是可以拿到数据,但是为了安全你选择吧。

eyJhbGciOiJFUzI1NiJ9 . eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt cGxlLmNvbS9pc19yb290Ijp0cnVlfQ . DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSA pmWQxfKTUJqPP3-Kg6NU1Q

这是我的decode 代码,token 是待解密的jws数据, keyPath是public key 证书的物理路径。 第二部分的数据,可以直接decode 拿到json数据.

public string Decode(string token, string keyPath, bool verify = true)         {             string[] parts = token.Split('.');             string header = parts[0];             string content = parts[1];             var jwtSignature = parts[2];             string headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));             string bodyJson= Encoding.UTF8.GetString(Base64UrlDecode(content));             JObject bodyData = JObject.Parse(bodyJson);             if (verify)             {                 var publicCert = new X509Certificate2(keyPath);                 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();                 rsa.FromXmlString(publicCert.PublicKey.Key.ToXmlString(false));                 SHA256 sha256 = SHA256.Create();                 byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(header + '.' + content));                 RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);                 rsaDeformatter.SetHashAlgorithm("SHA256");                 if (!rsaDeformatter.VerifySignature(hash, Base64UrlDecode(jwtSignature)))                     throw new ApplicationException(string.Format("exception - Invalid signature"));             }             return bodyData .ToString();         }

如果遇到server error, 类似RSACryptoServiceProvider 不允许操作,可以设置下面 enable使用。

转载请注明原文地址: https://www.6miu.com/read-60991.html

最新回复(0)