2015-10-17 4 views
12

मैं सी ++ कोड को सी # पर बंद करने की कोशिश कर रहा हूं और अधिकांश भाग के लिए यह काम कर रहा है, हालांकि केवल लूप के पहले 3 राउंड के लिए। चौथे दौर में, इनपुट ब्लॉक के लिए बाइट अलग-अलग होने लगते हैं और मुझे समझ में नहीं आता क्यों। अगर हम मानते हैं कि सी ++ संस्करण सही कार्यान्वयन है, तो सी # कोड चौथे दौर में एक अलग परिणाम क्यों दे रहा है। नीचे मेरे परिणाम और कोड (सी ++/सीएलआर और सी # के लिए दोनों कंसोल अनुप्रयोग)एन्क्रिप्शन एल्गोरिदम के इस सी # पोर्ट के चौथे दौर पर मेरे बाइट अलग क्यों हैं?

मुझे लगता है कि एईएस को पारित होने से पहले प्रत्येक दौर में इनपुट ब्लॉक बनाया जा रहा है, जिस तरह से कुछ अलग है (सी ++ में आधार 256, से_base_256 और से_base_256) में कनवर्ट करने का एक तरीका है, लेकिन सी # में मैं बेस 256 बाइट सरणी को सीधे BigInteger में परिवर्तित कर रहा हूं और फिर बाइट सरणी पर वापस आ रहा हूं। मुझे नहीं पता कि प्रत्येक के पहले 3 राउंड के लिए समान इनपुट ब्लॉक मान क्यों होंगे, लेकिन चौथे के लिए नहीं।

संपादित करें: अधिक डिबगिंग मैं को संकुचित होता जहां समस्या पाश के लिए में इस लाइन ही दिखा शुरू होने के बाद जब मैं = 2 (गोल 3)

BigInteger AESResult = new BigInteger(t); 

की एईएस एन्क्रिप्शन के बाद ब्लॉक मेरी बाइट सरणी टी

23, 111, 30, 144, 117, 161, 87, 113, 157, 52, 215, 157, 130, 135, 20, 184

शामिल

लेकिन जब मैं इन बाइट्स को उपरोक्त रेखा का उपयोग करके बिगइंटर में परिवर्तित करता हूं, अचानक अचानक मूल्य पर संकेत नकारात्मक हो जाता है और यह सब वहां से नीचे की ओर जाता है। मूल्य पिछले राउंड में स्थानीय विंडो में भी प्रदर्शित नहीं होता है।

आउटपुट परिणामों

ROUND 1

इनपुट
सी ++ 224,144,103,1,0,0,0,0,0,0,0,0,0,0,0, 0,
सी # 224,144,103,1,0,0,0,0,0,0,0,0,0,0,0,0,
एईएस एन्क्रिप्टेड
सी ++ 175,19,208,16,98,242,219,41,136,137,124,214,117,242,222, 20,
सी # 175,19,208,16,98, 242,219,41,136,137,124,214,117,242,222,20,

ROUND 2

इनपुट
सी ++ 168,68,153,2,0,0,0,0,0,0,0,0,1,0,0,0,
सी # 168,68,153,2,0,0,0,0,0,0,0,0,1,0,0,0,
एईएस एन्क्रिप्टेड
सी ++ 182,186,181,102,204,102,32,32,232,213,226,133,59,128,225,109,
सी # 182,186,181,102,204,102,32,32,232,213,226,133,59,128,225,109,

राउंड 3

इनपुट
सी ++ 150,126,97,5,0,0,0,0,0,0,0,0,2,0,0,0,
सी # 150,126,97,5,0,0, 0,0,0,0,0,0,2,0,0,0,
एईएस एन्क्रिप्टेड
सी ++ 23,111,30,144,117,161,87,113,157,52,215,157,130,135,20,184,
सी # 23,111,30,144,117,161,87,113,157,52,215,157,130,135,20,184,

ROUND 4

इनपुट
सी ++ 191,210,191,0,0,0,0,0,0 , 0,0,0,3,0,0,0,
सी # 191,255,174,252,0,0,0,0,0,0,0,0,3,0,0,0,
एईएस एन्क्रिप्टेड
सी ++ 130,187,182,115,251,12,63,157,109,110,234,35,137,208,172,203,
सी # 248,197,125,177,46,103,91,217,246,8,202,219,115,4,213,37,

