1. 程式人生 > >給INI檔案內容XOR加密 VC實現

給INI檔案內容XOR加密 VC實現

這兩天主要在搞一些檔案加密,ini格式還有xml格式的檔案加密

本人用了一個最簡單的異或加密,呵呵。在加解密這塊是個新手。請多多包含。

下面是異或加密的簡單介紹

加密演算法中最廣泛使用也是最有用的運算之一是   XOR。有必要理解   XOR   為什麼如此有助於加密演算法。XOR(在密碼術中使用時)是一種位(bitwise)數字函式,其定義域是一個位對而值域是一個結果位。(在形式邏輯中使用時,它有細微差異,但還是同構的。)大多數讀者可能已經很熟悉   XOR   的結果表,但還是讓我們來看一下,以幫助回憶一下:  
        XOR(1,   1)   -->   0
        XOR(1,   0)   -->   1
        XOR(0,   1)   -->   1
        XOR(0,   0)   -->   0
上表中我們以字首形式書寫   XOR   函式,但是大多數程式語言使用中綴形式。不必擔心符號   —   上表只是幫助闡明   XOR   函式的本質。還有,在大多數程式語言中,稱為   XOR   的運算(或更準確地說是“按位   XOR”)所做的比上表所顯示的要多,而上表只是作為一般的法則。也就是說,在象   C、Perl   或   Python   之類的運算中,“^”實際上是兩位域(或   ASCII   字元、整數等等,認為是位欄位)中的每個對應位的布林   XOR。原則上,擁有一位   XOR   的語言可以通過在各個位的位置上迴圈來模擬位域   XOR   的運算行為(但是複合位域   XOR   的計算效率要高很多)。  

那麼   XOR   到底特殊在哪裡呢?首先,假設我們希望對一個明文位執行密碼替代。我們希望防止攻擊者對我們明文位轉換後將要得到的值進行任何預測(即使是統計上的)。使用   XOR,明文的   0   位可能成為密文的   1   或   0,這取決於用作“加密位”(定義域對中的第二位)是   1   還是   0。對明文中的   1   也是同樣的。轉換的完全不可預測性對於密碼術而言是理想的(除非您有權訪問加密位)。  

XOR   的另一個重要特性是無損。實際上,XOR   是直接可逆的。也就是說,如果我們有   Cb   =   Pb   XOR   Kb,那麼就自動知道   Pb   =   Cb   XOR   Kb。即,如果(且僅如果)兩次使用相同的加密位,則對第一次   XOR   運算的結果再應用   XOR   運算將返回原始(明文)位。XOR   與另一個布林運算的行為對比:
        AND(1,   1)   -->   1
        AND(1,   0)   -->   0
        AND(0,   1)   -->   0
        AND(0,   0)   -->   0
在執行   AND   運算的過程中,我們丟失了資訊。假設我們知道   0   =   Pb   AND   Kb。沒有加密位我們確實無法重新計算出   Pb。但是,如果   Kb   恰好為   0,即使擁有加密位,我們也無法重新計算出   Pb!我們根本無法取回   Pb   的值。  

儘管   XOR   象它的運算行為一樣好,但是它不象一些人幼稚地(或不懷好意地)宣稱的那樣好。而現實世界中有數目驚人的應用程式使用僅僅由   XOR   構成的加密。提醒一下,在一種情況下這工作得很好   —   一次性密碼本(OTP)。如果您恰好有和待加密的明文一樣多的金鑰資料,可以證明   XOR   是理想的加密方法(假設金鑰資料是真正隨機的,也就是說,它具有的平均資訊量和其長度相等,因此其語言比率為   1)。  

許多有缺陷的演算法只使用很小數量的金鑰資料,將每個明文塊與金鑰塊進行   XOR   運算,然後就將結果稱為密文。對於單一塊這很有效。但是當您開始重用同一金鑰塊來加密多個密文時,整個安全性就土崩瓦解了。  

幼稚的   XOR   加密到底是如何顯示其弱點的呢?基本上,它無力防範頻率分析。假設我們使用   8   位元組長的明文塊和相應   8   位元組長的加密金鑰。(塊更長也沒有太大區別;雖然這會要求更多的已知密文,但應用的引數還是相同的。)找到一些密文並只臨時忽略密文中除位元組   1、9、17   等以外的任何東西。  

對應於每塊首部密文的明文將仍然和整個明文具有相同頻率的規律性。並且每個相同的明文位元組都會轉換成相同的密文位元組。因此通過知道明文的   13%   是由字母“E”組成的(假設是英語散文),我們所需要做的全部就是尋找以相同頻率出現的密文位元組值(這裡我們通過忽略大小寫和標點來簡化示例,但這對於概念並不重要)。一旦找到了這些對應的明文和密文位元組,立即就可以通過   KB   =   PB   XOR   CB   得出金鑰位元組,舉個例子:KB   =   'E '   XOR   'q '。一旦知道了金鑰位元組,我們就可以對所有其明文不是“E”的密文值解密,而無須進一步工作。對   [2,10,18,...]   和   [3,11,19,...]   密文位元組重複相同過程,以此類推。

