本文固定鏈接***
SM2-SM4 c#加密與OpenSSL交互
Encryption SM2-SM4 C# interacts with OpenSSL
最近在搗騰國密2、3、4,很顯然,C#,尤其是Unity需要用到BouncyCastle這個dll(在我這個csdn下載裏有源碼以及dll下載,賺點小幣幣,以後喫喝嫖賭啥的關顧小主們就可以肆無忌憚了)這裏總結一下C# 使用國密即SM2-SM4的事情,同時跟大家描繪一下C#的SM2-SM4跟C++的OpenSSL是咋相互加密解密的。
首先是下載一個BouncyCastle,導入Unity或者Winform之類的(本質有啥區別?沒有,都是.net的東西)。鏈接如下:
bccrypto-csharp-1.8.5 dll
c# bccrypto-csharp-1.8.5源碼
(額,這裏放得都是我自己CSDN的鏈接,當然了,你去別的地方下載我不會怪你的。反正是要捶你小胸胸纔行)
下載後導入Unity/VisualStudio之類的裏面。我這裏用Unity作爲例子,並且我下載的是源碼,因爲方便調試查問題。如圖:
導入好後就可以開始幹活了。因爲這玩意是國際Csharp版本的必要內容。
接下來我們來徜徉一下SM的內容,這個其實網上也有版本,但是你下載後會發現,除了跟自己加解密暢通之外,跟其他的那簡直是💩。我這裏截個圖:
注意,這個地方有個SM4RepairVersion,說明單單SM4我改得有點多。細節部分暫時不去說了。
因爲說不完。哇咔咔。
啥都沒有說,總要說點啥,那就舉個例子吧。反正左手痛,也不知道昨晚上幹啥了。作爲一個有伴侶的人,左手痛,只能是壓的。
先放張圖:
再放一張:
再放一張:
反正就是這幾張圖實現了國密SM2獲取public key和private key並且對123456進行加密和對加密結果自己解密。(注意,此處還只是淡出的Csharp版本,並沒有openssl的事情)
這裏直接整代碼:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using CDRW.SM.SAMPLE;
using CDRW.SM;
using CDRW.EXT;
using CDRW.SM.Data;
namespace CDRW.SM.SAMPLE
{
public class EncryptDecrypt_SM23 : MonoBehaviour
{
private InputField mPubInputField;
private InputField mPriInputField;
private InputField mEnDecryptInputField;
private InputField mResultInputField;
private Button mPubPriKeyButton;
private Button mEncryptButton;
private Button mDecryptButton;
void Start()
{
mPubInputField = gameObject.GetChildUIScript<InputField>("PubLabel/Key");
mPriInputField = gameObject.GetChildUIScript<InputField>("PriLabel/Key");
mEnDecryptInputField = gameObject.GetChildUIScript<InputField>("EnDecryptLabel/Key");
mResultInputField = gameObject.GetChildUIScript<InputField>("ResultLabel/Key");
mPubPriKeyButton = gameObject.GetChildUIScript<Button>("PubPriButton");
mPubPriKeyButton.onClick.AddListener(PubPriKey);
mEncryptButton = gameObject.GetChildUIScript<Button>("EncryptButton");
mEncryptButton.onClick.AddListener(DoEncrypt);
mDecryptButton = gameObject.GetChildUIScript<Button>("DecryptButton");
mDecryptButton.onClick.AddListener(DoDecrypt);
mEnDecryptInputField.text = string.Empty;
mResultInputField.text = "show result";
mPubInputField.text = "";
mPriInputField.text = "";
mEnDecryptInputField.text = "123456";
}
private void PubPriKey()
{
//獲取公鑰、私鑰的方法
SM2Utils.GenerateKeyPair(out string publicKey, out string privateKey);
mPubInputField.text = publicKey;
mPriInputField.text = privateKey;
}
private void DoEncrypt()
{
string content = mEnDecryptInputField.text;
if (string.IsNullOrWhiteSpace(mPubInputField.text))
{
PubPriKey();
}
if (string.IsNullOrWhiteSpace(content))
{
mResultInputField.text = "Error no Input Content";
return;
}
try
{
string en = SM2Utils.Encrypt(mPubInputField.text, content);
mResultInputField.text = en;
}
catch (Exception e)
{
mResultInputField.text = e.ToString();
}
}
private void DoDecrypt()
{
string content = mEnDecryptInputField.text;
if (string.IsNullOrWhiteSpace(mPriInputField.text))
{
PubPriKey();
}
if (string.IsNullOrWhiteSpace(content))
{
mResultInputField.text = "Error no Input Content";
return;
}
try
{
string en =DataUtil.ChangeCode(SM2Utils.Decrypt(mPriInputField.text, content, false));
mResultInputField.text = en;
}
catch (Exception e)
{
mResultInputField.text = e.ToString();
}
}
private void OnDestroy()
{
mEncryptButton?.onClick.RemoveListener(DoEncrypt);
mEncryptButton?.onClick.RemoveListener(DoDecrypt);
}
}
}
當然,我承認錯誤,我沒有寫註釋。
SM3其實已經包含在內了,而且SM3沒啥好說的,就算了。
那麼SM4咧,這玩意內容多。得好好整。先看個圖:
再看一張
這個玩意其實也差不多,用的ECB,後續會擴展開來,現在手痛。
上代碼:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using CDRW.SM;
using System.Text;
using Org.BouncyCastle.Utilities.Encoders;
using CDRW.EXT;
namespace CDRW.SM.SAMPLE
{
public class EncryptDecrypt_SM4 : MonoBehaviour
{
private InputField mKeyInputField;
private InputField mDataInputField;
private InputField mResultInputField;
private Button mECBEncryptButton;
private Button mECBDecryptButton;
private SM4RepairVersion.SM4Utils sm4;
void Start()
{
mKeyInputField = gameObject.GetChildUIScript<InputField>("KeyLabel/Key");
mDataInputField = gameObject.GetChildUIScript<InputField>("DataKeyLabel/Key");
mResultInputField = gameObject.GetChildUIScript<InputField>("ResultKeyLabel/Key");
mECBEncryptButton = gameObject.GetChildUIScript<Button>("EncryptButton");
mECBDecryptButton = gameObject.GetChildUIScript<Button>("DecryptButton");
mKeyInputField.text = "0123456789ABCDEFFEDCBA9876543210";
mDataInputField.text = "FEDCBA98765432100123456789ABCDEF";
mResultInputField.text = "";
mECBEncryptButton.onClick.AddListener(OnECBEncryptClick);
mECBDecryptButton.onClick.AddListener(OnECBDecryptClick);
sm4 = new SM4RepairVersion.SM4Utils();
sm4.hexString = true;
}
private void OnECBEncryptClick()
{
string key = mKeyInputField.text;
if (string.IsNullOrWhiteSpace(key))
{
mResultInputField.text = "the key is null";
return;
}
string content = mDataInputField.text;
if (string.IsNullOrWhiteSpace(content))
{
mResultInputField.text = "the data is null";
return;
}
sm4.secretKey = key;
var info =sm4.Encrypt_ECB(content);
mResultInputField.text = info;
}
private void OnECBDecryptClick()
{
string key = mKeyInputField.text;
if (string.IsNullOrWhiteSpace(key))
{
mResultInputField.text = "the key is null";
return;
}
string content = mDataInputField.text;
if (string.IsNullOrWhiteSpace(content))
{
mResultInputField.text = "the data is null";
return;
}
sm4.secretKey = key;
string enECBR = sm4.Decrypt_ECB(content);
mResultInputField.text =enECBR;
}
private void OnDestroy()
{
mECBEncryptButton?.onClick.RemoveListener(OnECBEncryptClick);
mECBDecryptButton?.onClick.RemoveListener(OnECBDecryptClick);
}
}
}
請允許我再次說明,我沒有寫註釋。因爲我手痛。
以上內容無足輕重,因爲網上也有類似的,不過是我改了下代碼讓他們跟OpenSSL能發生化學反應。
下面看看OpenSSL的。先上圖,內容包含SM2-SM4所有內容:
可以發現OpenSSL跟C#產生的基本上沒區別,這裏有心的朋友注意回看上面的。
下面看看C#跟OpenSSL之間的交互過程。本來這裏要寫個簡單的收發過程的,但是我手痛。你懂得。
到這裏細心的朋友已經發現了,整個過程,從開始到結束都很完美。
額。。。。。。
代碼截圖如下:
分不同的場景來做的,截圖如下:
額。。。。。。這些東東都是摸索出來的。額。。。。。。。。我手痛。。。。。額。。。。。。下次發鏈接吧。今天。。。。。。。。手痛。。。。。。。
還有就是拜託留言的朋友彆着急。
下次。。。。
發下載鏈接,今天先開個頭。。。。。。
額。。。。。。。。
。。。。。。手痛。。。。。。