免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
自制基于rc5的一個(gè)文件加密小程序

來(lái)源:https://blog.csdn.net/lingqinghua/article/details/741734
標(biāo)簽:RC5,加密,解密
收藏:株野
作者:lingqinghua
日期:2006年05月16日 21:13:00


RC5分組密碼算法是1994由麻薩諸塞技術(shù)研究所的Ronald L. Rivest教授發(fā)明的,并由RSA實(shí)驗(yàn)室分析。它是參數(shù)可變的分組密碼算法,三個(gè)可變的參數(shù)是:分組大小、密鑰大小和加密輪數(shù)。在此算法中使用了三種運(yùn)算:異或、加和循環(huán)。

    名       稱:RC5

    提出時(shí)間:1994年

    提出人   : Ronald L. Rivest教授

    定      義: 參數(shù)可變的分組密碼算法

    可變參數(shù):分組大小、密鑰大小和加密輪數(shù)

    使用運(yùn)算: 異或、加和循環(huán)



相關(guān)介紹

編輯

簡(jiǎn)介

RC5是種比較新的算法,Rivest設(shè)計(jì)了RC5的一種特殊的實(shí)現(xiàn)方式,因此RC5算法有一個(gè)面向字的結(jié)構(gòu):RC5-w/r/b,這里w是字長(zhǎng)其值可以是16、32或64對(duì)于不同的字長(zhǎng)明文和密文塊的分組長(zhǎng)度為2w位,r是加密輪數(shù),b是密鑰字節(jié)長(zhǎng)度。由于RC5一個(gè)分組長(zhǎng)度可變的密碼算法,為了便于說(shuō)明在本文中主要是針對(duì)64位的分組w=32進(jìn)行處理的,下面詳細(xì)說(shuō)明了RC5加密解密的處理過(guò)程:

加密解密

1、創(chuàng)建密鑰
RC5算法加密時(shí)使用了2r+2個(gè)密鑰相關(guān)的的32位字: ,這里r表示加密的輪數(shù)。創(chuàng)建這個(gè)密鑰組的過(guò)程是非常復(fù)雜的但也是直接的,首先將密鑰字節(jié)拷貝到32位字的數(shù)組L中(此時(shí)要注意處理器是little-endian順序還是big-endian順序),如果需要,最后一個(gè)字可以用零填充。然后利用線性同余發(fā)生器模2初始化數(shù)組S:
對(duì)于i=1到2(r+1)-1: (本應(yīng)模 ,本文中令w=32)
其中對(duì)于16位字32位分組的RC5,P=0xb7e1 Q=0x9e37
對(duì)于32位字和64位分組的RC5,P=0xb7e15163 Q=0x9e3779b9
對(duì)于64位字和128位分組,P=0xb7151628aed2a6b Q=0x9e3779b97f4a7c15
最后將L與S混合,混合過(guò)程如下:
i=j=0
A=B=0
處理3n次(這里n是2(r+1)和c中的最大值,其中c表示輸入的密鑰字的個(gè)數(shù))
2、加密處理
在創(chuàng)建完密鑰組后開(kāi)始進(jìn)行對(duì)明文的加密,加密時(shí),首先將明文分組劃分為兩個(gè)32位字:A和B(在假設(shè)處理器字節(jié)順序little-endian、w=32的情況下,第一個(gè)明文字節(jié)進(jìn)入A的最低字節(jié),第四個(gè)明文字節(jié)進(jìn)入A的最高字節(jié),第五個(gè)明文字節(jié)進(jìn)入B的最低字節(jié),以此類推),其中操作符<<<表示循環(huán)左移,加運(yùn)算是模 (本應(yīng)模 ,本文中令w=32)的。
輸出的密文是在寄存器A和B中的內(nèi)容
3、解密處理
解密也是很容易的,把密文分組劃分為兩個(gè)字:A和B(存儲(chǔ)方式和加密一樣),這里符合>>>是循環(huán)右移,減運(yùn)算也是模 (本應(yīng)模 ,本文中令w=32)的。
RSA試驗(yàn)室花費(fèi)了相當(dāng)?shù)臅r(shí)間來(lái)分析64位分組的RC5算法,在5輪后統(tǒng)計(jì)特性看起來(lái)非常好。在8輪后,每一個(gè)明文位至少影響一個(gè)循環(huán)。對(duì)于5輪的RC5,差分攻擊需要 個(gè)選擇明文;對(duì)10輪需要 個(gè);對(duì)于12輪需要 個(gè);對(duì)15輪需要 個(gè)。而對(duì)于64位的分組只有 個(gè)可能的明文,所以對(duì)于15輪或以上的RC5的差分攻擊是失敗的。在6輪后線性分析就是安全的了,Rivest推薦至少12輪,甚至可能是16輪。這個(gè)輪數(shù)可以進(jìn)行選擇。

