Unity SKFramework框架(二十五)、RSA算法加密、签名工具 RSA Crypto
2023-06-13 09:11:38 时间
简介
在调用Java后端接口,需要使用后端提供的pem私钥,在Unity中使用RSA算法对参数进行签名时,需要先将pem文件中的私钥内容转换为c#支持的xml格式再进行签名,该工具提供了转换及签名的函数,已上传至我的开发框架SKFramework中的开发工具包中,如图所示:
依赖第三方库:BouncyCastle.Crypto.dll
SKFramework开源地址:
https://github.com/136512892/SKFramework
函数
1.pem公钥内容转xml
/// <summary>
/// pem公钥内容转xml
/// </summary>
/// <param name="publicKey"></param>
/// <returns></returns>
public static string Convert2XMLPublicKey(string pem)
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pem));
string XML = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
return XML;
}
2.pem私钥内容转xml
/// <summary>
/// pem私钥内容转xml
/// </summary>
/// <param name="pem">pem私钥内容</param>
/// <returns></returns>
public static string Convert2XMLPrivateKey(string pem)
{
RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(pem));
return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
}
3.使用公钥对数据进行加密
/// <summary>
/// RSA使用公钥对数据加密
/// </summary>
/// <param name="content">待加密内容</param>
/// <param name="publicKeyXml">公钥</param>
/// <returns></returns>
public static string EncryptWithPublicKey(string content, string publicKeyXml)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(publicKeyXml);
cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
return Convert.ToBase64String(cipherbytes);
}
4.使用私匙对待签名内容进行签名
/// <summary>
/// RSA使用私匙对签名内容加签名
/// </summary>
/// <param name="sign">代签名内容</param>
/// <param name="privateKeyXml">私钥</param>
/// <param name="hashAlgorithm">哈希算法 默认为SHA256</param>
/// <returns></returns>
public static byte[] SignWithPrivateKey(string sign, string privateKeyXml, string hashAlgorithm = "SHA256")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(privateKeyXml);
byte[] dataBytes = Encoding.UTF8.GetBytes(sign);
byte[] hashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
return hashbyteSignature;
}
示例
要求:
将pem文件中的私钥内容Copy下来,需要去除首行和尾行的内容,即“-----BEGIN PRIVATE KEY-----”和“-----END PRIVATE KEY-----”:
using System;
using System.Text;
using System.Collections;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using BestHTTP.WebSocket;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
using UnityEngine;
using Newtonsoft.Json;
using SK.Framework.Crypto;
/// <summary>
/// 灵犀云会议字幕流接口Demo
/// </summary>
public class SubtitleExample : MonoBehaviour
{
//ws
private WebSocket webSocket;
//地址
[SerializeField] private string host;
//业务码ID 由字幕系统提供
[SerializeField] private string buCode;
//秘钥 与buCode同时提供
[SerializeField] private string secret;
//固定值 目前为1.0
[SerializeField] private string signVersion = "1.0";
//约定的appid 校验用
[SerializeField] private string appid;
//私钥 用于根据RSA签名算法得到签名字符串
[SerializeField, TextArea]
private string privateKey;
//会话ID
private string sid;
#region >> WebSocket回调
//ws建立连接回调
private void OnOpen(WebSocket ws)
{
Debug.Log("WebSocket Open.");
}
//ws接收数据回调
private void OnMessageReceived(WebSocket ws, string message)
{
Debug.Log(string.Format("WebSocket Received: {0}.", message));
}
//ws关闭连接回调
private void OnClosed(WebSocket ws, UInt16 code, string message)
{
Debug.Log(string.Format("WebSocket Closed. Code:{0} Message:{1}.", code, message));
webSocket = null;
}
//ws发生错误回调
private void OnError(WebSocket ws, string error)
{
Debug.LogError(string.Format("WebSocket Error: {0}.", error));
}
#endregion
//十六进制
private string ByteToHex(byte[] data)
{
string hs = string.Empty;
for (int i = 0; i < data.Length; i++)
{
string temp = Convert.ToString(data[i], 16);
hs = temp.Length == 1 ? (hs + "0" + temp) : (hs + temp);
}
return hs.ToUpper();
}
private void OnGUI()
{
GUI.enabled = webSocket == null;
if (GUILayout.Button("Open", GUILayout.Width(200f), GUILayout.Height(50f)))
{
//请求url
string url = string.Format("{0}/subtitle/ws/connect", host);
//时间戳
TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
long timestamp = Convert.ToInt64(ts.TotalMilliseconds);
//Int32随机数
string signNonce = UnityEngine.Random.Range(Int32.MinValue, Int32.MaxValue).ToString();
//待签名内容
string signContent = string.Format("buCode={0}&secret={1}×tamp={2}&signNonce={3}&signVersion={4}&appid={5}",
buCode, secret, timestamp, signNonce, signVersion, appid);
Debug.Log(string.Format("待签名内容:{0}", signContent));
//签名
string sign = ByteToHex(RSACrypto.SignWithPrivateKey(signContent, RSACrypto.Convert2XMLPrivateKey(privateKey)));
Debug.Log(string.Format("签名: {0}", sign));
//最终请求地址
string address = string.Format("{0}?lang={1}&codec={2}&appid={3}&extend={4}&buCode={5}×tamp={6}&signNonce={7}&signVersion={8}&sign={9}&appid={10}",
url, "cn", "speex", appid, "", buCode, timestamp, signNonce, signVersion, sign, appid);
Debug.Log(string.Format("Uri: {0}", address));
webSocket = new WebSocket(new Uri(address));
webSocket.OnOpen += OnOpen;
webSocket.OnMessage += OnMessageReceived;
webSocket.OnClosed += OnClosed;
webSocket.OnError += OnError;
webSocket.Open();
}
}
}
相关文章
- 为了测试未知来源的算法题,我写了一个本地刷题工具!
- [算法]-最短路径算法总结「建议收藏」
- [推荐算法]基于用户的协同过滤算法「建议收藏」
- 天池算法大赛项目:基于大规模日志的故障诊断亚军方案!
- python-louvain_louvin算法
- AI 算法成了裁员工具,HR:这样做能减少愧疚感
- (六)算法基础——动态规划
- 手写现代前端框架diff算法
- 分布式场景全局唯一ID生成工具类(非雪花算法)
- 【Android 安全】DEX 加密 ( Java 工具开发 | 加密解密算法 API | 编译代理 Application 依赖库 | 解压依赖库 aar 文件 )
- 【计算理论】图灵机 ( 非确定性图灵机 -> 确定性图灵机 | 模仿过程示例 | 算法的数学模型 )
- Redis实现雪花算法高效生成唯一ID(redis 雪花id)
- jsLZ77算法的实现代码