• Unity SKFramework框架(二十五)、RSA算法加密、签名工具 RSA Crypto


    目录

    简介

    函数

    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

    函数

    1.pem公钥内容转xml

    1. ///
    2. /// pem公钥内容转xml
    3. ///
    4. ///
    5. ///
    6. public static string Convert2XMLPublicKey(string pem)
    7. {
    8. RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pem));
    9. string XML = string.Format("{0}{1}",
    10. Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
    11. Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
    12. return XML;
    13. }

    2.pem私钥内容转xml 

    1. ///
    2. /// pem私钥内容转xml
    3. ///
    4. /// pem私钥内容
    5. ///
    6. public static string Convert2XMLPrivateKey(string pem)
    7. {
    8. RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(pem));
    9. return string.Format("{0}{1}

      {2}

      {3}{4}{5}{6}{7}
      "
      ,
    10. Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
    11. Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
    12. Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
    13. Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
    14. Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
    15. Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
    16. Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
    17. Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
    18. }

    3.使用公钥对数据进行加密

    1. ///
    2. /// RSA使用公钥对数据加密
    3. ///
    4. /// 待加密内容
    5. /// 公钥
    6. ///
    7. public static string EncryptWithPublicKey(string content, string publicKeyXml)
    8. {
    9. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    10. byte[] cipherbytes;
    11. rsa.FromXmlString(publicKeyXml);
    12. cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
    13. return Convert.ToBase64String(cipherbytes);
    14. }

    4.使用私匙对待签名内容进行签名

    1. ///
    2. /// RSA使用私匙对签名内容加签名
    3. ///
    4. /// 代签名内容
    5. /// 私钥
    6. /// 哈希算法 默认为SHA256
    7. ///
    8. public static byte[] SignWithPrivateKey(string sign, string privateKeyXml, string hashAlgorithm = "SHA256")
    9. {
    10. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    11. rsa.FromXmlString(privateKeyXml);
    12. byte[] dataBytes = Encoding.UTF8.GetBytes(sign);
    13. byte[] hashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
    14. return hashbyteSignature;
    15. }

    示例

    要求:

    将pem文件中的私钥内容Copy下来,需要去除首行和尾行的内容,即“-----BEGIN PRIVATE KEY-----”和“-----END PRIVATE KEY-----”:

    1. using System;
    2. using System.Text;
    3. using System.Collections;
    4. using System.Security.Cryptography;
    5. using System.Runtime.InteropServices;
    6. using BestHTTP.WebSocket;
    7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
    8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
    9. using UnityEngine;
    10. using Newtonsoft.Json;
    11. using SK.Framework.Crypto;
    12. ///
    13. /// 灵犀云会议字幕流接口Demo
    14. ///
    15. public class SubtitleExample : MonoBehaviour
    16. {
    17. //ws
    18. private WebSocket webSocket;
    19. //地址
    20. [SerializeField] private string host;
    21. //业务码ID 由字幕系统提供
    22. [SerializeField] private string buCode;
    23. //秘钥 与buCode同时提供
    24. [SerializeField] private string secret;
    25. //固定值 目前为1.0
    26. [SerializeField] private string signVersion = "1.0";
    27. //约定的appid 校验用
    28. [SerializeField] private string appid;
    29. //私钥 用于根据RSA签名算法得到签名字符串
    30. [SerializeField, TextArea]
    31. private string privateKey;
    32. //会话ID
    33. private string sid;
    34. #region >> WebSocket回调
    35. //ws建立连接回调
    36. private void OnOpen(WebSocket ws)
    37. {
    38. Debug.Log("WebSocket Open.");
    39. }
    40. //ws接收数据回调
    41. private void OnMessageReceived(WebSocket ws, string message)
    42. {
    43. Debug.Log(string.Format("WebSocket Received: {0}.", message));
    44. }
    45. //ws关闭连接回调
    46. private void OnClosed(WebSocket ws, UInt16 code, string message)
    47. {
    48. Debug.Log(string.Format("WebSocket Closed. Code:{0} Message:{1}.", code, message));
    49. webSocket = null;
    50. }
    51. //ws发生错误回调
    52. private void OnError(WebSocket ws, string error)
    53. {
    54. Debug.LogError(string.Format("WebSocket Error: {0}.", error));
    55. }
    56. #endregion
    57. //十六进制
    58. private string ByteToHex(byte[] data)
    59. {
    60. string hs = string.Empty;
    61. for (int i = 0; i < data.Length; i++)
    62. {
    63. string temp = Convert.ToString(data[i], 16);
    64. hs = temp.Length == 1 ? (hs + "0" + temp) : (hs + temp);
    65. }
    66. return hs.ToUpper();
    67. }
    68. private void OnGUI()
    69. {
    70. GUI.enabled = webSocket == null;
    71. if (GUILayout.Button("Open", GUILayout.Width(200f), GUILayout.Height(50f)))
    72. {
    73. //请求url
    74. string url = string.Format("{0}/subtitle/ws/connect", host);
    75. //时间戳
    76. TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
    77. long timestamp = Convert.ToInt64(ts.TotalMilliseconds);
    78. //Int32随机数
    79. string signNonce = UnityEngine.Random.Range(Int32.MinValue, Int32.MaxValue).ToString();
    80. //待签名内容
    81. string signContent = string.Format("buCode={0}&secret={1}×tamp={2}&signNonce={3}&signVersion={4}&appid={5}",
    82. buCode, secret, timestamp, signNonce, signVersion, appid);
    83. Debug.Log(string.Format("待签名内容:{0}", signContent));
    84. //签名
    85. string sign = ByteToHex(RSACrypto.SignWithPrivateKey(signContent, RSACrypto.Convert2XMLPrivateKey(privateKey)));
    86. Debug.Log(string.Format("签名: {0}", sign));
    87. //最终请求地址
    88. 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}",
    89. url, "cn", "speex", appid, "", buCode, timestamp, signNonce, signVersion, sign, appid);
    90. Debug.Log(string.Format("Uri: {0}", address));
    91. webSocket = new WebSocket(new Uri(address));
    92. webSocket.OnOpen += OnOpen;
    93. webSocket.OnMessage += OnMessageReceived;
    94. webSocket.OnClosed += OnClosed;
    95. webSocket.OnError += OnError;
    96. webSocket.Open();
    97. }
    98. }
    99. }
  • 相关阅读:
    浅谈自媒体运营
    SVN安装教程
    Unity2D创建帧动画片段
    主播产品话术
    你准备好启动推荐计划了吗?
    java毕业设计畅言情感互助网站mybatis+源码+调试部署+系统+数据库+lw
    适用于顺序磁盘访问的1分钟法则
    kubeadm安装高可用k8s集群
    CentOs/Ubuntu 一行指令安装Docker
    【安装填坑】-import win32api, sys, os ImportError: DLL load failed: 找不到指定的模块。
  • 原文地址:https://blog.csdn.net/qq_42139931/article/details/125874937