सी ++ CLR कंसोल आवेदन

// ConsoleApplication2.cpp : main project file. 

#include "stdafx.h" 

using namespace System; 
using namespace System::Security::Cryptography; 


void unpack(unsigned int a, unsigned char *b) 
{ /* unpack bytes from a word */ 
    b[0] = unsigned char(a); 
    b[1] = unsigned char(a >> 8); 
    b[2] = unsigned char(a >> 16); 
    b[3] = unsigned char(a >> 24); 

} 

array<unsigned char>^ AES_encrypt_block(array<unsigned char>^ plainText) 
{ 
    array<unsigned char>^ key = gcnew array<unsigned char>(16); 
    key[0] = 0x01; key[1] = 0x01; key[2] = 0x01; key[3] = 0x01; key[4] = 0x01; key[5] = 0x01; key[6] = 0x01; key[7] = 0x01; 
    key[8] = 0x01; key[9] = 0x01; key[10] = 0x01; key[11] = 0x01; key[12] = 0x01; key[13] = 0x01; key[14] = 0x01; key[15] = 0x01; 

    AesManaged^ AES = gcnew AesManaged(); 
    AES->BlockSize = 128; 
    AES->KeySize = 128; 
    AES->Key = key; 
    AES->Mode = CipherMode::ECB; 
    AES->Padding = PaddingMode::None; 

    array<unsigned char>^ output_buffer = gcnew array<unsigned char>(16); 

    ICryptoTransform^ encryptor = AES->CreateEncryptor(AES->Key, AES->IV); 
    encryptor->TransformBlock(plainText, 0, plainText->Length, output_buffer, 0); 

    return output_buffer; 
} 

void from_base_256(unsigned char *y, int len, int s, char *x) 
{ 
    int i, m, n; 
    unsigned int c, d; 

    m = 16; 
    n = 0; c = 0; 
    for (;;) 
    { 
     while (m>0 && y[m - 1] == 0) m--; 
     d = 0; 

     for (i = m - 1; i >= 0; i--) 
     { 
      d = (d << 8) + y[i]; 
      y[i] = d/s; 
      d %= s; 
     } 


     d += c + x[n]; c = 0; 
     if ((int)d >= s) 
     { 
      c = 1; x[n] = d - s; 
     } 
     else x[n] = d; 

     n++; 
     if (n >= len) break; 
    } 
} 

int to_base_256(char *x, int len, int s, unsigned char *y) 
{ 
    int i, j, m; 
    unsigned int c; 

    for (i = 0; i<16; i++) 
     y[i] = 0; 
    if (len == 0) return 0; 

    m = 1; y[0] = x[len - 1]; 
    for (j = len - 2; j >= 0; j--) 
    { 
     c = x[j]; 
     for (i = 0; i<m; i++) 
     { 
      c += (unsigned int)y[i] * s; 
      y[i] = c & 0xff; 
      c >>= 8; 
     } 
     if (c>0) { m++; y[m - 1] = c; } 
    } 

    return m; 
} 



