से बाइट सरणी कैसे लौटा सकता हूं इसलिए मैं थोड़ा सा इसके लिए संघर्ष कर रहा हूं। मैं अपने कार्यक्रमों में से एक के साथ उपयोग करने के लिए अपनी खुद की एईएस 128 लाइब्रेरी बनाने की कोशिश कर रहा हूं। पुस्तकालय बाहर परीक्षण और सी में काम करता है ++ (अच्छी तरह से एन्क्रिप्ट समारोह के लिए .. मैं दूसरों लागू नहीं किया है) 'एन्क्रिप्ट' समारोह इस तरह है:मैं सी ++ से सी #
नए कोड
void Aes128Class::EncryptBlock(BYTE* outBlock, const BYTE* inBlock, const BYTE* cipherBlock)
{
BYTE temp[16] = {0x00};
Galois::XorBlock(temp, inBlock);
Galois::XorBlock(temp, cipherBlock);
BYTE expandedKey[176] = {0x00};
memcpy(expandedKey, Key, 16);
Galois::expand_key(expandedKey);
Galois::XorBlock(temp, expandedKey);
for(int i=16; i<160; i+=16)
{
Galois::DoRound(temp, &expandedKey[i]);
}
Galois::SubBytes(temp);
Galois::ShiftRows(temp);
Galois::XorBlock(temp, &expandedKey[160]);
memcpy(outBlock, temp, 16);
}
void Aes128Class::EncryptData(BYTE* outBlock, size_t& outlen, const BYTE* inBlock, size_t length)
{
float blockSize = (float)(length/16);
blockSize = ceilf(blockSize);
int newLength = (int)(blockSize*16);
BYTE* temp = (BYTE*)malloc(newLength);
BYTE* padd = (BYTE*)malloc(newLength);
memset(temp, 0, newLength);
memcpy(padd, inBlock, length);
EncryptBlock(temp, padd, IV);
for (int i=1; i<blockSize; i++)
{
EncryptBlock(&temp[i*16], &padd[i*16], &temp[(i-1)*16]);
}
outlen = newLength;
memcpy(outBlock, temp, newLength);
}
विचार यह है कि यदि plainText
16-बाइट ब्लॉक वृद्धि में नहीं है तो मैं इसे मजबूर करता हूं। तो यह एक परिवर्तनीय आकार बाइट सरणी के लिए बनाता है। यह मेरे C++
परीक्षणों में काम करता है, लेकिन जब मैं इसे C#
में कॉल करता हूं तो मुझे कुछ अलग त्रुटियां मिलती हैं ... इसका वर्णन करने में एक मिनट लग जाएगा।
[DllImport("CppAes128.dll", CallingConvention = CallingConvention.ThisCall,
EntryPoint = "[email protected]@@[email protected]")]
static extern void EncryptData(IntPtr pClass, ref IntPtr outblock, [Out]int OutLength, byte[] inBlock, int length);
जब मैं इस फोन मैं दोनों array
, और outlength को वैध संकेत मिलता है। जिस तरह से यह ठीक दिखता है अब पहुंच उल्लंघन का कारण बनता है, लेकिन अगर मैं [Out]int OutLength
को ref IntPtr
में बदलता हूं तो मैं उस संरचना को काम करने के लिए प्राप्त कर सकता हूं। दिलचस्प बात यह है कि अगर मैं ref int
या ref uint
करता हूं तो यह अभी भी "काम करता है"। तो अगर मैं ऐसा करता हूं तो मैं intptr
पढ़ने की कोशिश करता हूं और फिर मुझे एक एक्सेस उल्लंघन मिलता है। मैं इसे के रूप में .NET 4.0
में संकलित कर रहा हूं (क्योंकि मैंने कहीं पढ़ा है कि 3.5 में एक्सेस के साथ कुछ बग हैं ...)
यहां मैंने C#
में कोशिश की है। यह थोड़ा विकृत है के रूप में मैं घंटों के लिए इसे साथ खेल किया गया है (खेद):
public byte[] EncryptData(byte[] plainText, int length)
{
byte[] enc = null;
int len = 0;
IntPtr pArray = IntPtr.Zero;
EncryptData(theClass, ref pArray, len, plainText, length);
Console.WriteLine(len);
//enc = new byte[len];
//Marshal.Copy(pArray, enc, 0, len);
//Marshal.Release(pArray);
//try
//{
// int elementSize = Marshal.SizeOf(typeof(IntPtr));
// //IntPtr unmanagedArray = Marshal.AllocHGlobal(10 * elementSize);
// Console.WriteLine("Reading unmanaged memory:");
// // Print the 10 elements of the C-style unmanagedArray
// for (int i = 0; i < 10; i++)
// {
// Console.WriteLine("{0:X2}:", Marshal.ReadByte(pArray, i));
// }
// Marshal.FreeHGlobal(pArray);
//}
//catch (Exception ex)
//{
// Console.WriteLine("{0}\n{1}", ex.Source, ex.Message);
// Console.WriteLine("Win32({0})", Marshal.GetLastWin32Error());
//}
//Marshal.Release(pArray);
return enc;
}
केवल समय इस काम किया है जब मैं सिर्फ एक स्थिर आकार सरणी बना दिया है और उपयोग नहीं किया ref
या marshal
प्रतिलिपि या कुछ भी .. मुझे लगता है कि अपने हस्ताक्षर इस
static extern void EncryptData(IntPtr pClass, byte[] outBlock, byte[] inBlock, int length);
यह लगभग काम की तरह कुछ था, लेकिन समस्या यह है कि यह हमेशा आकार है कि मैं डाल .. कहने के लिए निराशा होती थी, जब मुझे लगता है कि array
पर एक foreach
पाश किया था कम से कम।
तो मैं गलत क्या कर रहा हूं? में इससे कैसे चला सकता हूँ? मैं इसके साथ बहुत निराश हूँ। धन्यवाद
ओह और एफवाईआई, ऐसा इसलिए है कि मैं अब cryptlib
पर निर्भर नहीं हो सकता। मैं एक अलग परियोजना को पुन: संकलित करने की कोशिश कर रहा हूं, जो स्थिर पुस्तकालय के रूप में cryptlib
का उपयोग करता है और साझा नहीं किया जाता है, जो मेरे संकलित विकल्पों के साथ कुछ समस्याएं पैदा करता है और वापस बदलने में परेशानी का बड़ा हिस्सा है।
संपादित अधिक कोड को दिखाने के लिए
इस परीक्षण है कि मैं का उपयोग करें। मुझे एक वेबपेज मिला जिसने परीक्षणों का एक गुच्छा दिखाया, इसलिए यह मैं इसे लागू कर रहा हूं।
void VerifyEncrypt16(const BYTE* expected, const BYTE* key, const BYTE* iv, const BYTE* plainText)
{
BYTE actual[16] = {0x00};
Aes128Class aes;
aes.SetKey(key, 16);
aes.SetIV(iv, 16);
size_t len = 0;
aes.EncryptData(actual, len, plainText, 16);
_ASSERT(CompareTwoArrays(expected, actual));
}
void VerifyEncrypt16String(const char* expected, const char* key, const char* iv, const char* plainText)
{
BYTE e[16];
BYTE k[16];
BYTE i[16];
BYTE p[16];
ByteUtil::StringToHex(expected, e);
ByteUtil::StringToHex(key, k);
ByteUtil::StringToHex(iv, i);
ByteUtil::StringToHex(plainText, p);
VerifyEncrypt16(e, k, i, p);
}
void CheckEncrypt16(void)
{
_RPT0(_CRT_WARN, "Checking Encryption of a 16 byte number IV set to 0\n");
//AESVS GFSbox test data for CBC
VerifyEncrypt16String("0336763e966d92595a567cc9ce537f5e","00000000000000000000000000000000","00000000000000000000000000000000","f34481ec3cc627bacd5dc3fb08f273e6");
VerifyEncrypt16String("a9a1631bf4996954ebc093957b234589","00000000000000000000000000000000","00000000000000000000000000000000","9798c4640bad75c7c3227db910174e72");
VerifyEncrypt16String("ff4f8391a6a40ca5b25d23bedd44a597","00000000000000000000000000000000","00000000000000000000000000000000","96ab5c2ff612d9dfaae8c31f30c42168");
VerifyEncrypt16String("dc43be40be0e53712f7e2bf5ca707209","00000000000000000000000000000000","00000000000000000000000000000000","6a118a874519e64e9963798a503f1d35");
VerifyEncrypt16String("92beedab1895a94faa69b632e5cc47ce","00000000000000000000000000000000","00000000000000000000000000000000","cb9fceec81286ca3e989bd979b0cb284");
VerifyEncrypt16String("459264f4798f6a78bacb89c15ed3d601","00000000000000000000000000000000","00000000000000000000000000000000","b26aeb1874e47ca8358ff22378f09144");
VerifyEncrypt16String("08a4e2efec8a8e3312ca7460b9040bbf","00000000000000000000000000000000","00000000000000000000000000000000","58c8e00b2631686d54eab84b91f0aca1");
//AESVS KeySbox test data for CBC
VerifyEncrypt16String("6d251e6944b051e04eaa6fb4dbf78465","10a58869d74be5a374cf867cfb473859","00000000000000000000000000000000","00000000000000000000000000000000");
//A TON OF MORE TESTS! etc etc etc VerifyEncrypt16String("5c005e72c1418c44f569f2ea33ba54f3","00000000000000000000000000000000","00000000000000000000000000000000","fffffffffffffffffffffffffffffffe");
VerifyEncrypt16String("3f5b8cc9ea855a0afa7347d23e8d664e","00000000000000000000000000000000","00000000000000000000000000000000","ffffffffffffffffffffffffffffffff");
}
चेक बाहर इस [जवाब] (http://stackoverflow.com/a/13123962/175157) । संक्षेप में, सी # यह नहीं जान सकता कि आपने सी ++ कोड में कितनी मेमोरी आवंटित की है। – Alex
मुझे यकीन नहीं है कि आपका अंतिम लक्ष्य क्या है, लेकिन मैं यह इंगित करना चाहता हूं कि सी # में [सिस्टम.Security.Cryptography नेमस्पेस] में कुछ महान क्रिप्टोग्राफी कक्षाएं शामिल हैं (http://msdn.microsoft.com/en-us /library/system.security.cryptography.aspx) जो बहुत अच्छा काम करता है। –
सी ++ कोड के साथ इंटरऑप के लिए एक आवश्यक प्रारंभिक बिंदु यह है कि आप * सी ++ कोड के साथ शुरू करें जिसे सुरक्षित रूप से अन्य सी ++ कोड से बुलाया जा सकता है। आप अभी तक नहीं हैं, आप स्मृति को बुरी तरह लीक कर रहे हैं और सी ++ कॉलर के पास आवश्यक बफर आकार पर कोई अनुमान नहीं होगा। जब आप सी # से कॉल करते हैं तो ये समस्या बेहतर नहीं होती है। –