目录
简介
在调用Java后端接口,需要使用后端提供的pem私钥,在Unity中使用RSA算法对参数进行签名时,需要先将pem文件中的私钥内容转换为c#支持的xml格式再进行签名,该工具提供了转换及签名的函数,已上传至我的开发框架SKFramework中的开发工具包中,如图所示:
依赖第三方库:BouncyCastle.Crypto.dll
SKFramework开源地址:
https://github.com/136512892/SKFramework
函数
1.pem公钥内容转xml
- ///
- /// pem公钥内容转xml
- ///
- ///
- ///
- public static string Convert2XMLPublicKey(string pem)
- {
- RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pem));
- string XML = string.Format("
{0} {1} ", - Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
- Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
- return XML;
- }
2.pem私钥内容转xml
- ///
- /// pem私钥内容转xml
- ///
- /// pem私钥内容
- ///
- public static string Convert2XMLPrivateKey(string pem)
- {
- RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(pem));
- return string.Format("
{0} {1} {2}
{3}
{4} {5} {6} {7} ", - 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.使用公钥对数据进行加密
- ///
- /// RSA使用公钥对数据加密
- ///
- /// 待加密内容
- /// 公钥
- ///
- 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.使用私匙对待签名内容进行签名
- ///
- /// RSA使用私匙对签名内容加签名
- ///
- /// 代签名内容
- /// 私钥
- /// 哈希算法 默认为SHA256
- ///
- 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;
-
- ///
- /// 灵犀云会议字幕流接口Demo
- ///
- 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();
- }
- }
- }

当代野生程序猿
微信公众号
Unity开发日志分享,欢迎关注/留言/私信。


评论记录:
回复评论: