.NET core AES-128/GCM + BASE64算法加密 实名认证


网上找了一圈,发现.NET core关于本次实名认证

https://wlc.nppa.gov.cn/2021/02/25/16e2520acd9f4404897ed1a5b8fd1240.pdf

相关博客没有,根据node.js的代码用.NET core实现,然后分享给大家

aes具体的算法就不赘述了,详情可以看

https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aesgcm?view=net-5.0

提几个比较关键的点

1、nonce是固定12位,被加在密文的前面

2、tag是16位,被加在密文的后面

3、key是32位的16进制的字符串,使用时要根据对应函数转化成byte[]

4、测试的密文总长度是136位,经过base64解码之后是102位,原文的长度是74位,加上nonce(12位)与tag(16位)正好是102位

下面是测试代码,环境是.NET core 3.1

using System;
using System.Security.Cryptography;
using System.Text;

namespace aesgcmtest
{
    class Program
    {
        //16进制string转byte[]
        public static byte[] StrToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "", StringComparison.CurrentCulture);
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }
        public static string Decrypt(string hexStrKey, string base64Cliper)
        {
            //1.将16进制的密钥转化为byte数组
            var key = StrToHexByte(hexStrKey);
            //2.将base64格式的密文转化为byte数组136位->102位
            var cliper = Convert.FromBase64String(base64Cliper);
            var nonce = new byte[12];
            var tag = new byte[16];
            var clipertext = new byte[cliper.Length - 28];
            var plaintext = new byte[cliper.Length - 28];
            //3.密文的前12位为nonce
            Array.ConstrainedCopy(cliper, 0, nonce, 0, 12);
            //4.密文的后16位为tag
            Array.ConstrainedCopy(cliper, cliper.Length - 16, tag, 0, 16);
            //5.密文长度与加密原文长度一致
            Array.ConstrainedCopy(cliper, 12, clipertext, 0, cliper.Length - 28);
            //6.解密
            using var aesGcm = new AesGcm(key);
            aesGcm.Decrypt(nonce, clipertext, tag, plaintext);
            //7.将byte数组转化为string并返回
            return Encoding.Default.GetString(plaintext);
        }

        public static string Encrypt(string hexStrKey, string plain)
        {
            //1.将16进制的密钥转化为byte数组
            var key = StrToHexByte(hexStrKey);
            //2.将string格式的原文转化为byte数组
            var plaintext = Encoding.Default.GetBytes(plain);
            //2.1密文与原文等长
            var ciphertext = new byte[plaintext.Length];
            //3.随机数,给nonce赋值随机数
            Random rand = new Random();
            var nonce = new byte[12];
            var tag = new byte[16];
            rand.NextBytes(nonce);
            //4.加密
            using var aesGcm = new AesGcm(key);
            aesGcm.Encrypt(nonce, plaintext, ciphertext, tag);
            //5.将nonce(12位)拼在密文前,将tag(16位拼在密文后)
            var cipher = new byte[ciphertext.Length + 28];
            Array.ConstrainedCopy(nonce, 0, cipher, 0, 12);
            Array.ConstrainedCopy(ciphertext, 0, cipher, 12, ciphertext.Length);
            Array.ConstrainedCopy(tag, 0, cipher, 12 + ciphertext.Length, 16);
            return Convert.ToBase64String(cipher);
        }
        static void Main()
        {
            var hexStrKey = @"2836e95fcd10e04b0069bb1ee659955b";
            var base64Cliper = @"CqT/33f3jyoiYqT8MtxEFk3x2rlfhmgzhxpHqWosSj4d3hq2EbrtVyx2aLj565ZQNTcPrcDipnvpq/D/vQDaLKW70O83Q42zvR0//OfnYLcIjTPMnqa+SOhsjQrSdu66ySSORCAo";
            var plaintext = Decrypt(hexStrKey, base64Cliper);
            Console.WriteLine("解密成功,测试原文:" + plaintext);
            plaintext = ".NET 666";
            var ciphertext = Encrypt(hexStrKey, plaintext);
            Console.WriteLine("加密成功,密文:" + ciphertext);
            Console.WriteLine("解密成功,原文:" + Decrypt(hexStrKey, ciphertext));
        }
    }
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM