我的情況:我正在用C++編寫一個用C++編寫的服務器,用於學習目的。在某些時候,客戶端會向加密的服務器發送一個密碼。他們使用Rijndael加密密碼。 你可以找到原始的加密類在這裏:Rijndael:C++加密,C#解密
Rijndael.h:https://github.com/astorks/FlyFF/blob/master/Source/_Common/Rijndael.h
Rijndael.cpp:https://github.com/astorks/FlyFF/blob/master/Source/_Common/Rijndael.cpp#L926
正如你可以在.cpp文件看,他們使用該密鑰和IV:
char const* CRijndael::sm_chain0 = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
char szDefaultKey[32] = "dldhsvmflvm";
這裏的一部分,他們實際上是在原來的服務器解密密碼(https://github.com/astorks/FlyFF/blob/master/Source/CERTIFIER/DPCertifier.cpp#L256)
// MAX_PASSWORD is actually 42. So 16*42 = 672 byte
char szEnc[ 16 * MAX_PASSWORD ] = {0, };
char szDec[ 16 * MAX_PASSWORD ] = {0, };
ar.Read(szEnc, 16 * MAX_PASSWORD);
g_xRijndael->ResetChain();
g_xRijndael->Decrypt(szEnc, szDec, 16 * MAX_PASSWORD, CRijndael::CBC);
現在我在我正確地從客戶端獲取數據包和我需要解密密碼的地方。我目前的C#代碼不能正確解密數據,我找不出原因。這是我的代碼:
public static class Rijndael
{
private static ICryptoTransform decryptor { get; set; }
private static RijndaelManaged rijndael { get; set; }
public static void Init()
{
byte[] decryptKey = Encoding.ASCII.GetBytes("dldhsvmflvm").Concat(Enumerable.Repeat((byte)0, 21).ToArray()).ToArray();
byte[] decryptIV = Enumerable.Repeat((byte)0, 16).ToArray();
// I've tried BlockSize 128 and 256. It actually should be 128 since it's 16 on the original server (16 * 8 = 128)
rijndael = new RijndaelManaged() { Padding = PaddingMode.Zeros, Mode = CipherMode.CBC, KeySize = 256, BlockSize = 128, Key = decryptKey, IV = decryptIV };
decryptor = rijndael.CreateDecryptor(decryptKey, decryptIV);
}
public static string decrypt(byte[] data)
{
string password = null;
using (MemoryStream ms = new MemoryStream(data))
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (StreamReader sr = new StreamReader(cs))
password = sr.ReadToEnd();
return password;
}
}
他們撿了32個字節在服務器端而只用11個字符填滿了:dldhsvmflvm。這就是爲什麼我用0填充其他21個字節。 32 * 8 = 256位=密鑰大小
我得到一個錯誤,當我使用IV像字節[32]並填充0它說,smth像IV不適合塊大小。這就是爲什麼它現在有16個字節,並填充了0.這可能是問題,如果是這樣,我該如何解決它?
除此之外,我不知道哪裏可能出錯。希望你能拯救我的一天,Stackoverflow。 :)
您能否驗證IV和Key的值在C++代碼和C#代碼中是否確實相同? –
CRijndael的默認塊大小是128位,所以16個字節,所以IV必須是16個字節長。 (請參閱''void MakeKey(char const * key,char const * chain,int keylength = DEFAULT_BLOCK_SIZE,int blockSize = DEFAULT_BLOCK_SIZE)',其中'enum {DEFAULT_BLOCK_SIZE = 16}','CRYndael調用'MakeKey': :CRijndael()''帶''MakeKey(szDefaultKey,CRijndael :: sm_chain0);',所以使用默認參數。) – xanatos
請注意,即使密鑰長度必須爲16. CRijndael不使用sizeof(char [ 32])或類似的。它知道'MakeKey'參數的密鑰長度,所以請嘗試'Enumerable.Repeat((byte)0,5)' – xanatos