开发中遇到某个模块的表单需要发布给匿名用户填写,想到了RSA签名对URL进行签名处理来做,代码很多,贴上的是符合自己开发的,需要注意的是Convert.FromBase64String这个函数的传参,用PrivateKey对发布的URL参数Content进行签名,再用PublicKey验证签名,需要注意对PublicKey和PrivateKey的理解。
首先生成PrivateKey和PublicKey,代码如下:
/// <summary> /// RSA产生密钥 /// </summary> /// <param name="xmlKeys">私钥</param> /// <param name="xmlPublicKey">公钥</param> public void RSAKey(out string xmlKeys, out string xmlPublicKey) { try { System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); xmlKeys = rsa.ToXmlString(true); xmlPublicKey = rsa.ToXmlString(false); } catch (Exception ex) { throw ex; } }
签名代码如下:
#region RSA 签名验证 /// <summary> /// RSA签名 /// </summary> /// <param name="privateKey">私钥</param> /// <param name="content">需签名的数据</param> /// <returns>签名后的值</returns> public static string SignatureFormatter(string privateKey, string content) { var hashData = GetHash(content); RSACryptoServiceProvider key = new RSACryptoServiceProvider(); key.FromXmlString(privateKey); RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key); formatter.SetHashAlgorithm("SHA1"); byte[] inArray = formatter.CreateSignature(hashData); return Convert.ToBase64String(inArray).Replace("/", "_"); } /// <summary> /// RSA验证 /// </summary> /// <param name="publicKey">公钥</param> /// <param name="hashData">Hash描述</param> /// <param name="signature">签名后的结果</param> /// <returns></returns> public static bool ValidateSignature(string publicKey, byte[] hashData, string signature) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(publicKey); RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa); rsaDeformatter.SetHashAlgorithm("SHA1"); var deformatterData = Convert.FromBase64String(signature); return rsaDeformatter.VerifySignature(hashData, deformatterData); } /// <summary> /// Hash算法 /// </summary> /// <param name="content"></param> /// <returns></returns> public static byte[] GetHash(string content) { var buffer = Encoding.GetEncoding("UTF-8").GetBytes(content); var sha = HashAlgorithm.Create("SHA1"); return sha?.ComputeHash(buffer); } #endregion
最后在请求表单时做认证
/// <summary> /// 获取专项信息 /// </summary> /// <param name="detailId"></param> /// <param name="signCode"></param> /// <returns></returns> [Route("get-zxjc-task/{detailId}/{signCode}"), HttpGet, AllowAnonymous] public ApiResultModel<SaveZxjcDetailModel> GetZxjcTaskModel(string detailId, string signCode) { var hashStr = _zxjcRecordProvider.GetHashStr(detailId); var hashData = RsaCryption.GetHash(hashStr); if (RsaCryption.ValidateSignature(publicKey, hashData, signCode.Replace("_", "/"))) { var result = _zxjcRecordProvider.GetZxjcTaskModel(detailId); return this.Success(result); } else return new ApiResultModel<SaveZxjcDetailModel>(); }