參考例子

編輯

rfc 2040文檔中列出了RC5算法密鑰生成和加密實(shí)現(xiàn)的C代碼,在此筆者參照文檔中定義的算法結(jié)構(gòu),編寫(xiě)了用于對(duì)密文解密的程序代碼(此代碼經(jīng)多次測(cè)試運(yùn)行良好),供讀者參考。

宏定義

1、補(bǔ)充了兩個(gè)個(gè)宏定義
#define SHL1(x,s,w) ((RC5_WORD)((x)<<((w)-((s)&ROT_MASK))))
#define ROTR(x,s,w) ((RC5_WORD)(SHR1((x),(s))|SHL1((x),(s),(w))))

函數(shù)定義

2、解密函數(shù)定義如下:
void RC5_Block_Decrypt (RC5_WORD *S,int R,char *in,char *out)
{
    int i;
    RC5_WORD A,B;
    A = in[0] & 0xFF;
    A += (in[1] & 0xFF) << 8;
    A += (in[2] & 0xFF) << 16;
    A += (in[3] & 0xFF) << 24;
    B = in[4] & 0xFF;
    B += (in[5] & 0xFF) << 8;
    B += (in[6] & 0xFF) << 16;
    B += (in[7] & 0xFF) << 24;

    for(i=R;i>=1;i--)

    {
        B=ROTR((B-S[2*i+1]),A,W);
        B=B^A;
        A=ROTR((A-S[2*i]),B,W);
        A=A^B;
    }
    B=B-S[1];
    A=A-S[0];
    out[0] = (A >> 0) & 0xFF;
    out[1] = (A >> 8) & 0xFF;
    out[2] = (A >> 16) & 0xFF;
    out[3] = (A >> 24) & 0xFF;
    out[4] = (B >> 0) & 0xFF;
    out[5] = (B >> 8) & 0xFF;
    out[6] = (B >> 16) & 0xFF;
    out[7] = (B >> 24) & 0xFF;
    return;
}/*End of RC5_Block_Decrypt */
int RC5_CBC_Decrypt_Init (pAlg, pKey)
rc5CBCAlg *pAlg;
rc5UserKey *pKey;
{
if ((pAlg == ((rc5CBCAlg *) 0)) || (pKey == ((rc5UserKey *) 0)))
    return (0);
RC5_Key_Expand (pKey->keyLength, pKey->keyBytes,pAlg->R, pAlg->S);
    return (RC5_CBC_SetIV(pAlg, pAlg->I));
}
int RC5_CBC_Decrypt_Update(rc5CBCAlg *pAlg,int N,char *C,int *plainLen,char *P)
{
    int plainIndex,cipherIndex,j;
    plainIndex=cipherIndex=0;
    for(j=0;j<BB;j++)
    {
        P[plainIndex]=pAlg->chainBlock[j];
        plainIndex++;
    }
    plainIndex=0;
    while(cipherIndex<N)
    {
        if (pAlg->inputBlockIndex<BB)
        {
            pAlg->inputBlock[pAlg->inputBlockIndex]=C[cipherIndex];
            pAlg->inputBlockIndex++;
            cipherIndex++;
        }
        if (pAlg->inputBlockIndex==BB)
        {
            pAlg->inputBlockIndex=0;
            RC5_Block_Decrypt (pAlg->S,pAlg->R,pAlg->inputBlock,pAlg->chainBlock);
            for(j=0;j<BB;j++)
            {
                if (plainIndex<BB)
                    P[plainIndex]^=pAlg->chainBlock[j];
                else
                    P[plainIndex]=C[cipherIndex-16+j]^pAlg->chainBlock[j];
                plainIndex++;
            }
        }
    }
    *plainLen=plainIndex;
    return (1);
}    /*End of RC5_CBC_Decrypt_Update*/

