C# AES CTR模式 CryptoJS 對應C# .NET寫法
阿新 • • 發佈:2020-06-04
吐槽下國內部落格基本都是瞎幾把轉發,找了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);