Files
Slnkdwf/SlnkDWFCom/Crypto.cpp
Jos Groot Lipman 76d3cce070 Versie 4.11: Crypto.hex_pbkdf2 object toegevoegd
svn path=/Slnkdwf/trunk/; revision=26205
2015-09-06 09:47:55 +00:00

256 lines
6.5 KiB
C++

// Crypto.cpp : Implementation of CCrypto
#include "stdafx.h"
#include "Crypto.h"
// CCrypto
#include "hmac_sha1.h"
#include <math.h>
// Base64_encode from http://www.adp-gmbh.ch/cpp/common/base64.html
static const char *base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
CString base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len, BOOL padding) {
CString ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while(padding && (i++ < 3))
ret += '=';
}
return ret;
}
STDMETHODIMP CCrypto::b64_hmac_sha1(BSTR key, BSTR data, BSTR* pVal)
{
BYTE digest[20];
CString akey(key);
CString adata(data);
CHMAC_SHA1 HMAC_SHA1 ;
HMAC_SHA1.HMAC_SHA1((BYTE *)adata.GetBuffer(), adata.GetLength(), (BYTE *)akey.GetBuffer(), akey.GetLength(), digest) ;
CString res = base64_encode(digest, 20, false); // no padding
CComBSTR bstrString(res);
return bstrString.CopyTo(pVal);
}
const char *hex_tab = "0123456789abcdef";
STDMETHODIMP CCrypto::hex_hmac_sha1(BSTR key, BSTR data, BSTR* pVal)
{
BYTE digest[20];
CString akey(key);
CString adata(data);
CHMAC_SHA1 HMAC_SHA1 ;
HMAC_SHA1.HMAC_SHA1((BYTE *)adata.GetBuffer(), adata.GetLength(), (BYTE *)akey.GetBuffer(), akey.GetLength(), digest) ;
CString res;
for(int i = 0; i < 20; i++)
{
res = res + hex_tab[digest[i] >> 4];
res = res + hex_tab[digest[i] & 0xF];
}
CComBSTR bstrString(res);
return bstrString.CopyTo(pVal);
}
STDMETHODIMP CCrypto::hex_sha1(BSTR data, BSTR* pVal)
{
CSHA1 sha1;
CString adata(data);
sha1.Update((UINT_8*)adata.GetBuffer(), adata.GetLength());
sha1.Final();
TCHAR res[41];
sha1.ReportHash(res, CSHA1::REPORT_HEX_SHORT); // Get final hash as pre-formatted string
CComBSTR bstrString(res);
bstrString.ToLower();
return bstrString.CopyTo(pVal);
}
// Big Endian
static inline void be32enc(void *pp, uint32_t x)
{
uint8_t * p = (uint8_t *)pp;
p[3] = x & 0xff;
p[2] = (x >> 8) & 0xff;
p[1] = (x >> 16) & 0xff;
p[0] = (x >> 24) & 0xff;
}
/* F(P, S, c, i) = U1 xor U2 xor ... Uc
* U1 = PRF(P, S || i)
* U2 = PRF(P, U1)
* Uc = PRF(P, Uc-1)
*/
#define SHA1_MAC_LEN 20
STDMETHODIMP CCrypto::hex_pbkdf2(BSTR pPassword, BSTR pSalt, ULONG pCount, ULONG pLength, BSTR* pVal)
{
CString apass(pPassword);
CString asalt(pSalt);
int saltlen = asalt.GetLength();
BYTE *saltbuff = (BYTE *)asalt.GetBufferSetLength(saltlen + 4); // Ruimte maken voor counter
int passlen = apass.GetLength();
BYTE *passbuff = (BYTE *)apass.GetBuffer();
size_t i;
uint8_t U[SHA1_MAC_LEN];
uint8_t T[SHA1_MAC_LEN]; // Hierin komt het XOR resultaat
CString res;
/* Iterate through the blocks. */
for (i = 0; i * SHA1_MAC_LEN < pLength; i++)
{
/* Generate INT(i + 1). */
be32enc(saltbuff + saltlen, i + 1);
/* Compute U_1 = PRF(P, S || INT(i)). */
CHMAC_SHA1 HMAC_SHA1;
HMAC_SHA1.HMAC_SHA1(saltbuff, saltlen + 4, passbuff, passlen, U);
/* T_1 = U_1 ... */
memcpy(T, U, SHA1_MAC_LEN);
for (uint64_t j = 2; j <= pCount; j++)
{
/* Compute U_j. */
HMAC_SHA1.HMAC_SHA1(U, SHA1_MAC_LEN, passbuff, passlen, U);
/* ... xor U_j ... */
for (int k = 0; k < sizeof(U); k++)
T[k] ^= U[k];
}
/* Copy as many bytes as necessary into buf. */
int clen = pLength - i * SHA1_MAC_LEN;
if (clen > SHA1_MAC_LEN)
clen = SHA1_MAC_LEN;
for (int k = 0; k < clen; k++)
{
res = res + hex_tab[T[k] >> 4];
res = res + hex_tab[T[k] & 0xF];
}
}
CComBSTR bstrString(res);
return bstrString.CopyTo(pVal);
}
STDMETHODIMP CCrypto::hex_sha1_file(BSTR fname, BSTR* pVal)
{
CSHA1 sha1;
if (!sha1.HashFile(CString(fname))) // Hash the contents of the file
return myAtlReportError (GetObjectCLSID(), "\nCCrypto::hex_sha1_file('%ls')", (LPCSTR)fname);
sha1.Final();
TCHAR res[41];
sha1.ReportHash(res, CSHA1::REPORT_HEX_SHORT); // Get final hash as pre-formatted string
CComBSTR bstrString(res);
bstrString.ToLower();
return bstrString.CopyTo(pVal);
}
STDMETHODIMP CCrypto::hotp(BSTR hexseed, LONGLONG moving_factor, BYTE digits, BSTR* pVal)
{
BYTE digest[20];
CSHA1 sha1;
if (digits < 6 || digits > 8)
return E_INVALIDARG;
CString sseed(hexseed);
if (sseed.GetLength() > 40)
return E_INVALIDARG;
BYTE seed[20];
for(int i = 0; i < sizeof(seed); i++)
{
BYTE hi=sseed[2*i];
hi-=(hi<'A' ? '0' : 'A'-10);
BYTE lo=sseed[2*i+1];
lo-=(lo<'A' ? '0' : 'A'-10);
seed[i] = (hi<<4) | (lo & 0x0F); // " & 0x0F" deals with lower-case characters
}
ATLASSERT(sizeof(moving_factor) == 8);
BYTE counter[sizeof(moving_factor)];
for (int i = 0; i < sizeof (counter); i++)
counter[i] = (BYTE)(moving_factor >> ((sizeof (moving_factor) - i - 1) * 8)) & 0xFF;
CHMAC_SHA1 HMAC_SHA1 ;
HMAC_SHA1.HMAC_SHA1((BYTE *)(&counter), sizeof(counter), seed, sizeof(seed), digest) ;
CString res;
BYTE offset = digest[sizeof (digest) - 1] & 0x0f;
uint64_t S = (((digest[offset] & 0x7f) << 24)
| ((digest[offset + 1] & 0xff) << 16)
| ((digest[offset + 2] & 0xff) << 8) | ((digest[offset + 3] & 0xff)));
res.Format("%lld",1000000000L + S);
res = res.Right(digits);
/*
for(int i = 0; i < 20; i++)
{
res = res + hex_tab[digest[i] >> 4];
res = res + hex_tab[digest[i] & 0xF];
}
*/
CComBSTR bstrString(res);
bstrString.ToLower();
return bstrString.CopyTo(pVal);
}