int main(array<System::String ^> ^args) 
{ 


    int i, n; 

    //PLAINTEXT 
    char x[256]; 
    x[0] = 1; x[1] = 4; x[2] = 2; x[3] = 5; x[4] = 6; x[5] = 9; x[6] = 8; x[7] = 7; 
    x[8] = 2; x[9] = 1; x[10] = 5; x[11] = 4; x[12] = 6; x[13] = 5; x[14] = 3; x[15] = 2; 

    unsigned int TL, TR; 

    TR = 0;  
    TL = 0; 

    int j; 
    char *left, *right; 
    unsigned char buff[16]; 
    int l, r; 
    l = r = 16/2; 
    if (16 % 2 == 1) l++; 

    left = &x[0]; right = &x[l]; 

    for (j = 0; j < 8; j++) 
    { 
     System::Diagnostics::Debug::WriteLine(""); 
     System::Diagnostics::Debug::WriteLine("ROUND " + (j+1)); 

     if (j % 2 == 0) 
     { 
      to_base_256(right, r, 10, buff); 

      unpack(TR^j, &buff[12]); 

      int size = sizeof(buff)/sizeof(*buff); 
      array<unsigned char>^ inputPlaintext = gcnew array<unsigned char>(size); 
      for (int i = 0; i < size; i++) 
       inputPlaintext[i] = buff[i]; 

      System::Diagnostics::Debug::WriteLine(""); 
      System::Diagnostics::Debug::WriteLine("INPUT"); 
      for (int z = 0; z < size; z++) 
       System::Diagnostics::Debug::Write(inputPlaintext[z] + ","); 

      array<unsigned char>^ result = AES_encrypt_block(inputPlaintext); 

      System::Diagnostics::Debug::WriteLine(""); 
      System::Diagnostics::Debug::WriteLine("AES ENCRYPTED"); 
      for (int z = 0; z < size; z++) 
       System::Diagnostics::Debug::Write(result[z] + ","); 

      pin_ptr<unsigned char>buff = &result[0]; 

      from_base_256(buff, l, 10, left); 

      System::Diagnostics::Debug::WriteLine(""); 
      System::Diagnostics::Debug::WriteLine("afterFromBase256 - left"); 
      for (int z = 0; z < sizeof(left)/sizeof(*left); z++) 
       System::Diagnostics::Debug::Write(left[z] + " , "); 
     } 
     else 
     { 
      to_base_256(left, l, 10, buff); 

      unpack(TL^j, &buff[12]); 

      int size = sizeof(buff)/sizeof(*buff); 
      array<unsigned char>^ inputPlaintext = gcnew array<unsigned char>(size); 
      for (int i = 0; i < size; i++) 
       inputPlaintext[i] = buff[i]; 

      System::Diagnostics::Debug::WriteLine(""); 
      System::Diagnostics::Debug::WriteLine("INPUT"); 
      for (int z = 0; z < size; z++) 
       System::Diagnostics::Debug::Write(inputPlaintext[z] + ","); 

      array<unsigned char>^ result = AES_encrypt_block(inputPlaintext); 

      System::Diagnostics::Debug::WriteLine(""); 
      System::Diagnostics::Debug::WriteLine("AES ENCRYPTED"); 
      for (int z = 0; z < size; z++) 
       System::Diagnostics::Debug::Write(result[z] + ","); 

      pin_ptr<unsigned char>buff = &result[0]; 

      from_base_256(buff, r, 10, right); 

      System::Diagnostics::Debug::WriteLine(""); 
      System::Diagnostics::Debug::WriteLine("afterFromBase256 - right"); 
      for (int z = 0; z < sizeof(right)/sizeof(*right); z++) 
       System::Diagnostics::Debug::Write(right[z] + " , "); 
     } 
    } 

    return 0; 
} 

सी # कंसोल आवेदन

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Security.Cryptography; 
using System.IO; 
using System.Numerics; 

namespace BPS_ConsoleTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      //integer array to hold the bytes of plaintext 
      int[] plaintext = new int[16] { 1, 4, 2, 5, 6, 9, 8, 7, 2, 1, 5, 4, 6, 5, 3, 2 }; 

      byte[] key = new byte[16]; 
      key[0] = 0x01; key[1] = 0x01; key[2] = 0x01; key[3] = 0x01; key[4] = 0x01; key[5] = 0x01; key[6] = 0x01; key[7] = 0x01; 
      key[8] = 0x01; key[9] = 0x01; key[10] = 0x01; key[11] = 0x01; key[12] = 0x01; key[13] = 0x01; key[14] = 0x01; key[15] = 0x01; 

      //Block Cipher - AES-128 
      AES AESEncrypt = new AES(key); 

      int bits = 128 - 32; //128 block for AES-128 

      //tweak 
      int tweak = 0; //64 bit user provided tweak value 
      int TR = 0; //left side of tweak 
      int TL = 0; //right side of tweak 

      int s = 10; 

      int w = 8; //recommended number of rounds 

      int BLOCK_SIZE = 16; //block size in bytes (16 = 128 bits for AES-128) 
      int b = 0; //s-integer input length 


      b = plaintext.Length; 

      //Split the tweak into right and left 
      // 

      TR = tweak % (1 << 32); 
      TL = (tweak - TR)/(1 << 32); 

      //Split the plaintext into left and right substrings 
      // 
      int j = 0; 
      int[] XR; //right substring 
      int[] XL; //left substring 

      int l; //length of left substring 
      int r; //length of right substring 

      if (b % 2 == 1) //b is odd 
      { 
       l = (b + 1)/2; 
       r = (b - 1)/2; 
      } 
      else //b is even 
      { 
       l = r = b/2; 
      } 

      XL = new int[l]; 
      XR = new int[r]; 

      for (int i = 0; i < l; i++) 
       XL[i] = plaintext[i]; 

      j = 0; 
      for (int i = l; i <= l + r - 1; i++, j++) 
       XR[j] = plaintext[i]; 


      //initialize left and right branches 

      BigInteger L = 0; 

      for (int i = 0; i < l; i++) 
      { 
       L += XL[i] * BigInteger.Pow(s, i); 
      } 

      BigInteger R = 0; 

      for (int i = 0; i < l; i++) 
      { 
       R += XR[i] * BigInteger.Pow(s, i); 
      } 


      byte[] initial_Lbytes = L.ToByteArray(); 
      byte[] initial_Rbytes = R.ToByteArray(); 

      int[] intitial_L = new int[l]; 
      int[] intitial_R = new int[r]; 

      foreach (byte bL in initial_Lbytes) 
      { 
       BigInteger num = new BigInteger(new byte[] { bL }); 
      } 

      //8 Rounds 
      for (int i = 0; i < 8; i++) 
      { 
       System.Diagnostics.Debug.WriteLine(""); 
       System.Diagnostics.Debug.WriteLine("ROUND " + (i + 1)); 

       if (i % 2 == 0) //even 
       { 
        byte[] RBytes = R.ToByteArray(); 

        byte[] inputPlaintext = new byte[16]; 
        for (int k = 0; k < RBytes.Length; k++) 
         inputPlaintext[k] = RBytes[k]; 

        inputPlaintext = INT2LE(TR^i, inputPlaintext); 

        System.Diagnostics.Debug.WriteLine("INPUT"); 
        foreach (byte bb in inputPlaintext) 
         System.Diagnostics.Debug.Write(bb + ","); 

        byte[] t = AESEncrypt.Encrypt(inputPlaintext); 

        System.Diagnostics.Debug.WriteLine(""); 
        System.Diagnostics.Debug.WriteLine("AES ENCRYPTED"); 
        foreach (byte bb in t) 
         System.Diagnostics.Debug.Write(bb + ","); 

        BigInteger AESResult = new BigInteger(t); 

        BigInteger res = (L + AESResult) % BigInteger.Pow(s, l); 

        L = res; 

       } 
       else //odd 
       { 

        byte[] LBytes = L.ToByteArray(); 


        byte[] inputPlaintext = new byte[16]; 
        for (int k = 0; k < LBytes.Length; k++) 
         inputPlaintext[k] = LBytes[k]; 

        inputPlaintext = INT2LE(TL^i, inputPlaintext); 

        System.Diagnostics.Debug.WriteLine("INPUT"); 
        foreach (byte bb in inputPlaintext) 
         System.Diagnostics.Debug.Write(bb + ","); 

        byte[] t = AESEncrypt.Encrypt(inputPlaintext); 

        System.Diagnostics.Debug.WriteLine(""); 
        System.Diagnostics.Debug.WriteLine("AES ENCRYPTED"); 
        foreach (byte bb in t) 
         System.Diagnostics.Debug.Write(bb + ","); 

        BigInteger AESResult = new BigInteger(t); 

        BigInteger res = (R + AESResult) % BigInteger.Pow(s, r); 

        R = res; 
       } 
      } 

      BigInteger FINAL_R = R; 
      BigInteger FINAL_L = L; 

     } 

     public static byte[] INT2LE(Int32 data, byte[] arr) 
     { 
      byte[] b = arr; 
      b[12] = (byte)data; 
      b[13] = (byte)(((uint)data >> 8) & 0xFF); 
      b[14] = (byte)(((uint)data >> 16) & 0xFF); 
      b[15] = (byte)(((uint)data >> 24) & 0xFF); 
      return b; 
     } 
    } 


    public class AES : IBlockCipher 
    { 
     private byte[] _key; 
     public AES(byte[] key) 
     { 
      _key = key; 
     } 
     public byte[] Encrypt(byte[] input) 
     { 
      byte[] output_buffer = new byte[16]; 
      using (AesManaged E = new AesManaged()) 
      { 
       E.BlockSize = 128; 
       E.KeySize = 128; 
       E.Mode = CipherMode.ECB; 
       E.Key = _key; 
       E.Padding = PaddingMode.None; 
       //E.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 

       // Create a decrytor to perform the stream transform. 
       ICryptoTransform encryptor = E.CreateEncryptor(E.Key, E.IV); 
       encryptor.TransformBlock(input, 0, 16, output_buffer, 0); 

      } 

      //return encrypted; 
      return output_buffer; 
     } 
    } 

    interface IBlockCipher 
    { 
     byte[] Encrypt(byte[] input); 
    } 


} 
+0

