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

/// <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}&timestamp={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}&timestamp={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();
        } 
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42139931/article/details/125874937
RSA