C# AES CTR模式 CryptoJS 对应C# .NET写法

吐槽下国内博客基本都是瞎几把转发,找了2天没找到正确的方式,都准备放弃,使用WebBrowser 来跑

CryptoJS.AES.decrypt({ciphertext: CryptoJS.enc.Base64.parse("79VrqFVhnPb36ZbAP0DZlA==")},CryptoJS.enc.Latin1.parse("442A472D4B6150645267556B58703273"),{mode:CryptoJS.mode.CTR,iv:CryptoJS.enc.Latin1.parse("556A586E32723575"),padding: CryptoJS.pad.Pkcs7}).toString(CryptoJS.enc.Utf8);

  javascript解析出来明文是:hello

 

// The MIT License (MIT)

// Copyright (c) 2014 Hans Wolff

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Security.Cryptography;

public class Aes128CounterMode : SymmetricAlgorithm
{
    private readonly byte[] _counter;
    private readonly AesManaged _aes;

    public Aes128CounterMode(byte[] counter)
    {
        if (counter == null) throw new ArgumentNullException("counter");
        if (counter.Length != 16)
            throw new ArgumentException(String.Format("Counter size must be same as block size (actual: {0}, expected: {1})",
                counter.Length, 16));

        _aes = new AesManaged
        {
            Mode = CipherMode.ECB,
            Padding = PaddingMode.None
        };

        _counter = counter;
    }

    public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] ignoredParameter)
    {
        return new CounterModeCryptoTransform(_aes, rgbKey, _counter);
    }

    public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] ignoredParameter)
    {
        return new CounterModeCryptoTransform(_aes, rgbKey, _counter);
    }

    public override void GenerateKey()
    {
        _aes.GenerateKey();
    }

    public override void GenerateIV()
    {
        // IV not needed in Counter Mode
    }
}

public class CounterModeCryptoTransform : ICryptoTransform
{
    private readonly byte[] _counter;
    private readonly ICryptoTransform _counterEncryptor;
    private readonly Queue<byte> _xorMask = new Queue<byte>();
    private readonly SymmetricAlgorithm _symmetricAlgorithm;

    public CounterModeCryptoTransform(SymmetricAlgorithm symmetricAlgorithm, byte[] key, byte[] counter)
    {
        if (symmetricAlgorithm == null) throw new ArgumentNullException("symmetricAlgorithm");
        if (key == null) throw new ArgumentNullException("key");
        if (counter == null) throw new ArgumentNullException("counter");
        if (counter.Length != symmetricAlgorithm.BlockSize / 8)
            throw new ArgumentException(String.Format("Counter size must be same as block size (actual: {0}, expected: {1})",
                counter.Length, symmetricAlgorithm.BlockSize / 8));

        _symmetricAlgorithm = symmetricAlgorithm;
        _counter = counter;

        var zeroIv = new byte[_symmetricAlgorithm.BlockSize / 8];
        _counterEncryptor = symmetricAlgorithm.CreateEncryptor(key, zeroIv);
    }

    public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
    {
        var output = new byte[inputCount];
        TransformBlock(inputBuffer, inputOffset, inputCount, output, 0);
        return output;
    }

    public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
    {
        for (var i = 0; i < inputCount; i++)
        {
            if (NeedMoreXorMaskBytes()) EncryptCounterThenIncrement();

            var mask = _xorMask.Dequeue();
            outputBuffer[outputOffset + i] = (byte)(inputBuffer[inputOffset + i] ^ mask);
        }

        return inputCount;
    }

    private bool NeedMoreXorMaskBytes()
    {
        return _xorMask.Count == 0;
    }

    private void EncryptCounterThenIncrement()
    {
        var counterModeBlock = new byte[_symmetricAlgorithm.BlockSize / 8];

        _counterEncryptor.TransformBlock(_counter, 0, _counter.Length, counterModeBlock, 0);
        IncrementCounter();

        foreach (var b in counterModeBlock)
        {
            _xorMask.Enqueue(b);
        }
    }

    private void IncrementCounter()
    {
        for (var i = _counter.Length - 1; i >= 0; i--)
        {
            if (++_counter[i] != 0)
                break;
        }
    }

    public int InputBlockSize { get { return _symmetricAlgorithm.BlockSize / 8; } }
    public int OutputBlockSize { get { return _symmetricAlgorithm.BlockSize / 8; } }
    public bool CanTransformMultipleBlocks { get { return true; } }
    public bool CanReuseTransform { get { return false; } }

    public void Dispose()
    {
    }
}

  

using RGiesecke.DllExport;
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;

namespace AES_CTR_NET
{

