/********************************************************************
Created: 27/3/2004, 21:37
File name: D:\Projects\Exile\Exile\security.cpp
File path: D:\Projects\Exile\Exile
File base: security
File ext: cpp
Author: Gogolev Anton
*********************************************************************/
#include "StdAfx.h"
#include "../MD5/MD5.h"
#include "Security.h"
void GeneratePrivateKey(CString &rstrUserName, CString &rstrPassword, int nKeyLength, KEYINFO &rKeyInfo)
{
rKeyInfo.pbKey = new BYTE[nKeyLength / 8];
rKeyInfo.nKeySize = nKeyLength;
MD5HASH hs[8]; // This is maximum as 1024 bit key is the longest available
size_t sUserName = rstrUserName.GetLength() * sizeof(TCHAR);
size_t sPassword = rstrPassword.GetLength() * sizeof(TCHAR);
BYTE *pBuffer = 0; // Buffer for holding data which is to be hashed
for(int n = 0; n < nKeyLength / 8 / 16; ++n)
{
// In each round we use User Name, Password and all previous
// hashes to get a new hash.
// Md5GetExpandedBufferSize() calculates the size of a buffer we'll need.
size_t sBuffer = ::Md5GetExpandedBufferSize(sUserName + sPassword + sizeof(MD5HASH) * n);
pBuffer = new BYTE[sBuffer];
// This is always like that
memmove(pBuffer, rstrUserName.LockBuffer(), sUserName);
memmove(pBuffer + sUserName, rstrPassword.LockBuffer(), sPassword);
// And now append previous hashes
for(int i = 0; i < n; ++i)
{
memmove(pBuffer + sUserName + sPassword + sizeof(MD5HASH) * i, (void *)&hs[i], sizeof(MD5HASH));
} // for
// Now hash what we have
size_t sSgSize = sUserName + sPassword + sizeof(MD5HASH) * n;
::Md5ExpandData(pBuffer, sSgSize, sBuffer);
::Md5HashData((MD5_WORD *)pBuffer, sBuffer / 64, hs[n]);
// When we have this loop for the first time, hs[0]
// equals to "User Name + Password" hash which is exactly what
// we need
if(0 == n)
rKeyInfo.hsPassword = hs[0];
FreeBuffer(pBuffer, sBuffer);
} // for
// Now moving to buffer we allocated...
memmove(rKeyInfo.pbKey, hs, nKeyLength / 8);
// ...and cleaning up
CleanBuffer(hs, sizeof(MD5HASH) * 8);
}
void GeneratePasswordHash(CString &rstrUserName, CString &rstrPassword, MD5HASH &rhsPassword)
{
size_t sUserName = rstrUserName.GetLength() * sizeof(TCHAR);
size_t sPassword = rstrPassword.GetLength() * sizeof(TCHAR);
BYTE *pBuffer = 0; // Buffer for holding data which is to be hashed
size_t sBuffer = ::Md5GetExpandedBufferSize(sUserName + sPassword);
pBuffer = new BYTE[sBuffer];
memmove(pBuffer, rstrUserName.LockBuffer(), sUserName);
memmove(pBuffer + sUserName, rstrPassword.LockBuffer(), sPassword);
::Md5ExpandData(pBuffer, sUserName + sPassword, sBuffer);
::Md5HashData((MD5_WORD *)pBuffer, sBuffer / 64, rhsPassword);
FreeBuffer(pBuffer, sUserName + sPassword);
}
void GeneratePassword(TCHAR *pszCharSet, int nCharSetLength, DWORD *pdwData,
int nDataLength, int nPasswordLength, TCHAR *pszPassword)
{
if((0 == pszCharSet) || (0 == nCharSetLength) || (0 == pdwData) || (0 == nDataLength) ||
(0 == nPasswordLength) || (0 == pszPassword))
return;
// First, hash ;) data we have and a character set
size_t sData, sBuffer;
sData = sizeof(TCHAR) * nCharSetLength;
sBuffer = ::Md5GetExpandedBufferSize(sData);
// Character set
BYTE *pBuffer = new BYTE[sBuffer];
MD5HASH hsCharset, hsData;
memmove(pBuffer, (void *)pszCharSet, sData);
::Md5ExpandData(pBuffer, sData, sBuffer);
::Md5HashData((MD5_WORD *)pBuffer, sBuffer / 64, hsCharset);
FreeBuffer(pBuffer, sBuffer);
// Input data
sData = sizeof(DWORD) * nDataLength;
sBuffer = ::Md5GetExpandedBufferSize(sData);
pBuffer = new BYTE[sBuffer];
memmove(pBuffer, (void *)pdwData, sData);
::Md5ExpandData(pBuffer, sData, sBuffer);
::Md5HashData((MD5_WORD *)pBuffer, sBuffer / 64, hsData);
FreeBuffer(pBuffer, sBuffer);
// Done with preparations. Now generating password
unsigned int nChar = 0;
for(int n = 0; n < nPasswordLength; ++n)
{
// Have several versions
switch(n % 4)
{
case 0:
nChar = hsCharset.wA ^ pdwData[n % nDataLength] ^ hsData.wD;
break;
case 1:
nChar = hsCharset.wB ^ pdwData[n % nDataLength] ^ hsData.wC;
break;
case 2:
nChar = hsCharset.wC ^ pdwData[n % nDataLength] ^ hsData.wB;
break;
case 3:
nChar = hsCharset.wD ^ pdwData[n % nDataLength] ^ hsData.wA;
break;
default:
break;
} // switch
nChar %= nCharSetLength;
pszPassword[n] = pszCharSet[nChar];
} // for
// Done
CleanBuffer(&hsCharset, sizeof(MD5HASH));
CleanBuffer(&hsData, sizeof(MD5HASH));
}
void FreeBuffer(void *pBuffer, size_t sBuffer)
{
// Do it a couple of times
memset(pBuffer, 0, sBuffer);
memset(pBuffer, 0xFFFF, sBuffer);
delete [] pBuffer;
}
void CleanBuffer(void *pBuffer, size_t sBuffer)
{
// Do it a couple of times
memset(pBuffer, 0, sBuffer);
memset(pBuffer, 0xFFFF, sBuffer);
}
void CleanString(CString &rstrS)
{
for(int n = 0; n < rstrS.GetLength(); ++n)
{
rstrS.SetAt(n, _T('0'));
} // for
}