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源代码下载:
DEMO
AES_CTR_NET.AES_CTR.DesencriptaNTS(Convert.FromBase64String("79VrqFVhnPb36ZbAP0DZlA=="), System.Text.Encoding.UTF8.GetBytes("5A7234753778214125442A472D4B6150"), System.Text.Encoding.UTF8.GetBytes("556A586E32723575"), out resultbytes);
如果对您有帮助,请捐助我

浙公网安备 33010602011771号