2013-01-31 18 views
6

से बाइट सरणी कैसे लौटा सकता हूं इसलिए मैं थोड़ा सा इसके लिए संघर्ष कर रहा हूं। मैं अपने कार्यक्रमों में से एक के साथ उपयोग करने के लिए अपनी खुद की एईएस 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"); 
} 
+2

चेक बाहर इस [जवाब] (http://stackoverflow.com/a/13123962/175157) । संक्षेप में, सी # यह नहीं जान सकता कि आपने सी ++ कोड में कितनी मेमोरी आवंटित की है। – Alex

+1

मुझे यकीन नहीं है कि आपका अंतिम लक्ष्य क्या है, लेकिन मैं यह इंगित करना चाहता हूं कि सी # में [सिस्टम.Security.Cryptography नेमस्पेस] में कुछ महान क्रिप्टोग्राफी कक्षाएं शामिल हैं (http://msdn.microsoft.com/en-us /library/system.security.cryptography.aspx) जो बहुत अच्छा काम करता है। –

+1

सी ++ कोड के साथ इंटरऑप के लिए एक आवश्यक प्रारंभिक बिंदु यह है कि आप * सी ++ कोड के साथ शुरू करें जिसे सुरक्षित रूप से अन्य सी ++ कोड से बुलाया जा सकता है। आप अभी तक नहीं हैं, आप स्मृति को बुरी तरह लीक कर रहे हैं और सी ++ कॉलर के पास आवश्यक बफर आकार पर कोई अनुमान नहीं होगा। जब आप सी # से कॉल करते हैं तो ये समस्या बेहतर नहीं होती है। –

उत्तर

1

यदि आप अभी भी उत्तर की तलाश में हैं, तो यह उदाहरण प्रारंभिक बिंदु देता है।

मूल रूप से, देशी फ़ंक्शन कॉल में मेमोरी ब्लॉक आवंटित करने से शुरू करें, कॉल करने के लिए कॉल करें - वापस प्रबंधित करें जहां आप पास (रेफरी) सरणी से गुजरते हैं और इसका आकार इनपुट पैरामीटर की मूल सूची से सहेजा जाता है।

इस तरह आप प्रबंधित कोड में प्रबंधित कोड के लिए मेमोरी ब्लॉक आवंटित करते हैं और इसे देशी से सामग्री के साथ संपादित करते हैं।

http://msdn.microsoft.com/en-us/library/ektebyzx.aspx

वैकल्पिक विधि, प्रदर्शन की तुलना एक बोनस :) होगा खोजने के लिए अच्छा होगा

1

सच कहूं, मैं अप्रबंधित सी रैप करने के लिए एक प्रबंधित सी ++ कॉल के साथ फोन ++ है सबसे आसान तरीका है यह करने के लिए मिल गया है। प्रबंधित सी ++ में, आप सीधे सी ++ तरीके से डेटा की प्रतिलिपि बना सकते हैं (डेटा संरचना को पिन करके) और इसे वापस सी #