    [ComVisible(true)]
    [Guid("8871C5E0-B296-4AB8-AEE7-F2553BACB730"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IAES_CTR
    {
        [return: MarshalAs(UnmanagedType.I4)]
        int Encripta(string base64Data, string base64Llave, [MarshalAs(UnmanagedType.BStr)] out string base64Resultado);

        [return: MarshalAs(UnmanagedType.I4)]
        int Desencripta(string base64Data, string base64Llave, [MarshalAs(UnmanagedType.BStr)] out string base64Resultado);

        [return: MarshalAs(UnmanagedType.BStr)]
        string GetID();

        void SetID(string v);

        [return: MarshalAs(UnmanagedType.BStr)]
        string Version();
    }

    public class AES_CTR : IAES_CTR
    {

        private string _VERSION_ = "1.0.0.1";
        static private string _S_VERSION_ = "1.0.0.1";

        public string Version() { return this._VERSION_; }

        public string ID { get; set; }

        public void SetID(string v) { ID = v; }

        public string GetID() { return ID; }

        /// <summary>
        ///     Encripta un valor en AES_CTR
        /// </summary>
        /// <param name="base64Data">Cadena de texto en Base64 a encriptar</param>
        /// <param name="llave">Llave en claro</param>
        /// <param name="resultado">Cadena de texto en Base64 obtenida del arreglo de bytes</param>
        /// <returns> Cantidad de Bytes obtenido al encriptar</returns>       
        public int Encripta(string base64Data, string llave, out string base64Resultado)
        {

            int result = -1;
            base64Resultado = "";
            byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            byte[] outData = null;
            byte[] llaveB = null;
            byte[] data = null;
            try
            {
                #region Validaciones
                try
                {
                    Encoding.UTF8.GetString(Convert.FromBase64String(base64Data));
                }
                catch (Exception)
                {
                    throw new Exception(string.Format("La data a encriptar NO es un Base64 Valido [{0}]", base64Data));
                }

                try
                {
                    Encoding.UTF8.GetString(Convert.FromBase64String(llave));
                }
                catch (Exception)
                {
                    throw new Exception(string.Format("La llave NO es un Base64 Valido [{0}]", llave));
                }
                #endregion

                data = Encoding.UTF8.GetBytes(base64Data);
                outData = new byte[base64Data.Length];
                llaveB = Encoding.UTF8.GetBytes(llave);// Convert.FromBase64String(base64Llave);

                Aes128CounterMode am = new Aes128CounterMode(iv);
                ICryptoTransform ict = am.CreateEncryptor(llaveB, null);
                ict.TransformBlock(data, 0, outData.Length, outData, 0);

                base64Resultado = Convert.ToBase64String(outData);

                result = outData.Length;

            }
            catch (Exception e)
            {
                base64Resultado = e.Message;
            }


            return result;
        }       /// <summary>

        /// <summary>
        ///     Encripta un valor en AES_CTR
        /// </summary>
        /// <param name="data">Cadena de texto en Base64 a encriptar</param>
        /// <param name="llave">Llave en claro</param>
        /// <param name="resultado">Cadena de texto en Base64 obtenida del arreglo de bytes</param>
        /// <returns> Cantidad de Bytes obtenido al encriptar</returns>       
        public int Encripta(byte[] data, byte[] llave, out byte[] resultado)
        {

            int result = -1;
            byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            resultado = null;
            try
            {
                resultado = new byte[data.Length];

                Aes128CounterMode am = new Aes128CounterMode(iv);
                ICryptoTransform ict = am.CreateEncryptor(llave, null);
                ict.TransformBlock(data, 0, resultado.Length, resultado, 0);

                result = resultado.Length;

            }
            catch (Exception e)
            {
                resultado = Encoding.UTF8.GetBytes(e.Message);
            }


            return result;
        }

        /// <summary>
        ///     Desencripta un valor en AES_CTR
        /// </summary>
        /// <param name="base64Data">Data Encriptada</param>
        /// <param name="llave">Llave en claro</param>
        /// <param name="resultado">Cadena de texto obtenida del arreglo de bytes</param>
        /// <returns> Cantidad de Bytes obtenido al desencriptar </returns>
        public int Desencripta(string base64Data, string llave, out string resultado)
        {

            int result = -1;
            resultado = "";
            byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            byte[] outData = null;
            byte[] llaveB = null;
            byte[] data = null;

            try
            {

                #region Validaciones
                try
                {
                    Encoding.UTF8.GetString(Convert.FromBase64String(base64Data));
                }
                catch (Exception)
                {
                    throw new Exception(string.Format("La data a desencriptar NO es un Base64 Valido [{0}]", base64Data));
                }

                try
                {
                    Encoding.UTF8.GetString(Convert.FromBase64String(llave));
                }
                catch (Exception)
                {
                    throw new Exception(string.Format("La llave NO es un Base64 Valido [{0}]", llave));
                }
                #endregion

                data = Convert.FromBase64String(base64Data);
                outData = new byte[data.Length];
                llaveB = Encoding.UTF8.GetBytes(llave);// Convert.FromBase64String(base64Llave);

                Aes128CounterMode am = new Aes128CounterMode(iv);
                ICryptoTransform ict = am.CreateDecryptor(llaveB, null);
                ict.TransformBlock(data, 0, data.Length, outData, 0);

                resultado = Encoding.UTF8.GetString(outData);

                result = outData.Length;

            }
            catch (Exception e)
            {
                resultado = e.Message;
            }

            return result;
        }

        /// <summary>
        ///     Desencripta un valor en AES_CTR
        /// </summary>
        /// <param name="dataIn">Data Encriptada</param>
        /// <param name="llave">Arreglo de bytes (32 bytes)</param>
        /// <param name="resultado">Cadena de texto obtenida del arreglo de bytes</param>
        /// <returns> Cantidad de Bytes obtenido al desencriptar </returns>
        public int Desencripta(byte[] data, byte[] llave,byte[] iv, out byte[] resultado)
        {

            int result = -1;
            resultado = null;

            try
            {
                resultado = new byte[data.Length];

                Aes128CounterMode am = new Aes128CounterMode(iv);
                ICryptoTransform ict = am.CreateDecryptor(llave, null);
                ict.TransformBlock(data, 0, data.Length, resultado, 0);


                result = resultado.Length;

            }
            catch (Exception e)
            {
                resultado = Encoding.UTF8.GetBytes(e.Message);
            }

            return result;
        }

        [DllExport(CallingConvention = CallingConvention.Cdecl)]
        public static void CreaObjeto([MarshalAs(UnmanagedType.Interface)] out IAES_CTR miAES)
        {
            miAES = new AES_CTR();
            miAES.SetID("_UNDEF_");
        }

        [DllExport("VersionNTS", CallingConvention = CallingConvention.Cdecl)]
        public static void VersionNTS([MarshalAs(UnmanagedType.BStr)] out string version)
        {
            version = _S_VERSION_;
        }

        [DllExport("EncriptaNTS", CallingConvention = CallingConvention.Cdecl)]
        public static int EncriptaNTS(IntPtr base64Data_P, IntPtr base64Llave_P, [MarshalAs(UnmanagedType.BStr)] out string base64Resultado)
        {
            string base64Data = Marshal.PtrToStringAuto(base64Data_P);
            string base64Llave = Marshal.PtrToStringAuto(base64Llave_P);

            var a = new AES_CTR();
            var ok = a.Encripta(base64Data, base64Llave, out base64Resultado);
            a = null;
            return ok;
        }

        [DllExport("DesencriptaNTS", CallingConvention = CallingConvention.Cdecl)]
        public static int DesencriptaNTS(IntPtr base64Data_P, IntPtr base64Llave_P, [MarshalAs(UnmanagedType.BStr)] out string base64Resultado)
        {

            string base64Data = Marshal.PtrToStringAuto(base64Data_P);
            string base64Llave = Marshal.PtrToStringAuto(base64Llave_P);
            var a = new AES_CTR();
            var ok = a.Desencripta(base64Data, base64Llave, out base64Resultado);
            a = null;
            return ok;
        }

        public static int EncriptaNTS(string base64Data, string base64Llave, out string base64Resultado)
        {
            var a = new AES_CTR();
            var ok = a.Encripta(base64Data, base64Llave, out base64Resultado);
            a = null;
            return ok;
        }

        public static int DesencriptaNTS(string base64Data, string base64Llave, out string base64Resultado)
        {
            var a = new AES_CTR();
            var ok = a.Desencripta(base64Data, base64Llave, out base64Resultado);
            a = null;
            return ok;
        }
        public static int DesencriptaNTS(byte[] base64Data, byte[] base64Llave, byte[] iv, out byte[] base64Resultado)
        {
            var a = new AES_CTR();
            var ok = a.Desencripta(base64Data, base64Llave, iv, out base64Resultado);
            a = null;
            return ok;
        }

    }
}

  

.CS源代码下载:C# AES CTR模式 CryptoJS 对应C# .NET写法

DEMO

AES_CTR_NET.AES_CTR.DesencriptaNTS(Convert.FromBase64String("79VrqFVhnPb36ZbAP0DZlA=="), System.Text.Encoding.UTF8.GetBytes("5A7234753778214125442A472D4B6150"), System.Text.Encoding.UTF8.GetBytes("556A586E32723575"), out resultbytes);

C# AES CTR模式 CryptoJS 对应C# .NET写法

上一篇:Window Nginx 负载均衡


下一篇:容易忽视的前端api