常見(jiàn)模式

編輯

以上的操作只是針對(duì)的一個(gè)明文分組的,對(duì)于分組加密算法有以下幾種比較常見(jiàn)的分組密碼模式:

電子密碼本

電子密碼本(Electronic Code Book,,ECB)模式是使用分組密碼算法的最明顯的方式,其使用方式是一個(gè)明文分組加密成一個(gè)密文分組,相同的明文分組永遠(yuǎn)被加密成相同的密文分組,在理論上制造這樣的一個(gè)密碼本是可行的,但實(shí)際上要進(jìn)行大量的預(yù)計(jì)算耗費(fèi)存儲(chǔ)空間,最容易的運(yùn)行模式是每個(gè)明文分組可被獨(dú)立地進(jìn)行加密,但受分組重放攻擊。

密碼分組鏈接

密碼分組鏈接模式(Cipher Block Chaining,CBC)模式中,明文被加密之前要與前面的密文進(jìn)行異或運(yùn)算,如果前面的明文分組不同才能將完全相同的明文分組加密成不同的密文分組,這會(huì)給密碼分析者提供有用的線索,為了防止這種情況發(fā)生使用一個(gè)隨機(jī)數(shù)據(jù)分組作為加密的第一個(gè)分組叫作初始化向量(initialization Vector,IV),這樣就可以把完全相同的信息加密成不同的密文消息。

密碼反饋

密碼反饋模式(Cipher-Feedback,CFB)是把分組密碼算法用于自同步序列密碼的一種方法,在CBC模式下,整個(gè)數(shù)據(jù)分組在接收完之后才能進(jìn)行加密,在此模式下數(shù)據(jù)可以在比分組小的多的單元里進(jìn)行處理。

輸出反饋

輸出反饋模式(Output-Feedback,OFB)是將分組密碼用于同步序列密碼運(yùn)行的一種方法,它有一個(gè)很好的特性就是在明文存在前的大部分工作可以離線進(jìn)行。以上幾種模式中密碼分組鏈接模式是在安全協(xié)議中使用的最為普遍,在無(wú)線應(yīng)用協(xié)議中安全層定義的分組加密算法都是CBC模式。幾大手機(jī)廠家如Nokia,Motorala,Erison的WAP手機(jī)的首選的分組加密算法就是RC5。



自制基于rc5的一個(gè)文件加密小程序

//#include<time.h>

#include<afx.h>
#include <stdio.h>

#define KEYSIZE 16     /* size of key, in bytes */

#if !defined UINT
typedef unsigned int UINT; /* Should be 32-bit = 4 bytes        */
#endif

typedef enum { ShiftLeft, ShiftRight } ShiftDir;

typedef enum { KeyWords = KEYSIZE / 4,
           NumRounds = 15,  /* Number of cryptographic rounds  */
           TableSize = 32   /* size of table = 2 * (NumRounds + 1) */
} bogus;

UINT Table[ TableSize ];
UINT L[KeyWords];


UINT ROT(const UINT x, const UINT y, const ShiftDir dir)
{

  const unsigned int ShiftAmt = (y & (unsigned int)0x1f);
  const unsigned int ShiftBack = 0x20 - ShiftAmt;
  unsigned int result;
 
  if (dir == ShiftLeft)
    result = (x << ShiftAmt) | (x >> ShiftBack);
  else
    result = (x >> ShiftAmt) | (x << ShiftBack);
  return result;

} /* ROT */



