.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