基于C#实现SM2加签验签工具

 更新时间:2024年10月21日 10:21:02   作者:天天代码码天天  
这篇文章主要为大家详细介绍了如何基于C#实现一个SM2加签验签工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

效果

项目

代码

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Asn1.GM;
using System;
using System.Text;
using System.Windows.Forms;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Security;
using System.Linq;
 
namespace SM2VerifySignTool
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        int toDigit(char ch, int index)
        {
            int digit = Convert.ToInt32(ch.ToString(), 16);
            if (digit == -1)
            {
                throw new SystemException("Illegal hexadecimal character " + ch + " at index " + index);
            }
            return digit;
        }
 
        string HexToBase64(string hexString)
        {
            byte[] bytes = Enumerable.Range(0, hexString.Length)
                                     .Where(x => x % 2 == 0)
                                     .Select(x => Convert.ToByte(hexString.Substring(x, 2), 16))
                                     .ToArray();
            return Convert.ToBase64String(bytes);
        }
 
        byte[] hexStrToByte(String hexStr)
        {
            if ((null == hexStr) || (hexStr.Length == 0))
            {
                return null;
            }
            char[] hexData = hexStr.ToCharArray();
            int len = hexData.Length;
            if ((len & 0x1) != 0)
            {
                throw new SystemException("Odd number of characters.");
            }
            byte[] out1 = new byte[len >> 1];
            int i = 0;
            for (int j = 0; j < len; i++)
            {
                int f = toDigit(hexData[j], j) << 4;
                j++;
                f |= toDigit(hexData[j], j);
                j++;
                out1[i] = ((byte)(f & 0xFF));
            }
            return out1;
        }
 
        X9ECParameters x9ec = GMNamedCurves.GetByName("SM2P256V1");
 
 
        /**
        *生成
        */
        void GenerateKey(out string pubkeyStr, out string prikeyStr)
        {
            var g = new ECKeyPairGenerator();
            g.Init(new ECKeyGenerationParameters(new ECDomainParameters(x9ec), new SecureRandom()));
            var k = g.GenerateKeyPair();
            byte[] pubkey = ((ECPublicKeyParameters)k.Public).Q.GetEncoded(false);
            byte[] privkey = ((ECPrivateKeyParameters)k.Private).D.ToByteArray();
            prikeyStr = BitConverter.ToString(privkey).Replace("-", "");
            pubkeyStr = BitConverter.ToString(pubkey).Replace("-", "");
        }
 
        /**
        *加签
        */
        string Sign(string prikeyStr, string data)
        {
            byte[] msg = Encoding.UTF8.GetBytes(data);
            byte[] priKey = hexStrToByte(prikeyStr);
            SM2Signer sm2Signer = new SM2Signer();
            ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, priKey), new ECDomainParameters(x9ec));
 
            sm2Signer.Init(true, privateKeyParameters);
            sm2Signer.BlockUpdate(msg, 0, msg.Length);
            return Hex.ToHexString(sm2Signer.GenerateSignature());
        }
 
 
        /*
        * 验签
        */
        bool verifySign(string pubkeyStr, string data, string sign)
        {
            byte[] signHex = hexStrToByte(sign);
            byte[] pubkey = hexStrToByte(pubkeyStr);
            byte[] msgByte = Encoding.UTF8.GetBytes(data);
            SM2Signer sm2Signer = new SM2Signer();
            ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(x9ec.Curve.DecodePoint(pubkey), new ECDomainParameters(x9ec));
            sm2Signer.Init(false, publicKeyParameters);
            sm2Signer.BlockUpdate(msgByte, 0, msgByte.Length);
            return sm2Signer.VerifySignature(signHex);
        }
 
        private void btnVerify_Click(object sender, EventArgs e)
        {
            txtResult.Text = "";
            try
            {
                string pubk = txtPubkey.Text;
                string data = txtData.Text;
                string sign = txtSign.Text;
                bool b = verifySign(pubk, data, sign);
                if (b)
                {
                    txtResult.Text = "验证成功";
                }
                else
                {
                    txtResult.Text = "验证失败";
                }
            }
            catch (Exception ex)
            {
                txtResult.Text = "验证异常:" + ex.Message;
            }
        }
 
        /// <summary>
        /// Base64字符串转Hex字符串↓
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] bytes = Convert.FromBase64String(txtBase64.Text); // 将base64字符串转换为byte数组
                string hexString = BitConverter.ToString(bytes).Replace("-", ""); // 将byte数组转换为Hex字符串
                txtHex.Text = hexString;
            }
            catch (Exception ex)
            {
                txtHex.Text = "转换异常:" + ex.Message;
            }
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            //string pubkeyStr = "";
            //string prikeyStr = "";
            //GenerateKey(out pubkeyStr, out prikeyStr);
            //txtPriKey.Text = prikeyStr;
            //txtPubkey.Text = pubkeyStr;
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                string prik = txtPriKey.Text;
                string data = txtData.Text;
                txtSign.Text = Sign(prik, data);
            }
            catch (Exception ex)
            {
                txtSign.Text = "加签识别:" + ex.Message;
            }
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            string pubkeyStr = "";
            string prikeyStr = "";
            GenerateKey(out pubkeyStr, out prikeyStr);
            txtPriKey.Text = prikeyStr;
            txtPubkey.Text = pubkeyStr;
        }
 
        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                string hexString = txtHex.Text;
                string base64String = HexToBase64(hexString);
                txtBase64.Text = base64String;
            }
            catch (Exception ex)
            {
                txtBase64.Text = "转换异常:" + ex.Message;
            }
        }
 
        private void button5_Click(object sender, EventArgs e)
        {
            try
            {
                string originalString = txtStr.Text;
                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(originalString);
                string base64String = Convert.ToBase64String(bytes);
                txtBase64.Text = base64String;
            }
            catch (Exception ex)
            {
                txtBase64.Text = "编码异常:" + ex.Message;
            }
        }
 
        private void button6_Click(object sender, EventArgs e)
        {
            try
            {
                string base64String = txtBase64.Text;
                byte[] bytes = Convert.FromBase64String(base64String);
                string decodedString = Encoding.UTF8.GetString(bytes);
                txtStr.Text = decodedString;
            }
            catch (Exception ex)
            {
                txtStr.Text = "解码异常:" + ex.Message;
            }
        }
    }
}

到此这篇关于基于C#实现SM2加签验签工具的文章就介绍到这了,更多相关C#SM2加签验签内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Unity游戏开发之2048游戏的实现

    Unity游戏开发之2048游戏的实现

    2048是一款数字益智游戏,初始数字则是由2+2组成的基数4。在操作方面的不同则表现为一步一格的移动,变成更为爽快的一次到底。相同数字的方况在靠拢、相撞时会相加。本文将通过Unity3D实现这一游戏,需要的可以参考一下
    2022-03-03
  • C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法

    C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法

    这篇文章主要介绍了C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法,涉及C#多线程操作读写锁定的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • C#实现tostring转换成16进制的方法

    C#实现tostring转换成16进制的方法

    本文介绍了在C#中将整数、字节数组、字符串转换为十六进制字符串,以及将十六进制字符串转换回整数的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-02-02
  • Unity UGUI的Outline描边组件的介绍使用示例

    Unity UGUI的Outline描边组件的介绍使用示例

    这篇文章主要介绍了Unity UGUI的Outline描边组件的介绍使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • C#机器入门学习之判断日报是否合格详解

    C#机器入门学习之判断日报是否合格详解

    这篇文章主要给大家介绍了关于C#机器入门学习之判断日报是否合格的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用c#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • 带着问题读CLR via C#(笔记一)CLR的执行模型

    带着问题读CLR via C#(笔记一)CLR的执行模型

    CLR (Common Language Runtime) 是一个可以由多种编程语言使用的“运行时”。
    2013-04-04
  • C# 实现特殊字符快速转码

    C# 实现特殊字符快速转码

    这篇文章主要介绍了C# 实现特殊字符快速转码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • C#与C++与互操作实例讲解

    C#与C++与互操作实例讲解

    在本篇文章里小编给大家整理了关于C#与C++与互操作实例以及相关内容,需要的朋友们可以学习下。
    2019-08-08
  • winform 中显示异步下载的图片

    winform 中显示异步下载的图片

    本文主要介绍利用WebClient异步下载图片,显示在GridView上,需要的朋友可以参考下。
    2016-05-05
  • C#并行编程之PLINQ(并行LINQ)

    C#并行编程之PLINQ(并行LINQ)

    这篇文章介绍了C#并行编程之PLINQ(并行LINQ),文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05

最新评论