//設(shè)置密鑰
void SetKey( unsigned char KeyChar )
{
    static unsigned int KeyCntr;
    static unsigned int Shift;

    int ix = KeyCntr >> 2;

    /* this is simply a machine independent way of setting L[i] to
       KeyChar[i], without being affect by "endianess". */
    L[ ix ] = (L[ ix ] & (~(0xff << Shift))) | (KeyChar << Shift);

    Shift = (Shift + 8) & 0x1f;

    KeyCntr = (KeyCntr + 1) & (KEYSIZE - 1); 

    /* This Depends on KEYSIZE being  a power of two.  The & will cause the 

        KeyCntr to wrap  and only have values in the range 0..KEYSIZE-1.    */
}  /* RC5_Crypto */


//雙字加密函數(shù)
/* 2 UINT: input plain text, output encrypted text    */
void encrypt(UINT *PlainText, UINT *CryptoText)
{

  UINT i, temp;
  UINT A;
  UINT B;

  A = PlainText[0] + Table[0];
  B = PlainText[1] + Table[1];

  for (i = 1; i <= NumRounds; i++) {
    temp = i << 1;
    A = ROT(A^B, B, ShiftLeft) + Table[temp];
    B = ROT(A^B, A, ShiftLeft) + Table[temp+1];
  }
  CryptoText[0] = A;
  CryptoText[1] = B; 
}  /* RC5_Cypto::encrypt */

//雙字解密函數(shù)
/* 2 UINT input encrypted text, output plain text    */
void decrypt(UINT *CryptoText, UINT *PlainText)
{
  UINT i, temp;
  UINT B;
  UINT A;

  B = CryptoText[1];
  A = CryptoText[0];

  for (i=NumRounds; i > 0; i--) {
    temp = i << 1;
    B = ROT(B - Table[temp+1],A, ShiftRight)^A;
    A = ROT(A - Table[temp],  B, ShiftRight)^B;
  }
  PlainText[1] = B-Table[1];
  PlainText[0] = A-Table[0]; 

}     /*  decrypt */



//初始化函數(shù)
void setup() /* secret input key K[0...KEYSIZE-1]   */
{
  /* magic constants (courtesty of RSA) */
  static const UINT ROM[ TableSize ] = { 0xb7e15163, 0x5618cb1c, 0xf45044d5,
                                         0x9287be8e, 0x30bf3847, 0xcef6b200,
                                         0x6d2e2bb9, 0x0b65a572, 0xa99d1f2b,
                                         0x47d498e4, 0xe60c129d, 0x84438c56,
                                         0x227b060f, 0xc0b27fc8, 0x5ee9f981,
                                         0xfd21733a, 0x9b58ecf3, 0x399066ac,
                                         0xd7c7e065, 0x75ff5a1e, 0x1436d3d7,
                                         0xb26e4d90, 0x50a5c749, 0xeedd4102,
                                         0x8d14babb, 0x2b4c3474, 0xc983ae2d,
                                         0x67bb27e6, 0x05f2a19f, 0xa42a1b58,
                                         0x42619511, 0xe0990eca };
  UINT i;
  UINT A;
  UINT B;
  UINT j;
  UINT k;
 
  /* Copy "ROM" into "RAM" */
  for (i=0; i < TableSize; i++)
    Table[i] = ROM[i];

  /* 3*t > 3*KeyWords */

  A = 0;
  B = 0;
  i = 0;
  j = 0;

  for (k=0; k < 3*TableSize; k++) {
    Table[i] = ROT(Table[i]+(A+B),3, ShiftLeft);
    A = Table[i];
    L[j] = ROT(L[j]+(A+B),(A+B), ShiftLeft); 
    B = L[j];
    i= (i+1) & (TableSize-1);  /* using '&' for % only works for powers of 2  */
    j= (j+1) & (KeyWords-1);
  }
}     /* setup */


