1. 程式人生 > WINDOWS開發 >C# AES CTR模式 CryptoJS 對應C# .NET寫法

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,_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},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 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,_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,[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 };
            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,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 };
            resultado = null;
            try
            {
                resultado = new byte[data.Length];

                Aes128CounterMode am = new Aes128CounterMode(iv);
                ICryptoTransform ict = am.CreateEncryptor(llave,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,out string resultado)
        {

            int result = -1;
            resultado = "";
            byte[] iv = new byte[] { 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}]",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,data.Length,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[] 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,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,[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,out base64Resultado);
            a = null;
            return ok;
        }

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

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

    }
}

  

.CS原始碼下載:技術分享圖片

DEMO

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