c#.net core 中的等效 AES 加密代码
Equivalent AES encryption code in c# .net core
我有一个用 C 编写的 AES/CBC 加密代码。我必须在 C# 中转换此代码
C代码:
EVP_CIPHER_CTX_init(&e_ctx);
err = EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, NULL);
err = EVP_CIPHER_CTX_set_padding(&e_ctx,EVP_CIPH_NO_PADDING);
err = EVP_EncryptUpdate(&e_ctx,cipher,&cipher_len,plain,plain_len);
err = EVP_EncryptFinal_ex(&e_ctx, cipher+cipher_len, &f_len);
C#代码:
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
//aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor();
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{ using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{ using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(data);
}
byte[] encrypted = msEncrypt.ToArray();
}
}
}
但在这两种情况下,我都得到了不同的密文。虽然钥匙是一样的。
C 代码中不使用 IV。所以也不要在 c# 代码中使用。但我怀疑 OpenSSL 和 .net API.
使用了一些默认 IV
C 和 C# 代码 仅 在 IV 中不同。在 C 代码中,EVP_EncryptInit_ex()
将 NULL
作为第 5 个参数传递,这导致 IV 为零,即仅由 0x00
值组成的 IV。相反,C# 代码使用在调用 Aes.Create()
时创建的随机 IV。
因此,如果在 C# 代码中应用零向量,则 C# 代码在功能上与 C 代码相同。为此,请在行下方添加 aesAlg.Key = key
:
aesAlg.IV = new byte[16];
除此之外,两个代码都使用 same 模式和 same padding:
- Mode:在C代码中,
EVP_aes_256_cbc()
显式设置CBC模式,即C#代码中的default模式。
- 填充:在 C 代码中,填充仅表面上 禁用。
EVP_CIPHER_CTX_set_padding()
仅当第二个参数为 0
时才禁用默认的 PKCS7 填充。但是后者就不是这样了,因为EVP_CIPH_NO_PADDING
被定义为0x100
。所以C代码使用默认的PKCS7 padding,也就是C#代码中的default padding
在 C 代码中未禁用填充可能是由于在 EVP_CIPHER_CTX_set_padding()
的上下文中意外使用 EVP_CIPH_NO_PADDING
造成的疏忽。根据文档,EVP_CIPH_NO_PADDING
应用于 EVP_CIPHER_meth_set_flags()
. 的上下文中
如果添加以上行以便在 C# 代码中使用零向量,则 C 和 C# 代码在我的机器上为相同的输入数据生成相同的密文。
但是请注意,静态 IV 与零 IV 一样是不安全的。通常每次加密都会生成一个随机 IV,因为它不是秘密的,所以它与密文一起发送(通常是串联的)。
我有一个用 C 编写的 AES/CBC 加密代码。我必须在 C# 中转换此代码
C代码:
EVP_CIPHER_CTX_init(&e_ctx);
err = EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, NULL);
err = EVP_CIPHER_CTX_set_padding(&e_ctx,EVP_CIPH_NO_PADDING);
err = EVP_EncryptUpdate(&e_ctx,cipher,&cipher_len,plain,plain_len);
err = EVP_EncryptFinal_ex(&e_ctx, cipher+cipher_len, &f_len);
C#代码:
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
//aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor();
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{ using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{ using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(data);
}
byte[] encrypted = msEncrypt.ToArray();
}
}
}
但在这两种情况下,我都得到了不同的密文。虽然钥匙是一样的。 C 代码中不使用 IV。所以也不要在 c# 代码中使用。但我怀疑 OpenSSL 和 .net API.
使用了一些默认 IVC 和 C# 代码 仅 在 IV 中不同。在 C 代码中,EVP_EncryptInit_ex()
将 NULL
作为第 5 个参数传递,这导致 IV 为零,即仅由 0x00
值组成的 IV。相反,C# 代码使用在调用 Aes.Create()
时创建的随机 IV。
因此,如果在 C# 代码中应用零向量,则 C# 代码在功能上与 C 代码相同。为此,请在行下方添加 aesAlg.Key = key
:
aesAlg.IV = new byte[16];
除此之外,两个代码都使用 same 模式和 same padding:
- Mode:在C代码中,
EVP_aes_256_cbc()
显式设置CBC模式,即C#代码中的default模式。 - 填充:在 C 代码中,填充仅表面上 禁用。
EVP_CIPHER_CTX_set_padding()
仅当第二个参数为0
时才禁用默认的 PKCS7 填充。但是后者就不是这样了,因为EVP_CIPH_NO_PADDING
被定义为0x100
。所以C代码使用默认的PKCS7 padding,也就是C#代码中的default padding
在 C 代码中未禁用填充可能是由于在EVP_CIPHER_CTX_set_padding()
的上下文中意外使用EVP_CIPH_NO_PADDING
造成的疏忽。根据文档,EVP_CIPH_NO_PADDING
应用于EVP_CIPHER_meth_set_flags()
. 的上下文中
如果添加以上行以便在 C# 代码中使用零向量,则 C 和 C# 代码在我的机器上为相同的输入数据生成相同的密文。
但是请注意,静态 IV 与零 IV 一样是不安全的。通常每次加密都会生成一个随机 IV,因为它不是秘密的,所以它与密文一起发送(通常是串联的)。