- #include <stdio.h>
- #include <stdlib.h>
- #include <memory.h>
- #include <string.h>
- #include <time.h>
-
-
- typedef char int8 ;
- typedef unsigned char uint8 ;
- typedef short int16 ;
- typedef unsigned short uint16 ;
- typedef long int32 ;
- typedef unsigned long uint32 ;
-
- typedef struct tagTEACTX
- {
- uint8 buf[8] ;
- uint8 bufPre[8] ;
- const uint8 *pKey ;
- uint8 *pCrypt ;
- uint8 *pCryptPre ;
- } TEACTX, *LPTEACTX ;
-
- uint16 Host2NetShort(uint16 usHost)
- {
- const uint16 us = 0x1234 ;
- return ((uint8 *)&us)[0] == 0x12 ? usHost : ((usHost>>8) | (usHost<<8)) ;
- }
-
- uint16 Net2HostShort(uint16 usNet)
- {
- return Host2NetShort(usNet) ;
- }
-
- uint32 Host2NetLong(uint32 ulHost)
- {
- const uint16 us = 0x1234 ;
- return ((uint8 *)&us)[0] == 0x12 ? ulHost : (((ulHost>>8) & 0xFF00) |
- ((ulHost<<8) & 0xFF0000) | (ulHost<<24) | (ulHost>>24)) ;
- }
-
- uint32 Net2HostLong(uint32 ulHost)
- {
- return Host2NetLong(ulHost) ;
- }
-
- void EnCipher(const uint32 *const v, const uint32 *const k, uint32 *const w)
- {
- register uint32
- y = Host2NetLong(v[0]),
- z = Host2NetLong(v[1]),
- a = Host2NetLong(k[0]),
- b = Host2NetLong(k[1]),
- c = Host2NetLong(k[2]),
- d = Host2NetLong(k[3]),
- n = 0x10,
- sum = 0,
- delta = 0x9E3779B9;
-
- while (n-- > 0)
- {
- sum += delta;
- y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
- z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
- }
-
- w[0] = Net2HostLong(y);
- w[1] = Net2HostLong(z);
- }
-
- void DeCipher(const uint32 *const v, const uint32 *const k, uint32 *const w)
- {
- register uint32
- y = Host2NetLong(v[0]),
- z = Host2NetLong(v[1]),
- a = Host2NetLong(k[0]),
- b = Host2NetLong(k[1]),
- c = Host2NetLong(k[2]),
- d = Host2NetLong(k[3]),
- n = 0x10,
- sum = 0xE3779B90,
-
- delta = 0x9E3779B9;
-
-
- while (n-- > 0)
- {
- z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
- y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
- sum -= delta;
- }
-
- w[0] = Net2HostLong(y);
- w[1] = Net2HostLong(z);
- }
-
- uint32 Random(void)
- {
- return (uint32)rand();
-
- }
-
- static void EncryptEach8Bytes(TEACTX *pCtx)
- {
- #ifdef CRYPT_ONE_BYTE
- uint32 i ;
- uint8 *pPlain8, *pPlainPre8, *pCrypt8, *pCryptPre8 ;
- pPlain8 = (uint8 *)pCtx->buf ;
- pPlainPre8 = (uint8 *)pCtx->bufPre ;
- pCrypt8 = (uint8 *)pCtx->pCrypt ;
- pCryptPre8 = (uint8 *)pCtx->pCryptPre ;
-
- for(i=0; i<8; i++)
- pPlain8[i] ^= pCryptPre8[i] ;
-
- EnCipher((uint32 *)pPlain8, (uint32 *)pCtx->pKey, (uint32 *)pCrypt8) ;
-
- for(i=0; i<8; i++)
- pCrypt8[i] ^= pPlainPre8[i] ;
-
- for(i=0; i<8; i++)
- pPlainPre8[i] = pPlain8[i] ;
- #else
- uint32 *pPlain8, *pPlainPre8, *pCrypt8, *pCryptPre8 ;
- pPlain8 = (uint32 *)pCtx->buf ;
- pPlainPre8 = (uint32 *)pCtx->bufPre ;
- pCrypt8 = (uint32 *)pCtx->pCrypt ;
- pCryptPre8 = (uint32 *)pCtx->pCryptPre ;
- pPlain8[0] ^= pCryptPre8[0] ;
- pPlain8[1] ^= pCryptPre8[1] ;
- EnCipher(pPlain8, (const uint32 *)pCtx->pKey, pCrypt8) ;
- pCrypt8[0] ^= pPlainPre8[0] ;
- pCrypt8[1] ^= pPlainPre8[1] ;
- pPlainPre8[0] = pPlain8[0] ;
- pPlainPre8[1] = pPlain8[1] ;
- #endif
- pCtx->pCryptPre = pCtx->pCrypt ;
- pCtx->pCrypt += 8 ;
- }
-
- uint32 Encrypt(TEACTX *pCtx, const uint8 *pPlain, uint32 ulPlainLen,
- const uint8 *pKey, uint8 *pOut, uint32 *pOutLen)
- {
- uint32 ulPos, ulPadding, ulOut ;
- const uint8 *p ;
- if(pPlain == NULL || ulPlainLen == 0 || pOutLen == NULL)
- return 0 ;
-
-
-
- ulPos = (8 - ((ulPlainLen + 10) & 0x07)) & 0x07 ;
-
- ulOut = 1 + ulPos + 2 + ulPlainLen + 7 ;
- if(*pOutLen < ulOut)
- {
- *pOutLen = ulOut ;
- return 0 ;
- }
- *pOutLen = ulOut ;
- memset(pCtx, 0, sizeof(TEACTX)) ;
- pCtx->pCrypt = pOut ;
- pCtx->pCryptPre = pCtx->bufPre ;
- pCtx->pKey = pKey ;
-
- pCtx->buf[0] = (uint8)((Random() & 0xF8) | ulPos) ;
-
-
- memset(pCtx->buf+1, (uint8)Random(), ulPos++) ;
-
- for(ulPadding=0; ulPadding<2; ulPadding++)
- {
- if(ulPos == 8)
- {
- EncryptEach8Bytes(pCtx) ;
- ulPos = 0 ;
- }
- pCtx->buf[ulPos++] = (uint8)Random() ;
- }
- p = pPlain ;
- while(ulPlainLen > 0)
- {
- if(ulPos == 8)
- {
- EncryptEach8Bytes(pCtx) ;
- ulPos = 0 ;
- }
- pCtx->buf[ulPos++] = *(p++) ;
- ulPlainLen-- ;
- }
-
- for(ulPadding=0; ulPadding<7; ulPadding++)
- pCtx->buf[ulPos++] = 0x00 ;
-
- EncryptEach8Bytes(pCtx) ;
- return ulOut ;
- }
-
- static void DecryptEach8Bytes(TEACTX *pCtx)
- {
- #ifdef CRYPT_ONE_BYTE
- uint32 i ;
- uint8 bufTemp[8] ;
- uint8 *pBuf8, *pBufPre8, *pCrypt8, *pCryptPre8 ;
- pBuf8 = (uint8 *)pCtx->buf ;
- pBufPre8 = (uint8 *)pCtx->bufPre ;
- pCrypt8 = (uint8 *)pCtx->pCrypt ;
- pCryptPre8 = (uint8 *)pCtx->pCryptPre ;
-
- for(i=0; i<8; i++)
- bufTemp[i] = pCrypt8[i] ^ pBufPre8[i] ;
-
- DeCipher((uint32 *)bufTemp, (uint32 *)pCtx->pKey, (uint32 *)pBufPre8) ;
-
- for(i=0; i<8; i++)
- pBuf8[i] = pBufPre8[i] ^ pCryptPre8[i] ;
- #else
- uint32 bufTemp[2] ;
- uint32 *pBuf8, *pBufPre8, *pCrypt8, *pCryptPre8 ;
- pBuf8 = (uint32 *)pCtx->buf ;
- pBufPre8 = (uint32 *)pCtx->bufPre ;
- pCrypt8 = (uint32 *)pCtx->pCrypt ;
- pCryptPre8 = (uint32 *)pCtx->pCryptPre ;
- bufTemp[0] = pCrypt8[0] ^ pBufPre8[0] ;
- bufTemp[1] = pCrypt8[1] ^ pBufPre8[1] ;
- DeCipher(bufTemp, (const uint32 *)pCtx->pKey, pBufPre8) ;
- pBuf8[0] = pBufPre8[0] ^ pCryptPre8[0] ;
- pBuf8[1] = pBufPre8[1] ^ pCryptPre8[1] ;
- #endif
- pCtx->pCryptPre = pCtx->pCrypt ;
- pCtx->pCrypt += 8 ;
- }
-
- uint32 Decrypt(TEACTX *pCtx, const uint8 *pCipher, uint32 ulCipherLen,
- const uint8 *pKey, uint8 *pOut, uint32 *pOutLen)
- {
- uint32 ulPos, ulPadding, ulOut, ul ;
-
- if(pCipher == NULL || pOutLen == NULL ||
- ulCipherLen < 16 || (ulCipherLen & 0x07) != 0)
- return 0 ;
-
- DeCipher((const uint32 *)pCipher, (const uint32 *)pKey, (uint32 *)pCtx->bufPre) ;
- for(ul=0; ul<8; ul++)
- pCtx->buf[ul] = pCtx->bufPre[ul] ;
- ulPos = pCtx->buf[0] & 0x07 ;
- if(ulPos > 1)
- {
- for(ulOut=2; ulOut<=ulPos; ulOut++)
- {
- if(pCtx->buf[1] != pCtx->buf[ulOut])
- {
- *pOutLen = 0 ;
- return 0 ;
- }
- }
- }
- ulOut = ulCipherLen - ulPos - 10 ;
- if(ulPos + 10 > ulCipherLen || *pOutLen < ulOut)
- return 0 ;
- pCtx->pCryptPre = (uint8 *)pCipher ;
- pCtx->pCrypt = (uint8 *)pCipher + 8 ;
- ulPos++ ;
- for(ulPadding=0; ulPadding<2; ulPadding++)
- {
- if(ulPos == 8)
- {
- DecryptEach8Bytes(pCtx) ;
- ulPos = 0 ;
- }
- ulPos++ ;
- }
-
- for(ul=0; ul<ulOut; ul++)
- {
- if(ulPos == 8)
- {
- DecryptEach8Bytes(pCtx) ;
- ulPos = 0 ;
- }
- pOut[ul] = pCtx->buf[ulPos] ;
- ulPos++ ;
- }
-
- for(ulPadding=0; ulPadding<7; ulPadding++)
- {
- if(ulPos < 8)
- {
- if(pCtx->buf[ulPos] != 0x00)
- {
- *pOutLen = 0 ;
- return 0 ;
- }
- }
- ulPos++ ;
- }
- *pOutLen = ulOut ;
- return 1 ;
- }
-
- void PrintBuffer(const uint8 *buf, uint32 ulLen)
- {
- uint32 i ;
- for(i=0; i<ulLen; i++)
- {
- printf("%.2X ", buf[i]) ;
- if((i+1) % 16 == 0)
- putchar(‘\n‘) ;
- }
- if((ulLen & 0x0F) != 0)
- putchar(‘\n‘) ;
- }
-
- int main(void)
- {
- const char *pPK[][2] =
- {
-
- {"tea", "123456789abcdef"},
- {"tea", "123456789abcdef"},
- {"123456", "password1234567"},
- {"AABBCCD", "aabbccddeeffggh"},
- {"Hello World 你好世界!", "aabbccddeeffggh"}
- } ;
- TEACTX ctx ;
- uint8 bufEnc[512], bufDec[512] ;
- uint32 ulEnc, ulDec, ulRet ;
- int i ;
- for(i=0; i<sizeof(pPK)/sizeof(pPK[0]); i++)
- {
- printf("明文:%s\n密钥:%s\n", pPK[i][0], pPK[i][1]) ;
- ulEnc = sizeof(bufEnc) ;
- Encrypt(&ctx, (const uint8 *)pPK[i][0], strlen(pPK[i][0])+1,
- (const uint8 *)pPK[i][1], (uint8 *)bufEnc, &ulEnc) ;
- printf("密文:\n") ;
- PrintBuffer(bufEnc, ulEnc) ;
- ulDec = sizeof(bufDec) ;
- ulRet = Decrypt(&ctx, bufEnc, ulEnc, (const uint8 *)pPK[i][1],
- (uint8 *)bufDec, &ulDec) ;
- if(ulRet != 0)
- printf("解密后明文:%s\n", bufDec) ;
- else
- printf("解密失败!\n") ;
- putchar(‘\n‘) ;
- }
- return 0 ;
- }
QQ通讯协议里的TEA加解密算法
原文:http://www.cnblogs.com/zaiiiPan/p/4430039.html