gpt4 book ai didi

javascript - 兼容C#和javascript的AES加解密

转载 作者:数据小太阳 更新时间:2023-10-29 04:45:15 26 4
gpt4 key购买 nike

我正在尝试用 C# 和 Javascript 编写两个类,我可以在整个项目中使用它们在交换数据时使用 AES 加密或解密数据。

使用 AES,我在加密结果中嵌入了 Salt(32 字节)和 IV(16 字节),这在测试时对两个类都有效。将 Salt 和 IV 添加到组合中并不会带来很多引用来使它在两个平台之间工作。

对于 C#,我使用标准的 System.Security.Crypthography.AES

 private static readonly int iterations = 1000;

public static string Encrypt(string input, string password)
{
byte[] encrypted;
byte[] IV;
byte[] Salt = GetSalt();
byte[] Key = CreateKey(password, Salt);

using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Mode = CipherMode.CBC;

aesAlg.GenerateIV();
IV = aesAlg.IV;

var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(input);
}
encrypted = msEncrypt.ToArray();
}
}
}

byte[] combinedIvSaltCt = new byte[Salt.Length + IV.Length + encrypted.Length];
Array.Copy(Salt, 0, combinedIvSaltCt, 0, Salt.Length);
Array.Copy(IV, 0, combinedIvSaltCt, Salt.Length, IV.Length);
Array.Copy(encrypted, 0, combinedIvSaltCt, Salt.Length + IV.Length, encrypted.Length);

return Convert.ToBase64String(combinedIvSaltCt.ToArray());
}

public static string Decrypt(string input, string password)
{
byte[] inputAsByteArray;
string plaintext = null;
try
{
inputAsByteArray = Convert.FromBase64String(input);

byte[] Salt = new byte[32];
byte[] IV = new byte[16];
byte[] Encoded = new byte[inputAsByteArray.Length - Salt.Length - IV.Length];

Array.Copy(inputAsByteArray, 0, Salt, 0, Salt.Length);
Array.Copy(inputAsByteArray, Salt.Length, IV, 0, IV.Length);
Array.Copy(inputAsByteArray, Salt.Length + IV.Length, Encoded, 0, Encoded.Length);

byte[] Key = CreateKey(password, Salt);

using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;

ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

using (var msDecrypt = new MemoryStream(Encoded))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}

return plaintext;
}
catch (Exception e)
{
return null;
}
}

public static byte[] CreateKey(string password, byte[] salt)
{
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, iterations))
return rfc2898DeriveBytes.GetBytes(32);
}

private static byte[] GetSalt()
{
var salt = new byte[32];
using (var random = new RNGCryptoServiceProvider())
{
random.GetNonZeroBytes(salt);
}

return salt;
}

对于我使用 CryptoJS 的 Javascript 解决方案,基于此引用 http://www.adonespitogo.com/articles/encrypting-data-with-cryptojs-aes/

    var keySize = 256;
var ivSize = 128;
var saltSize = 256;
var iterations = 1000;

var message = "Hello World";
var password = "Secret Password";


function encrypt (msg, pass) {
var salt = CryptoJS.lib.WordArray.random(saltSize/8);

var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize/32,
iterations: iterations
});

var iv = CryptoJS.lib.WordArray.random(ivSize/8);

var encrypted = CryptoJS.AES.encrypt(msg, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC

});

// salt, iv will be hex 32 in length
// append them to the ciphertext for use in decryption
var transitmessage = salt + iv + encrypted;
return transitmessage.toString();
}

function decrypt (transitmessage, pass) {
var salt = CryptoJS.enc.Hex.parse(transitmessage.substr(0, 64));
var iv = CryptoJS.enc.Hex.parse(transitmessage.substr(64, 32));
var encrypted = transitmessage.substring(96);

var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize/32,
iterations: iterations
});

var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC

})
return decrypted.toString(CryptoJS.enc.Utf8);
}

使用的密码:Secret Password

C# 结果:r7Oi1vMXZ5mYJay8i+slbJZEiT3CxV/1zOYntbZIsS5RuasABJKQQQVvAe50U1deIIqyQiwzQWYelMJ48WWpMQ==

Javascript 结果:72ff8e7b653efbe3101d2c4ca7d7fe1af06652b907a90281aafa5ae09b45c9af091571b08d3d39cbad129939488319b2pprMQFFEJZR5JlrDsMqT8w==

结果应该是 Hello World

这两种解决方案都在各自的环境中运行良好,但是 C# 或 Javascript 哈希无法交换,它们不会解密。我的猜测是字符编码与它有关,因此 base64 大小差异如此之大。有没有人有想法让这个一起工作?谢谢!

最佳答案

错误在Javascript代码中,前半部分是Hex,后半部分是Base64加密后的结果。

以下 Javascript 代码使 AES 结果可以与上面提供的 C# 解决方案互换。我在确保所有结果都以十六进制正确编码和解码时遇到了一些困难,因此有一些新功能。

var keySize = 256;
var ivSize = 128;
var saltSize = 256;
var iterations = 1000;

var message = "Does this work?";
var password = "Secret Password";


function encrypt (msg, pass) {
var salt = CryptoJS.lib.WordArray.random(saltSize/8);

var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize/32,
iterations: iterations
});

var iv = CryptoJS.lib.WordArray.random(ivSize/8);

var encrypted = CryptoJS.AES.encrypt(msg, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC

});

var encryptedHex = base64ToHex(encrypted.toString());
var base64result = hexToBase64(salt + iv + encryptedHex);


return base64result;
}

function decrypt (transitmessage, pass) {

var hexResult = base64ToHex(transitmessage)

var salt = CryptoJS.enc.Hex.parse(hexResult.substr(0, 64));
var iv = CryptoJS.enc.Hex.parse(hexResult.substr(64, 32));
var encrypted = hexToBase64(hexResult.substring(96));

var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize/32,
iterations: iterations
});

var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC

})

return decrypted.toString(CryptoJS.enc.Utf8);
}

function hexToBase64(str) {
return btoa(String.fromCharCode.apply(null,
str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))
);
}

function base64ToHex(str) {
for (var i = 0, bin = atob(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {
var tmp = bin.charCodeAt(i).toString(16);
if (tmp.length === 1) tmp = "0" + tmp;
hex[hex.length] = tmp;
}
return hex.join("");
}

关于javascript - 兼容C#和javascript的AES加解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47891104/

26 4 0
文章推荐: javascript - Vue.js : "TypeError: Cannot set property props of# which has only a getter"