目录
简介
函数
1.pem公钥内容转xml
2.pem私钥内容转xml
3.使用公钥对数据进行加密
4.使用私匙对待签名内容进行签名
示例
简介在调用Java后端接口,需要使用后端提供的pem私钥,在Unity中使用RSA算法对参数进行签名时,需要先将pem文件中的私钥内容转换为c#支持的xml格式再进行签名,该工具提供了转换及签名的函数,已上传至我的开发框架SKFramework中的开发工具包中,如图所示:
依赖第三方库:BouncyCastle.Crypto.dll
SKFramework开源地址:
https://github.com/136512892/SKFramework
////// 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}3.使用公钥对数据进行加密{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())); }
////// 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(); } } }