下面就寫一個簡單的程式(網上有這樣的簡單例程)

#include "stdafx.h"
#include
<stdio.h>
#include
<windows.h>
main()
{
    FILE
*fp,*fp2;int i,j;  //i用作記錄0到255之間任一個數,j用作記錄當前XOR的位元組位置byte*buffer,*buffer1,*buffer2,*buffer3;    
    buffer
=(byte*)malloc(16);        //分配16個位元組給buffer指向的位置    buffer2 =(byte*)malloc(16*256);   //分配16*256個位元組給buffer2指向的位置

    fp = fopen("animation.cfg", "rb");//開啟懷疑加密了的檔案    buffer3=buffer2;                  //buffer3儲存buffer2初始時的地址for (i=0;i<=255;i++)
    {
        buffer1
=buffer;                //buffer1儲存buffer初始時的地址        fseek(fp, 0, 0);               //重定位到animation.cfg檔案的開頭        fread(buffer1, 16, 1, fp);     //讀取animation.cfg檔案的開頭16位元組資料到buffer
for(j=0;j<16;j++
        {
           
*buffer1=*buffer1^i; //animation.cfg檔案的開頭第一個位元組和0~255之間
                                
//任一個數值異或,結果儲存在buffer1所指的位置上*buffer2=*buffer1;   //將buffer1所指向的資料複製到buffer2所指的位置            buffer1=buffer1+1;   //buffer1指標加1,準備讀取下一個資料            buffer2=buffer2+1;   //buffer2指標加1,準備儲存下一個資料        }
    }
    fp2
= fopen("test", "wb+");  //開啟一個二進位制檔案,準備將資料寫入    fwrite(buffer3, 16*256, 1, fp2);//buffer3儲存buffer2初始時的地址,這個語句將buffer2初始時的地址所指的資料,用二進位制方式寫入16×256位元組    fclose(fp2);                 //關閉檔案控制代碼    fclose(fp);

仔細再看看程式還是有一點問題的,我試了一下,待加密的字串依然在存在,只不過加密後多了那麼多字元確實是對原字串加密後的 i應該從1開始 就避免了原字串的存在,這樣雖然起到加密的作用,但無緣無故多出那麼多的空間,浪費啊。我建議把這樣的 幾句程式放到第一個for迴圈裡
  buffer2 =(byte*)malloc(16*256); //分配16*256個位元組給buffer2指向的位置
  fp = fopen("animation.cfg", "rb");//開啟懷疑加密了的檔案
  buffer3=buffer2; //buffer3儲存buffer2初始時的地址

另外分配記憶體的空間最好根據檔案的大小來設定 ,

fseek(fp,0,SEEK_END);     //定位到檔案末  
nFileLen = ftell(fp);       //檔案長度

減少空間的浪費

下面我經過我重新更改過的程式:

#include "stdafx.h"

#include<stdio.h>
#include<windows.h>
void main()
{
    FILE *fp,*fp2;int i,j;  //i用作記錄0到255之間任一個數,j用作記錄當前XOR的位元組位置
    byte *buffer,*buffer1,*buffer2,*buffer3;//指標buffer和buffer1一組,指標buffer2和buffer3 一組,buffer指標會變動,buffer指標永遠指向buffer的第一個位元組位置,buffer2和buffer3同樣道理
    
      fp = fopen("config1.ini", "rb");   //開啟懷疑加密了的檔案
   fseek(fp,0,SEEK_END);     //定位到檔案末  
    int k = ftell(fp);       //檔案長度

    for (i=0;i<=255;i++)
    {
  ///////////////////////////////////////////////////////////////////////////////
  buffer =(byte*)malloc(k);        //分配k個位元組給buffer指向的位置
  buffer2 =(byte*)malloc(k);   //分配k個位元組給buffer2指向的位置
  buffer3=buffer2;                  //buffer3儲存buffer2初始時的地址
        ///////////////////////////////////////////////////////////////////////////////
        buffer1=buffer;                //buffer1儲存buffer初始時的地址
        fseek(fp, 0, 0);               //重定位到檔案的開頭
        fread(buffer1, k, 1, fp);     //讀取檔案的開頭k位元組資料到buffer
        for(j=0;j<k;j++) 
        {
            *buffer1=*buffer1^i; //檔案的開頭第一個位元組和0~255之間
                                 //任一個數值異或,結果儲存在buffer1所指的位置上
            *buffer2=*buffer1;   //將buffer1所指向的資料複製到buffer2所指的位置
            buffer1=buffer1+1;   //buffer1指標加1,準備讀取下一個資料
            buffer2=buffer2+1;   //buffer2指標加1,準備儲存下一個資料
        }
    }
    fp2 = fopen("config2.ini", "wb+");  //開啟一個二進位制檔案,準備將資料寫入
    fwrite(buffer3, k, 1, fp2);//buffer3儲存buffer2初始時的地址,這個語句將buffer2初始時的地址所指的資料,用二進位制方式寫入16×256位元組
    fclose(fp2);                 //關閉檔案控制代碼
    fclose(fp);

 最後再給個連結:字串異或加解密演算法 供大家學習和參考