- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将 C++ 源代码转换为 C#,后者使用 Rinjdael 密码学加密和解密文件。
但 c++ 源代码与正常的加密/解密有一点不同。
而且我不太擅长 C++,所以我很困惑。
我的一个客户的应用程序是用 VC++ 编写的,将其转换为 C# 是我工作的一部分。
而之前的 c++ 开发人员使用了来自 http://www.codeproject.com/Articles/10657/A-Simple-Portable-Rinjdael-AES-Based-Stream-Cipher 的开源代码操纵加密/解密。
这里是c++源代码。
int DCipher::DecryptFile(LPCTSTR szSrcFile, LPCTSTR szDestFile, const char* pwd, int head[19])
{
if(CheckMemSize() != 0)
return INSUFFICIENT_MEMORY;
FileSize=CurPosition=0;
_tcscpy(SrcFile, szSrcFile);
_tcscpy(OutFile, szDestFile);
//_tcscpy(OutFile, _T(".enc"));
strcpy(password, pwd);
for(int i=0; i<19; i++)
{
header[i] = head[i];
}
FILE *r, *w;
GetFileLength();
int nCheck = CheckIfEncrypted();
if(nCheck != ENCRYPTED_FILE )
return nCheck; //either NORMAL_FILE or BAD_SIGNATURE
if((r = _tfopen(SrcFile, _T("rb"))) == NULL)
return ERROR_SRC_FILE;
if((w = _tfopen(OutFile, _T("wb"))) == NULL)
{
fclose(r);
return ERROR_DST_FILE;
}
char zzz[26]; //fixed invalid pointer - DKeesler
fread(zzz, 25, 1, r); // Skip first 25 bytes of the file.
int pad = header[19];
pad *= 10;
pad += header[20];
// convert password to Rijndael key
strcpy((char*)key, (const char*)CalcMD5FromString((const char*)password));
/***************************************
Decryption algorithm
***************************************/
int rval = NO_ERRORS_DONE;
FileSize -= 25;
unsigned int BUFF_SIZE = liChunkSize;
unsigned int WRITE_SIZE = liChunkSize;
int nRound = FileSize / liChunkSize;
unsigned int LAST_BLOCK = FileSize % liChunkSize;
if(LAST_BLOCK >= 1)
nRound++;
const unsigned char* intext;
unsigned char* output;
intext = (const unsigned char*)malloc(BUFF_SIZE);
output = (unsigned char*)malloc(BUFF_SIZE+16);
if(intext == NULL || output == NULL)
{
fclose(r);
fclose(w);
return ALLOC_ERROR;
}
Rijndael rj;
rj.init(Rijndael::CBC, Rijndael::Decrypt, key, Rijndael::Key32Bytes);
for(int loop=1; loop <= nRound; loop++)
{
if(loop == nRound && LAST_BLOCK >= 1)
{
BUFF_SIZE = LAST_BLOCK;
WRITE_SIZE = LAST_BLOCK - pad;
}
fread((void*)intext, sizeof(char), BUFF_SIZE, r); // read plaintext into intext[] buffer
int bsize = BUFF_SIZE*8;
int len = rj.blockDecrypt((const UINT8*)intext, bsize, (UINT8*)output);
if(len >= 0)
{
fwrite((const void*)output, sizeof(char), WRITE_SIZE, w);
}
else
{
rval = READ_WRITE_ERROR;
break;
}
}
fclose(r); //close input file
fclose(w); //close output file
free((void*)intext);
free((void*)output);
//change these two lines if you want to leave backups or unencrypted copies...
//that would sort of defeat the purpose of encryption in my mind, but it's your
// app so write it like you want it.
if(DECRYPTION_CANCEL == rval) {
_tremove(OutFile);
}
else {
//_tremove(SrcFile); //remove input file
//_trename(OutFile, SrcFile); //rename output file to input filename
}
return rval; //ZERO .. see defines for description of error codes.
}
而c#源码来自https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael(v=vs.110).aspx .
然后我更改了一些代码。
这是 C# 代码。
public int DecryptFile(string SourceFilePath, string DestFilePath, string Password, string Signature)
{
try
{
FileSize = CurPosition = 0;
FileInfo _fi = new FileInfo(SourceFilePath);
FileSize = _fi.Length;
// copy the signature to _header
for(int i = 0; i < 19; i++)
{
_header[i] = (byte)Signature[i];
}
/*
* check if the file is valid encrypted file.
*/
int nCheck = this.CheckIfEncrypted(SourceFilePath);
switch (nCheck)
{
case ENCRYPTED_FILE:
// The file is an encrypted file.
break;
case NORMAL_FILE:
throw new ArgumentException("The file is a normal file.");
case BAD_SIGNATURE:
throw new ArgumentException("User signature doesn't match.");
}
int pad = _header[19];
pad *= 10;
pad += _header[20];
// Rijndael session key
byte[] session_key = this.CalcMD5FromString(Password);
byte[] _restFileBytes = new byte[_fi.Length - 25];
using (FileStream _fs = new FileStream(SourceFilePath, FileMode.Open, FileAccess.Read))
{
_fs.Read(_restFileBytes, 0, _restFileBytes.Length);
}
int rval = NO_ERRORS_DONE;
FileSize -= 25;
int BUFF_SIZE = liChunkSize;
int WRITE_SIZE = liChunkSize;
int nRound = (int)FileSize / liChunkSize;
int LAST_BLOCK = (int)FileSize % liChunkSize;
if(LAST_BLOCK >= 1)
nRound++;
byte[] intext = new byte[BUFF_SIZE];
byte[] output = new byte[BUFF_SIZE + 16];
if (intext.Length == 0 || output.Length == 0)
{
return ALLOC_ERROR;
}
for (int loop = 1; loop <= nRound; loop++)
{
if (loop == nRound && LAST_BLOCK >= 1)
{
BUFF_SIZE = LAST_BLOCK;
WRITE_SIZE = LAST_BLOCK - pad;
}
intext = new byte[BUFF_SIZE];
System.Buffer.BlockCopy(_restFileBytes, (loop - 1) * this.liChunkSize, intext, 0, BUFF_SIZE);
int bsize = BUFF_SIZE * 8; // -> I still couldn't figure out what this bsize does on Rijndael decryption.
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
myRijndael.Key = session_key;
//myRijndael.BlockSize = bsize;
//myRijndael.Padding = PaddingMode.None;
myRijndael.GenerateIV();
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = myRijndael.Key;
rijAlg.IV = myRijndael.IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(intext))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
//using (StreamReader srDecrypt = new StreamReader(csDecrypt))
//{
// // Read the decrypted bytes from the decrypting stream and place them in a string.
// //string s = srDecrypt.ReadToEnd();
//}
byte[] rettt = msDecrypt.ToArray();
} // --> Padding is invalid and cannot be removed error occurs here and msDecrypt byte array is just same as intext. So, it's not decrypted at all.
}
}
}
}
return rval;
}
catch
{
throw;
}
}
根据 Keesler(他是 codeproject.com 的 c++ 源代码的作者),前 25 个字节填充了用户数据(签名、填充和文件状态)。因此,我跳过了前 25 个字节并将其余字节保存到 _restFileBytes varialbes(字节数组)。
而 Keesler 有一个名为 chunk size 的变量,它将文件字节拆分为 block 大小(只要我理解)。
无论如何,我想我几乎转换为 c#,但当在 c# 中部署 CryptoStream 时,我仍然收到此错误消息“填充无效且无法删除”。
谁能给我一些指导来修复这个错误?
最佳答案
None
应该用作填充模式。看来您的同事和原始文章的作者制定了他们自己的填充方案。
此外,所有密文都应该从文件中流式传输(确保您读取了所有字节)。目前您正在为每个 block 重新使用 IV 进行加密,这并不好,IV 应该只在密文的开头使用。
在开始之前为 C++ 和 C# 打印出十六进制的 key 并进行比较。
请注意,Read
方法与 C++ 中的 fread
方法略有不同。
关于c# - 当出现 "Padding is invalid and cannot be removed"错误时,如何将 C++ Rijndael 密码学转换为 C#?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30158411/
我正在对一款流行游戏 (Minecraft) 进行一些修改,我在地形生成中看到了这些线条, double d4 = 1.0D; d4 *= d4; d4 *= d4; d4 = 1.0D - d4;
如何在没有浮点单元的处理器上执行 float 学运算?例如低端 8 位微 Controller 。 最佳答案 看看这篇文章:http://www.edwardrosten.com/code/fp_te
抱歉这个冗长的标题。我的代码针对没有浮点单元的微 Controller (msp430),但这应该适用于任何类似的 MCU。 如果我将一个大的运行时变量与通常被认为是浮点十进制数 (1.8) 相乘,M
我偶尔会在这个方法中遇到 stackoverflow 异常。 double norm_cdf(const double x) { double k = 1.0/(1.0 + 0.2316419
这是一个让我在过去几个小时里完全困惑的问题...... 我的程序中有一个硬编码的方程式: double s2; s2 = -(0*13)/84+6/42-0/84+24/12+(6*13)/42; 每
我知道 float 学充其量是丑陋的,但我想知道是否有人可以解释以下怪癖。在我测试的大多数编程语言中,将 0.4 添加到 0.2 会产生轻微错误,而 0.4 + 0.1 + 0.1 则不会。 两者计算
随着数据量持续增长,对合格数据专业人员的需求也会增长。具体而言,对SQL流利的专业人士的需求日益增长,而不仅仅是在初级层面。 因此,Stratascratch的创始人Nathan Rosidi以及我觉
当使用 c++ 或 -O0 编译时,以下 -O1 程序给出了数值不同的结果。 #include #include #include #include int main() { std::a
我正在尝试使用 SVG 在 map 上绘制飞行路径。我在 Leaflet 之上使用 d3,但所使用的框架不会对我的问题产生影响 - 这是三 Angular 关系。 http://fiddle.jshe
使用 IEEE754 float (在 JavaScript 中)时,与数学相关的精度损失风险是什么? 10*.1 即整数乘以有理数。 最佳答案 注意:该问题经过编辑,在发布此答案后很长时间添加了“t
我需要为网站 UI 做一些基本的 float 学运算(金钱的加法和乘法)。我知道 Javascript float 由于存储方式的原因并不准确,但我也知道以某种方式,可以获得我所需的准确度。我知道这一
我有一些像下面这样的宏: #define THING_LENGTH (512) #define MAX_COUNT (4096*8) #define MAX_LENGTH ((int32)((floa
我认为这是一个非常基本的问题 - 我正在执行此功能: private double convertMetersToFeet(double meters) { //function converts
我想在不损失太多精度的情况下替换这些函数中的 float 学,因为我没有 FPU。这可能吗?我认为逗号后的 3 个数字就足够了。 inline float smaller_f(float value,
我需要一个类来表示 double vector (在数学意义上)。 我需要的特殊功能: 任意维度 vector (我通常使用 10 - 100,000 维度) 高性能(用于受 CPU 限制的数字代码)
此社区 Wiki 问题的公认答案:What are best practices that you use when writing Objective-C and Cocoa?说 iPhone 不能
This question already has an answer here: Trouble with float on C [duplicate]
以下代码有问题: private const int movementMultiplier = 2; void Test() { XmlNode xnXCoordinate = xd.Sele
大家早上好 我在 float 学方面遇到了一些问题,完全迷失在“.to_f”、“*100”和“.0”中! 我希望有人能帮助我解决我的具体问题,并准确解释他们的解决方案为何有效,以便我下次理解这一点。
我的嵌入式 C 代码在具有单精度 FPU 的 Cortex M4F 上运行。我担心编译器多久将基于软件的 double 学放在诸如 ** float_var1 = 3.0 * int_var / fl
我是一名优秀的程序员,十分优秀!