//文件加密函數(shù)
bool EncryptFile(char *pchFileName)
{
    CFile    fileb4;
    CFile    encryptfile;
    CFileException e;
    char    pchEncryptFileName[100];
    sprintf(pchEncryptFileName, "$%s", pchFileName);
    //處理文件打開(kāi)的異常情形。
    if( !fileb4.Open( pchFileName, CFile::modeRead | CFile::shareDenyNone, &e ) )
    {
        printf("%s could not be opened %d/n", pchFileName, e.m_cause);
        return false;
    }
    if ( !encryptfile.Open( pchEncryptFileName, CFile::modeCreate | CFile::modeWrite, &e ))
    {
        printf("%s could not be created %d/n", pchEncryptFileName, e.m_cause);
        fileb4.Close();
        return false;
    }

    BYTE    bBuffer[8];
    BYTE    bEncryptFileHead[8];
    UINT    uFileLen = fileb4.GetLength();        /* 文件長(zhǎng)度 */

    memcpy(bEncryptFileHead,     "ISDN",    4);
    memcpy(bEncryptFileHead + 4, &uFileLen, 4);

    encryptfile.Write(bEncryptFileHead, 8);    /* 寫(xiě)文件頭 */

    DWORD    dwRead;
    UINT    uPlainData[2];
    UINT    uCryptoData[2];
    do
    {
        memset(bBuffer, 0, 8);
        dwRead = fileb4.Read(bBuffer, 8);
        if ( dwRead > 0 && dwRead <= 8 )
        {
            memcpy(&uPlainData[0], bBuffer    , 4);
            memcpy(&uPlainData[1], bBuffer + 4, 4);
           
            encrypt(uPlainData, uCryptoData);          /* 加密雙字 */    

            encryptfile.Write(&uCryptoData[0], 4);    /* 寫(xiě)入加密文件 */
            encryptfile.Write(&uCryptoData[1], 4);
        }
        //else if ( 8 > dwRead && 1 <= dwRead )
        //{
        //   
        //}       
    }
    while (dwRead > 0);                /* 循環(huán)條件 */

    // Close both files
    encryptfile.Close();
    fileb4.Close();

    //刪除明文文件,重命名加密文件。

    try
    {
        CFile::Remove(pchFileName);
        try
        {
            CFile::Rename( pchEncryptFileName, pchFileName );
        }
        catch(CFileException* pExRename )
        {
            printf( "File %s not found %d/n", pchEncryptFileName, pExRename->m_cause);
            pExRename->Delete();
        }
    }
    catch (CFileException* pExRemove)
    {
        printf( "File %s cannot be removed/n", pchFileName);
        pExRemove->Delete();
    }   

    return true;

}


//文件解密函數(shù)

