目录
一.前言
C++提供了windows和linux的两种库,netcore调用并实现.
二.netcore调用
1.windows库引用dll文件
public static class VVSecurity_win32
{
private const string dllName = "Lib/vvsec_win32/VVSecurity.dll";
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_Initlize(IntPtr pDevice, string pUserPin);
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_SM4EncryptData(DEVICE_HANDLE pDevice, PKI_DATA plaintext, ref PKI_DATA ciphertext);
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_SM4DecryptData(DEVICE_HANDLE pDevice, PKI_DATA ciphertext, ref PKI_DATA plaintext);
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_Finalize(DEVICE_HANDLE pDevice);
}
2.linux库引用so文件
public static class VVSecurity_centos64
{
private const string dllName = "Lib/vvsec_centosx64/VVSecurity.so";
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_Initlize(IntPtr pDevice, string pUserPin);
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_SM4EncryptData(DEVICE_HANDLE pDevice, PKI_DATA plaintext, ref PKI_DATA ciphertext);
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_SM4DecryptData(DEVICE_HANDLE pDevice, PKI_DATA ciphertext, ref PKI_DATA plaintext);
[DllImport(dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int VVSec_Finalize(DEVICE_HANDLE pDevice);
}
3.C++接口所需结构体
public struct DEVICE_HANDLE
{
public uint hdev { get; set; }
public uint hcont { get; set; }
public uint happ { get; set; }
}
/// <summary>
/// 加解密结构体:用句柄接收byte[]返回值
/// </summary>
public struct PKI_DATA
{
/// <summary>
/// value的长度,以16位单位增长.加密后的密文存储空间需要计算.
/// </summary>
public int size { get; set; }
/// <summary>
/// 值:byte[]句柄
/// </summary>
public IntPtr value { get; set; }
}
4.实现帮助类/返回结果类
public static class VVSecurityHelper
{
public static bool IsSuccessVVSecInit { get { return _issSuccessVVSecInit; } }
private static bool _issSuccessVVSecInit = false;
private static object _lockEncrypt = new object();//加密锁
private static object _lockDecrypt = new object();//解密锁
#region 处理后的加解密
private static DEVICE_HANDLE _deviceHandle = new DEVICE_HANDLE();
public static VVSecResult Init(string pUserPin = null)
{
try
{
DEVICE_HANDLE dh = new DEVICE_HANDLE();
GCHandle initlizeHandle = GCHandle.Alloc(dh, GCHandleType.Pinned);
var pdevice = Marshal.AllocHGlobal(12);
Marshal.StructureToPtr(dh, pdevice, false);
int code = 0;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
#region 设置动态库路径
StreamWriter sw = new StreamWriter("aavs.sh", false, Encoding.ASCII);
string dirPath = Path.Combine(Directory.GetCurrentDirectory(), "Lib/vvsec_centosx64").Trim('/').Replace("/", "\\/");
sw.WriteLine($"sed -i '/{dirPath}/d' /etc/ld.so.conf");//删除配置项
sw.WriteLine($"echo '{Directory.GetCurrentDirectory()}/Lib/vvsec_centosx64'>>/etc/ld.so.conf");//增加配置项
sw.WriteLine("ldconfig");
sw.Close();
Process process = new Process();
process.StartInfo.FileName = "sh";
process.StartInfo.Arguments = "aavs.sh";
process.Start();
process.WaitForExit();
process.Close();
#endregion
code = VVSecurity_centos64.VVSec_Initlize(pdevice, pUserPin);
}
else
{
code = VVSecurity_win32.VVSec_Initlize(pdevice, pUserPin);
}
Console.WriteLine($"安全加密.初始化:状态码{code}");
_issSuccessVVSecInit = code == 0;
_deviceHandle = Marshal.PtrToStructure<DEVICE_HANDLE>(pdevice);
initlizeHandle.Free();
return new VVSecResult { code = code };
}
catch (Exception ex)
{
Console.WriteLine("安全加密初始化异常:" + ex.ToString());
return new VVSecResult { code = -2, msessage = ex.ToString() };
}
}
public static VVSecResult Encrypt(string plaintextStr)
{
//初始化未成功,原文返回
if (!_issSuccessVVSecInit) return new VVSecResult { code = -1, text = plaintextStr };
//空内容
if (string.IsNullOrEmpty(plaintextStr)) return new VVSecResult { code = 0, text = "" };
lock (_lockEncrypt)
{
//明文
byte[] plaintextBt = Encoding.UTF8.GetBytes(plaintextStr);
var plaintextGCH = GCHandle.Alloc(plaintextBt, GCHandleType.Pinned);
PKI_DATA plaintextData = new PKI_DATA() { size = plaintextBt.Length, value = plaintextGCH.AddrOfPinnedObject() };
plaintextGCH.Free();
//密文
var ciphertextLen = (plaintextBt.Length / 16 + 1) * 16;//以16为单位增长
byte[] ciphertextBt = new byte[ciphertextLen];
var ciphertextGCH = GCHandle.Alloc(ciphertextBt, GCHandleType.Pinned);
PKI_DATA ciphertextData = new PKI_DATA() { size = ciphertextLen, value = ciphertextGCH.AddrOfPinnedObject() };
int code = 0;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
code = VVSecurity_centos64.VVSec_SM4EncryptData(_deviceHandle, plaintextData, ref ciphertextData);
}
else
{
code = VVSecurity_win32.VVSec_SM4EncryptData(_deviceHandle, plaintextData, ref ciphertextData);
}
var byteArr = (byte[])ciphertextGCH.Target;//密文返回值
var plaintextResult = code == 0 ? Convert.ToBase64String(byteArr) : "";
ciphertextGCH.Free();
var result = new VVSecResult() { code = code, text = plaintextResult };
return result;
}
}
public static VVSecResult Decrypt(string ciphertextBase64)
{
//初始化未成功,原文返回
if (!_issSuccessVVSecInit) return new VVSecResult { code = -1, text = ciphertextBase64 };
//空内容
if (string.IsNullOrEmpty(ciphertextBase64)) return new VVSecResult { code = 0, text = "" };
lock (_lockDecrypt)
{
byte[] ciphertextBt = null;
try
{
ciphertextBt = Convert.FromBase64String(ciphertextBase64);
}
catch (Exception)
{
return new VVSecResult { code = -3, text = "" };//要解密的字符串不是base64内容
}
//空密文直接返回
if (ciphertextBt == null || ciphertextBt.Length == 0) return new VVSecResult { code = 0, text = "" };
//密文
var ciphertextGCH = GCHandle.Alloc(ciphertextBt, GCHandleType.Pinned);
PKI_DATA ciphertextData = new PKI_DATA() { size = ciphertextBt.Length, value = ciphertextGCH.AddrOfPinnedObject() };
ciphertextGCH.Free();
//明文
byte[] plaintextBt = new byte[ciphertextBt.Length];
var plaintextGCH = GCHandle.Alloc(plaintextBt, GCHandleType.Pinned);
PKI_DATA plaintextData = new PKI_DATA() { size = plaintextBt.Length, value = plaintextGCH.AddrOfPinnedObject() };
int code = 0;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
code = VVSecurity_centos64.VVSec_SM4DecryptData(_deviceHandle, ciphertextData, ref plaintextData);
}
else
{
code = VVSecurity_win32.VVSec_SM4DecryptData(_deviceHandle, ciphertextData, ref plaintextData);
}
var byteArr = (byte[])plaintextGCH.Target;//明文byte数组
plaintextGCH.Free();
var text = Encoding.UTF8.GetString(byteArr).Replace("\0", "");//去掉明文中的空位
var result = new VVSecResult() { code = code, text = text };
return result;
}
}
#endregion
}
public class VVSecResult
{
/// <summary>
/// 状态码:0成功,其他失败
/// </summary>
public int code { get; set; }
/// <summary>
/// 加密后的base64密文 / 解密后的明文
/// </summary>
public string text { get; set; }
public string msessage { get; set; }
}