Files
core/ASCOfficePDFWriter/Encrypt.h

523 lines
18 KiB
C

//----------------------------------------------------------------------------------------
//
// The code implements MD5 message-digest algorithm.
// To compute the message digest of a chunk of bytes, declare an
// MD5Context structure, pass it to MD5Init, call MD5Update as
// needed on buffers full of bytes, and then call MD5Final, which
// will fill a supplied 16-byte array with the digest.
//
//----------------------------------------------------------------------------------------
#ifndef _ENCRYPT_H
#define _ENCRYPT_H
#include <time.h>
#include "MemoryManager.h"
#include "Consts.h"
#include "Utils.h"
#include "Objects.h"
//#include "MetaData.h"
static const BYTE c_sPaddingString[] =
{
0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
};
//-------- EncryptDict -------------------------------------------------------------------
#define ID_LEN 16
#define PASSWD_LEN 32
#define ENCRYPT_KEY_MAX 16
#define MD5_KEY_LEN 16
#define PERMISSION_PAD 0xFFFFFFC0
#define ARC4_BUF_SIZE 256
typedef struct TMD5Context
{
unsigned int anBuf[4];
unsigned int anBits[2];
BYTE anIn[64];
} MD5Context;
typedef struct TARC4ContextRec
{
BYTE nIndex1;
BYTE nIndex2;
BYTE anState[ARC4_BUF_SIZE];
} ARC4ContextRec;
typedef struct TEncryptRec *Encrypt;
typedef struct TEncryptRec
{
EncryptMode eMode;
// nKeyLen äîëæíî áûòü êðàòíî 8, è ëåæàòü â îòðåçêå îò 40 è äî 128
unsigned int nKeyLen;
// Owner-Password (íå øèôðîâàííûé)
BYTE anOwnerPassword[PASSWD_LEN];
// User-Password (íå øèôðîâàííûé)
BYTE anUserPassword[PASSWD_LEN];
// Owner-Password (øèôðîâàííûé)
BYTE anOwnerKey[PASSWD_LEN];
// User-Password (øèôðîâàííûé)
BYTE anUserKey[PASSWD_LEN];
int nPermission;
BYTE anEncryptID[ID_LEN];
BYTE anEncryptionKey[MD5_KEY_LEN + 5];
BYTE anMD5EncryptionKey[MD5_KEY_LEN];
ARC4ContextRec oARC4Context;
} EncryptRec;
//-------- MD5 àëãîðèòì - Âñïîìîãàòåëüíûå ôóíêöèè ----------------------------------------
// Îïòèìèçàöèîííûå ôóíêöèè.
#define OptFunc1(x, y, z) (z ^ (x & (y ^ z)))
#define OptFunc2(x, y, z) OptFunc1(z, x, y)
#define OptFunc3(x, y, z) (x ^ y ^ z)
#define OptFunc4(x, y, z) (y ^ (x | ~z))
// Îñíîâíîé øàã â àëãîðèòìå MD5.
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
// The core of the MD5 algorithm, this alters an existing MD5 hash to
// reflect the addition of 16 longwords of new data. MD5Update blocks
// the data and converts bytes into longwords for this routine.
static void MD5ByteReverse(BYTE *pBuf, unsigned int nLongs)
{
unsigned int nTemp = 0;
do
{
nTemp = (unsigned int) ((unsigned int) pBuf[3] << 8 | pBuf[2]) << 16 | ((unsigned int) pBuf[1] << 8 | pBuf[0]);
*(unsigned int *) pBuf = nTemp;
pBuf += 4;
}
while (--nLongs);
}
static void MD5Transform (unsigned int anBuf[4], const unsigned int anIn[16])
{
register unsigned int a, b, c, d;
a = anBuf[0];
b = anBuf[1];
c = anBuf[2];
d = anBuf[3];
MD5STEP( OptFunc1, a, b, c, d, anIn[0] + 0xd76aa478, 7);
MD5STEP( OptFunc1, d, a, b, c, anIn[1] + 0xe8c7b756, 12);
MD5STEP( OptFunc1, c, d, a, b, anIn[2] + 0x242070db, 17);
MD5STEP( OptFunc1, b, c, d, a, anIn[3] + 0xc1bdceee, 22);
MD5STEP( OptFunc1, a, b, c, d, anIn[4] + 0xf57c0faf, 7);
MD5STEP( OptFunc1, d, a, b, c, anIn[5] + 0x4787c62a, 12);
MD5STEP( OptFunc1, c, d, a, b, anIn[6] + 0xa8304613, 17);
MD5STEP( OptFunc1, b, c, d, a, anIn[7] + 0xfd469501, 22);
MD5STEP( OptFunc1, a, b, c, d, anIn[8] + 0x698098d8, 7);
MD5STEP( OptFunc1, d, a, b, c, anIn[9] + 0x8b44f7af, 12);
MD5STEP( OptFunc1, c, d, a, b, anIn[10] + 0xffff5bb1, 17);
MD5STEP( OptFunc1, b, c, d, a, anIn[11] + 0x895cd7be, 22);
MD5STEP( OptFunc1, a, b, c, d, anIn[12] + 0x6b901122, 7);
MD5STEP( OptFunc1, d, a, b, c, anIn[13] + 0xfd987193, 12);
MD5STEP( OptFunc1, c, d, a, b, anIn[14] + 0xa679438e, 17);
MD5STEP( OptFunc1, b, c, d, a, anIn[15] + 0x49b40821, 22);
MD5STEP( OptFunc2, a, b, c, d, anIn[1] + 0xf61e2562, 5);
MD5STEP( OptFunc2, d, a, b, c, anIn[6] + 0xc040b340, 9);
MD5STEP( OptFunc2, c, d, a, b, anIn[11] + 0x265e5a51, 14);
MD5STEP( OptFunc2, b, c, d, a, anIn[0] + 0xe9b6c7aa, 20);
MD5STEP( OptFunc2, a, b, c, d, anIn[5] + 0xd62f105d, 5);
MD5STEP( OptFunc2, d, a, b, c, anIn[10] + 0x02441453, 9);
MD5STEP( OptFunc2, c, d, a, b, anIn[15] + 0xd8a1e681, 14);
MD5STEP( OptFunc2, b, c, d, a, anIn[4] + 0xe7d3fbc8, 20);
MD5STEP( OptFunc2, a, b, c, d, anIn[9] + 0x21e1cde6, 5);
MD5STEP( OptFunc2, d, a, b, c, anIn[14] + 0xc33707d6, 9);
MD5STEP( OptFunc2, c, d, a, b, anIn[3] + 0xf4d50d87, 14);
MD5STEP( OptFunc2, b, c, d, a, anIn[8] + 0x455a14ed, 20);
MD5STEP( OptFunc2, a, b, c, d, anIn[13] + 0xa9e3e905, 5);
MD5STEP( OptFunc2, d, a, b, c, anIn[2] + 0xfcefa3f8, 9);
MD5STEP( OptFunc2, c, d, a, b, anIn[7] + 0x676f02d9, 14);
MD5STEP( OptFunc2, b, c, d, a, anIn[12] + 0x8d2a4c8a, 20);
MD5STEP( OptFunc3, a, b, c, d, anIn[5] + 0xfffa3942, 4);
MD5STEP( OptFunc3, d, a, b, c, anIn[8] + 0x8771f681, 11);
MD5STEP( OptFunc3, c, d, a, b, anIn[11] + 0x6d9d6122, 16);
MD5STEP( OptFunc3, b, c, d, a, anIn[14] + 0xfde5380c, 23);
MD5STEP( OptFunc3, a, b, c, d, anIn[1] + 0xa4beea44, 4);
MD5STEP( OptFunc3, d, a, b, c, anIn[4] + 0x4bdecfa9, 11);
MD5STEP( OptFunc3, c, d, a, b, anIn[7] + 0xf6bb4b60, 16);
MD5STEP( OptFunc3, b, c, d, a, anIn[10] + 0xbebfbc70, 23);
MD5STEP( OptFunc3, a, b, c, d, anIn[13] + 0x289b7ec6, 4);
MD5STEP( OptFunc3, d, a, b, c, anIn[0] + 0xeaa127fa, 11);
MD5STEP( OptFunc3, c, d, a, b, anIn[3] + 0xd4ef3085, 16);
MD5STEP( OptFunc3, b, c, d, a, anIn[6] + 0x04881d05, 23);
MD5STEP( OptFunc3, a, b, c, d, anIn[9] + 0xd9d4d039, 4);
MD5STEP( OptFunc3, d, a, b, c, anIn[12] + 0xe6db99e5, 11);
MD5STEP( OptFunc3, c, d, a, b, anIn[15] + 0x1fa27cf8, 16);
MD5STEP( OptFunc3, b, c, d, a, anIn[2] + 0xc4ac5665, 23);
MD5STEP( OptFunc4, a, b, c, d, anIn[0] + 0xf4292244, 6);
MD5STEP( OptFunc4, d, a, b, c, anIn[7] + 0x432aff97, 10);
MD5STEP( OptFunc4, c, d, a, b, anIn[14] + 0xab9423a7, 15);
MD5STEP( OptFunc4, b, c, d, a, anIn[5] + 0xfc93a039, 21);
MD5STEP( OptFunc4, a, b, c, d, anIn[12] + 0x655b59c3, 6);
MD5STEP( OptFunc4, d, a, b, c, anIn[3] + 0x8f0ccc92, 10);
MD5STEP( OptFunc4, c, d, a, b, anIn[10] + 0xffeff47d, 15);
MD5STEP( OptFunc4, b, c, d, a, anIn[1] + 0x85845dd1, 21);
MD5STEP( OptFunc4, a, b, c, d, anIn[8] + 0x6fa87e4f, 6);
MD5STEP( OptFunc4, d, a, b, c, anIn[15] + 0xfe2ce6e0, 10);
MD5STEP( OptFunc4, c, d, a, b, anIn[6] + 0xa3014314, 15);
MD5STEP( OptFunc4, b, c, d, a, anIn[13] + 0x4e0811a1, 21);
MD5STEP( OptFunc4, a, b, c, d, anIn[4] + 0xf7537e82, 6);
MD5STEP( OptFunc4, d, a, b, c, anIn[11] + 0xbd3af235, 10);
MD5STEP( OptFunc4, c, d, a, b, anIn[2] + 0x2ad7d2bb, 15);
MD5STEP( OptFunc4, b, c, d, a, anIn[9] + 0xeb86d391, 21);
anBuf[0] += a;
anBuf[1] += b;
anBuf[2] += c;
anBuf[3] += d;
}
//-------- MD5 àëãîðèòì - Îñíîâíûå ôóíêöèè -----------------------------------------------
void MD5Init (MD5Context *pContext)
{
pContext->anBuf[0] = 0x67452301;
pContext->anBuf[1] = 0xefcdab89;
pContext->anBuf[2] = 0x98badcfe;
pContext->anBuf[3] = 0x10325476;
pContext->anBits[0] = 0;
pContext->anBits[1] = 0;
}
void MD5Update(MD5Context *pContext, const BYTE *pBuf, unsigned int nLen)
{
// Update bitcount
unsigned int nTempBit = pContext->anBits[0];
if ( ( pContext->anBits[0] = nTempBit + ((unsigned int) nLen << 3) ) < nTempBit )
pContext->anBits[1]++; // Carry from low to high
pContext->anBits[1] += nLen >> 29;
nTempBit = (nTempBit >> 3) & 0x3f; // Bytes already in shsInfo->data
// Handle any leading odd-sized chunks
if ( nTempBit )
{
BYTE *pTemp = (BYTE *) pContext->anIn + nTempBit;
nTempBit = 64 - nTempBit;
if ( nLen < nTempBit )
{
UtilsMemCpy( pTemp, pBuf, nLen);
return;
}
UtilsMemCpy( pTemp, pBuf, nTempBit);
MD5ByteReverse( pContext->anIn, 16);
MD5Transform( pContext->anBuf, (unsigned int *) pContext->anIn);
pBuf += nTempBit;
nLen -= nTempBit;
}
// Process data in 64-byte chunks
while ( nLen >= 64 )
{
UtilsMemCpy( pContext->anIn, pBuf, 64);
MD5ByteReverse( pContext->anIn, 16);
MD5Transform( pContext->anBuf, (unsigned int *) pContext->anIn);
pBuf += 64;
nLen -= 64;
}
// Handle any remaining bytes of data.
UtilsMemCpy( pContext->anIn, pBuf, nLen);
}
// Final wrapup - pad to 64-byte boundary with the bit pattern
// 1 0* (64-bit count of bits processed, MSB-first)
void MD5Final (BYTE anDigest[16], MD5Context *pContext)
{
// Âû÷èñëÿåì êîëè÷åñòâî áàéòîâ ïî ìîäóëþ 64
unsigned int nCount = ( pContext->anBits[0] >> 3 ) & 0x3F;
// Óñòàíàâëèâàåì ïåðâûé ñèìâîë â äîïîëíèòåëüíîé ñòðîêå(padding) çíà÷åíèåì 0x80.
// Ýòî áåçîïàñíî, ïîñêîëüêó âñåãäà êàê ìèíèìóì îäèí áàéò ñâîáîäåí.
BYTE *pTemp = pContext->anIn + nCount;
*pTemp++ = 0x80;
// Bytes of padding needed to make 64 bytes
nCount = 64 - 1 - nCount;
// Pad out to 56 mod 64
if ( nCount < 8 )
{
// Two lots of padding: Pad the first block to 64 bytes
UtilsMemSet( pTemp, 0, nCount);
MD5ByteReverse( pContext->anIn, 16);
MD5Transform( pContext->anBuf, (unsigned int *) pContext->anIn);
// Now fill the next block with 56 bytes
UtilsMemSet( pContext->anIn, 0, 56);
}
else
{
// Pad block to 56 bytes
UtilsMemSet( pTemp, 0, nCount - 8);
}
MD5ByteReverse( pContext->anIn, 14);
// Append length in bits and transform
((unsigned int *) pContext->anIn)[14] = pContext->anBits[0];
((unsigned int *) pContext->anIn)[15] = pContext->anBits[1];
MD5Transform( pContext->anBuf, (unsigned int *) pContext->anIn);
MD5ByteReverse( (BYTE *)pContext->anBuf, 4);
UtilsMemCpy( (BYTE *)anDigest, (BYTE *)pContext->anBuf, 16);
UtilsMemSet( (BYTE *)pContext, 0, sizeof (pContext)); // In case it's sensitive
}
//-------- Encrypt - Âñïîìîãàòåëüíûå ôóíêöèè ---------------------------------------------
void ARC4Init (ARC4ContextRec *pContext, const BYTE *pKey, unsigned int nKeyLen)
{
BYTE pTempArray[ARC4_BUF_SIZE];
unsigned int nJ = 0;
for ( unsigned int nIndex = 0; nIndex < ARC4_BUF_SIZE; nIndex++)
pContext->anState[nIndex] = nIndex;
for ( unsigned int nIndex = 0; nIndex < ARC4_BUF_SIZE; nIndex++)
pTempArray[nIndex] = pKey[nIndex % nKeyLen];
for ( unsigned int nIndex = 0; nIndex < ARC4_BUF_SIZE; nIndex++)
{
nJ = ( nJ + pContext->anState[nIndex] + pTempArray[nIndex] ) % ARC4_BUF_SIZE;
BYTE nTemp = pContext->anState[nIndex];
pContext->anState[nIndex] = pContext->anState[nJ];
pContext->anState[nJ] = nTemp;
}
pContext->nIndex1 = 0;
pContext->nIndex2 = 0;
}
void ARC4CryptBuf (ARC4ContextRec *pContext, const BYTE *pIn, BYTE *pOut, unsigned int nLen )
{
for ( unsigned int nIndex = 0; nIndex < nLen; nIndex++)
{
pContext->nIndex1 = ( pContext->nIndex1 + 1 ) % 256;
pContext->nIndex2 = ( pContext->nIndex2 + pContext->anState[ pContext->nIndex1 ] ) % 256;
BYTE nTemp = pContext->anState[ pContext->nIndex1 ];
pContext->anState[ pContext->nIndex1 ] = pContext->anState[ pContext->nIndex2 ];
pContext->anState[ pContext->nIndex2 ] = nTemp;
unsigned int nTempIndex = ( pContext->anState[ pContext->nIndex1 ] + pContext->anState[ pContext->nIndex2 ] ) % 256;
BYTE nKoef = pContext->anState[nTempIndex];
pOut[nIndex] = pIn[nIndex] ^ nKoef;
}
}
//-------- Encrypt - Îñíîâíûå ôóíêöèè ----------------------------------------------------
void PadOrTrancatePassword (const char *sPassword, BYTE *pNewPassword)
{
unsigned int nLen = UtilsStrLen( sPassword, PASSWD_LEN + 1);
UtilsMemSet( pNewPassword, 0x00, PASSWD_LEN);
if ( nLen >= PASSWD_LEN )
UtilsMemCpy( pNewPassword, (BYTE*)sPassword, PASSWD_LEN);
else
{
if ( nLen > 0 )
UtilsMemCpy( pNewPassword, (BYTE*)sPassword, nLen);
UtilsMemCpy( pNewPassword + nLen, c_sPaddingString, PASSWD_LEN - nLen);
}
}
void EncryptInit (Encrypt pAttr)
{
UtilsMemSet( pAttr, 0, sizeof(EncryptRec) );
pAttr->eMode = EncryptR2;
pAttr->nKeyLen = 5;
UtilsMemCpy( pAttr->anOwnerPassword, c_sPaddingString, PASSWD_LEN);
UtilsMemCpy( pAttr->anUserPassword, c_sPaddingString, PASSWD_LEN);
pAttr->nPermission = ENABLE_PRINT | ENABLE_EDIT_ALL | ENABLE_COPY | ENABLE_EDIT | PERMISSION_PAD;
}
void EncryptCreateUserKey (Encrypt pAttr)
{
ARC4ContextRec oContext;
// Algorithm 3.4/5 step1
// Algorithm 3.4 step2
ARC4Init( &oContext, pAttr->anEncryptionKey, pAttr->nKeyLen);
ARC4CryptBuf( &oContext, c_sPaddingString, pAttr->anUserKey, PASSWD_LEN);
if ( EncryptR3 == pAttr->eMode )
{
MD5Context oMD5Context;
BYTE anDigest[MD5_KEY_LEN];
BYTE anDigest2[MD5_KEY_LEN];
// Algorithm 3.5 step2 (same as Algorithm3.2 step2)
MD5Init( &oMD5Context);
MD5Update( &oMD5Context, c_sPaddingString, PASSWD_LEN);
// Algorithm 3.5 step3
MD5Update( &oMD5Context, pAttr->anEncryptID, ID_LEN);
MD5Final( anDigest, &oMD5Context);
// Algorithm 3.5 step4
ARC4Init( &oContext, pAttr->anEncryptionKey, pAttr->nKeyLen);
ARC4CryptBuf( &oContext, anDigest, anDigest2, MD5_KEY_LEN);
// Algorithm 3.5 step5 */
for ( unsigned int nI = 1; nI <= 19; nI++ )
{
BYTE pNewKey[MD5_KEY_LEN];
for ( unsigned int nJ = 0; nJ < pAttr->nKeyLen; nJ++ )
pNewKey[nJ] = pAttr->anEncryptionKey[nJ] ^ nI;
UtilsMemCpy( anDigest, anDigest2, MD5_KEY_LEN);
ARC4Init( &oContext, pNewKey, pAttr->nKeyLen );
ARC4CryptBuf( &oContext, anDigest, anDigest2, MD5_KEY_LEN );
}
// use the result of Algorithm 3.4 as 'arbitrary padding'
UtilsMemSet( pAttr->anUserKey, 0, PASSWD_LEN);
UtilsMemCpy( pAttr->anUserKey, anDigest2, MD5_KEY_LEN);
}
}
void EncryptCreateOwnerKey (Encrypt pAttr)
{
ARC4ContextRec oARC4Context;
MD5Context oMD5Context;
BYTE anDigest[MD5_KEY_LEN];
BYTE anTempPassword[PASSWD_LEN];
// create md5-digest using the value of anOwnerPassword
// Algorithm 3.3 step 2
MD5Init( &oMD5Context);
MD5Update( &oMD5Context, pAttr->anOwnerPassword, PASSWD_LEN);
MD5Final( anDigest, &oMD5Context);
// Algorithm 3.3 step 3 (Revision 3 only)
if ( EncryptR3 == pAttr->eMode )
{
for (unsigned int nIndex = 0; nIndex < 50; nIndex++)
{
MD5Init( &oMD5Context);
//MD5Update( &oMD5Context, anDigest, MD5_KEY_LEN);
MD5Update ( &oMD5Context, anDigest, pAttr->nKeyLen );
MD5Final( anDigest, &oMD5Context);
}
}
// Algorithm 3.3 step 4
ARC4Init( &oARC4Context, anDigest, pAttr->nKeyLen );
// Algorithm 3.3 step 6
ARC4CryptBuf( &oARC4Context, pAttr->anUserPassword, anTempPassword, PASSWD_LEN);
// Algorithm 3.3 step 7
if ( EncryptR3 == pAttr->eMode )
{
BYTE anTempPassword2[PASSWD_LEN];
for (unsigned int i = 1; i <= 19; i++)
{
BYTE anNewKey[MD5_KEY_LEN];
for (unsigned int j = 0; j < pAttr->nKeyLen; j++)
anNewKey[j] = anDigest[j] ^ i;
UtilsMemCpy( anTempPassword2, anTempPassword, PASSWD_LEN);
ARC4Init( &oARC4Context, anNewKey, pAttr->nKeyLen);
ARC4CryptBuf( &oARC4Context, anTempPassword2, anTempPassword, PASSWD_LEN);
}
}
// Algorithm 3.3 step 8
UtilsMemCpy( pAttr->anOwnerKey, anTempPassword, PASSWD_LEN);
}
void EncryptCreateEncryptionKey (Encrypt pAttr)
{
MD5Context oMD5Context;
BYTE anTempFlag[4];
// Algorithm3.2 step2
MD5Init( &oMD5Context);
MD5Update( &oMD5Context, pAttr->anUserPassword, PASSWD_LEN);
// Algorithm3.2 step3
MD5Update( &oMD5Context, pAttr->anOwnerKey, PASSWD_LEN);
// Algorithm3.2 step4
anTempFlag[0] = pAttr->nPermission;
anTempFlag[1] = (pAttr->nPermission >> 8);
anTempFlag[2] = (pAttr->nPermission >> 16);
anTempFlag[3] = (pAttr->nPermission >> 24);
MD5Update( &oMD5Context, anTempFlag, 4);
// Algorithm3.2 step5
MD5Update(&oMD5Context, pAttr->anEncryptID, ID_LEN);
MD5Final( pAttr->anEncryptionKey, &oMD5Context);
// Algorithm 3.2 step6 (Revision 3 only)
if ( EncryptR3 == pAttr->eMode )
{
for ( unsigned int nIndex = 0; nIndex < 50; nIndex++)
{
MD5Init( &oMD5Context);
MD5Update( &oMD5Context, pAttr->anEncryptionKey, pAttr->nKeyLen);
MD5Final( pAttr->anEncryptionKey, &oMD5Context);
}
}
}
void EncryptInitKey (Encrypt pAttr, unsigned int nObjectId, unsigned short nGenNo )
{
MD5Context oContext;
pAttr->anEncryptionKey[pAttr->nKeyLen] = nObjectId;
pAttr->anEncryptionKey[pAttr->nKeyLen + 1] = (nObjectId >> 8);
pAttr->anEncryptionKey[pAttr->nKeyLen + 2] = (nObjectId >> 16);
pAttr->anEncryptionKey[pAttr->nKeyLen + 3] = nGenNo;
pAttr->anEncryptionKey[pAttr->nKeyLen + 4] = (nGenNo >> 8);
MD5Init( &oContext);
MD5Update( &oContext, pAttr->anEncryptionKey, pAttr->nKeyLen + 5);
MD5Final( pAttr->anMD5EncryptionKey, &oContext);
unsigned int nKeyLen = ( pAttr->nKeyLen + 5 > ENCRYPT_KEY_MAX) ? ENCRYPT_KEY_MAX : pAttr->nKeyLen + 5;
ARC4Init( &pAttr->oARC4Context, pAttr->anMD5EncryptionKey, nKeyLen );
}
void EncryptReset (Encrypt pAttr)
{
unsigned int nKeyLen = ( pAttr->nKeyLen + 5 > ENCRYPT_KEY_MAX) ? ENCRYPT_KEY_MAX : pAttr->nKeyLen + 5;
ARC4Init( &pAttr->oARC4Context, pAttr->anMD5EncryptionKey, nKeyLen );
}
void EncryptCryptBuf (Encrypt pAttr, const BYTE *pSrc, BYTE *pDst, unsigned int nLen)
{
ARC4CryptBuf( &pAttr->oARC4Context, pSrc, pDst, nLen);
}
#endif /* _ENCRYPT_H */