बस एक साइड नोट के रूप में - यदि आप एन्क्रिप्शन का अध्ययन करने के लिए ऐसा कर रहे हैं, कोई समस्या नहीं है, लेकिन उत्पादन में एन्क्रिप्शन एल्गोरिदम के अपने कार्यान्वयन को रखने से सावधान रहें। भेद्यताएं पेश करना बहुत आसान है जो मूल कार्यान्वयन में मौजूद नहीं हैं, अक्सर नए पक्ष चैनल हमलों, लेकिन आपके द्वारा उपयोग की जाने वाली पुस्तकालयों में भी कमजोरियां। –

+0

@ केविनकेन उन कुछ हमलों को हार्डवेयर तक पहुंच की आवश्यकता नहीं है जिस पर सादे पाठ का एन्क्रिप्शन किया गया था? – erotavlas

+0

हां, कुछ करते हैं, लेकिन मैंने केवल उन उदाहरणों के रूप में उल्लेख किया है। अधिक महत्वपूर्ण विचार यह है कि आप * नहीं जानते * आप किस भेद्यता को पेश करते हैं। आपको अपने स्वयं के कोड, और आपके द्वारा उपयोग की जाने वाली किसी भी पुस्तकालय के पूर्ण विश्लेषण की आवश्यकता होगी। कार्यान्वयन के मुद्दे के कारण हुई भेद्यता के लिए एक उदाहरण हार्टबलेड था - और यह ओपनएसएसएल के विशेषज्ञों के साथ हुआ। –

उत्तर

10

कि BigInteger constructor के लिए दस्तावेज़ स्पष्ट रूप से कहा गया है:

निर्माता साइन-और-परिमाण प्रतिनिधित्व उपयोग करने के लिए बाइट सरणी में सकारात्मक मूल्यों की उम्मीद है, और करने के लिए ऋणात्मक मानों दो का पूरक प्रतिनिधित्व का उपयोग करें। दूसरे शब्दों में, यदि का उच्चतम ऑर्डर बिट मूल्य में उच्चतम ऑर्डर बाइट सेट है, परिणामी बिगइंटर मूल्य नकारात्मक है।बाइट सरणी के स्रोत के आधार पर, इससे नकारात्मक मान के रूप में गलत व्याख्या करने के लिए सकारात्मक मान हो सकता है।

इसे ठीक करने के कई तरीके हैं, जिनमें से सबसे आसान बाइट सरणी में शून्य बाइट जोड़ना है यदि इसे अन्यथा नकारात्मक संख्या के रूप में व्याख्या किया जाए। ऐसा करने के लिए यहां एक आसान तरीका है।

public static BigInteger BuildPositiveBigInteger(byte [] littleEndianBytes) { 
    if (littleEndianBytes[littleEndianBytes.Length-1] >= 0x80) { 
     byte[] newBytes = new byte[littleEndianBytes.Length + 1]; 
     littleEndianBytes.CopyTo (newBytes, 0); 
     return new BigInteger (newBytes); 
    } else { 
     return new BigInteger (littleEndianBytes); 
    } 
} 

अपने कोड में, यदि आप BuildPositiveBigInteger के लिए कॉल के साथ new BigInteger(byte[]) के सभी उदाहरणों की जगह यह अपेक्षित तरीके से चलना चाहिए।

+0

मैंने इस विधि को भी टी। कॉनकैट (नया बाइट [] {0}) की कोशिश की। ToArray() हालांकि प्रोफाइलर के अनुसार आपकी विधि तेज थी। धन्यवाद। – erotavlas

संबंधित मुद्दे