bool DecryptFile(char *pchFileName, unsigned int uiOffset, void *pMem, unsigned int &uiMemSize)
{
    CFile    fileb4;
    CFile    decryptfile;
    CFileException e;
    char    pchDecryptFileName[100];        //文件的全路徑名稱。
    sprintf(pchDecryptFileName, "$%s", pchFileName);    //賦值新文件名。
    // 處理文件打開(kāi)的異常情形。
    if( !fileb4.Open( pchFileName, CFile::modeRead | CFile::shareDenyNone, &e ) )
    {
        printf("%s could not be opened %d/n", pchFileName, e.m_cause);
        return false;
    }
    if ( !decryptfile.Open( pchDecryptFileName, CFile::modeCreate | CFile::modeWrite, &e ))
    {
        printf("%s could not be created %d/n", pchDecryptFileName, e.m_cause);
        fileb4.Close();
        return false;
    }

    UINT    uFileLen = fileb4.GetLength();        /* 文件長(zhǎng)度 */
    if ( uFileLen % 8 != 0 )
    {
        printf("%s 's length mod 8 is not 0/n", pchFileName);
        // 若文件的長(zhǎng)度不是8的倍數(shù),說(shuō)明文件出了問(wèn)題,不能解密。
        decryptfile.Close();
        fileb4.Close();

        return false;
    }

    DWORD    dwRead;
    BYTE    bEncryptFileHead[8];
    UINT    uDecryptFileLen;
   
    dwRead = fileb4.Read(bEncryptFileHead, 8);        /* 讀取文件頭部的8個(gè)字節(jié) */
    if ( 8 == dwRead )

    {

        // 判斷頭部是否正確。

        if ( bEncryptFileHead[0] != 'I' )
        {
            decryptfile.Close();
            fileb4.Close();
            return false;
        }
        if ( bEncryptFileHead[1] != 'S' )
        {
            decryptfile.Close();
            fileb4.Close();
            return false;
        }
        if ( bEncryptFileHead[2] != 'D' )
        {
            decryptfile.Close();
            fileb4.Close();
            return false;
        }
        if ( bEncryptFileHead[3] != 'N' )
        {
            decryptfile.Close();
            fileb4.Close();
            return false;

        }

        //判斷文件的長(zhǎng)度是否改變。

        memcpy(&uDecryptFileLen, bEncryptFileHead + 4, 4 );
        if ( uDecryptFileLen + 8 > uFileLen || uDecryptFileLen + 16 < uFileLen )
        {
            decryptfile.Close();
            fileb4.Close();
            return false;
        }
    }
    else

    {

        //文件的頭部小于8個(gè)字節(jié),直接退出。

        decryptfile.Close();
        fileb4.Close();
        return false;
    }
   
    fileb4.Seek( uiOffset, CFile::current);        /* 定位到文件的當(dāng)前位置。
   
    BYTE    bBuffer[8];
    UINT    uPlainData[2];
    UINT    uCryptoData[2];
    UINT    uDecryptFileLenHasWrite = 0;
    do
    {
        memset(bBuffer, 0, 8);                        /* 分配內(nèi)存 */
        dwRead = fileb4.Read(bBuffer, 8);
        if ( dwRead > 0 && dwRead <= 8 )
        {
            memcpy(&uCryptoData[0], bBuffer    , 4);
            memcpy(&uCryptoData[1], bBuffer + 4, 4);
           
            decrypt(uCryptoData,uPlainData);        /* 解密雙字 */
           
            if ( uDecryptFileLen - uDecryptFileLenHasWrite >= 8 )
            {
                decryptfile.Write(&uPlainData[0], 4);    /* 寫(xiě)入文件。 */
                decryptfile.Write(&uPlainData[1], 4);
           
                uDecryptFileLenHasWrite += 8;
            }
            else if ( uDecryptFileLen - uDecryptFileLenHasWrite >= 4 )
            {
                decryptfile.Write(&uPlainData[0], 4);

                uDecryptFileLenHasWrite += 4;

                decryptfile.Write(&uPlainData[1], uDecryptFileLen - uDecryptFileLenHasWrite);
               
                uDecryptFileLenHasWrite = uDecryptFileLen;
            }
            else
            {
                decryptfile.Write(&uPlainData[0], uDecryptFileLen - uDecryptFileLenHasWrite);

                uDecryptFileLenHasWrite = uDecryptFileLen;
            }
        }
        //else if ( 8 > dwRead && 1 <= dwRead )
        //{
        //   
        //}       
    }
    while (dwRead > 0);            /* 循環(huán)條件 */

    // Close both files

    decryptfile.Close();
    fileb4.Close();

    return true;
}

//主函數(shù)
void main()
{   
    if (sizeof(UINT)!=4)
    {
        printf("RC5 error: UINT has %d bytes./n",sizeof(UINT));
    }
   
    UINT j;
    char *keystr = "0123456789ABCDEF";
    for (j=0; j < KEYSIZE; j++)
    {
        SetKey((unsigned char)keystr[j]);
    }
   
    /* Setup, encrypt, and decrypt */
    setup();

    ////////////////////////////////////////////////////////////////////////
    //
    EncryptFile("Test.dat");
    UINT    uMemLen;
    DecryptFile("Test.dat", 0, NULL, uMemLen);
   
    return 0;
}            
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
CFIle類的使用
Linux 考試試題
VC 編程ANSI環(huán)境下讀寫(xiě)Unicode文件和將CStdioFile類擴(kuò)展,讀取UNICODE文本文件
VS2010/MFC編程入門(mén)之四十五(MFC常用類:CFile文件操作類)
pca9555(i2c-gpio擴(kuò)展)應(yīng)用層測(cè)試代碼
窗口截圖(二)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服