1 // Berkeley Open Infrastructure for Network Computing
2 // http://boinc.berkeley.edu
3 //
4 // Source Code Originally from:
5 // http://support.microsoft.com/kb/814463
6 //
7
8 #include "stdafx.h"
9 #include "password.h"
10
11 //Generates a Random string of length nLen - 1. Buffer ppwd must allocate an extra character for null terminator.
12 //Returns TRUE if successful, FALSE if fails.
13 //Extended error information can be obtained from GetLastError().
GenPwd(TCHAR * ppwd,int nLen)14 BOOL GenPwd(TCHAR* ppwd, int nLen)
15 {
16 BOOL bResult = FALSE; //assume failure
17 HCRYPTPROV hProv = NULL;
18 HCRYPTHASH hHash = NULL;
19
20 //Storage for random string 4 times longer than the resulting password.
21 DWORD dwBufSize = nLen*4;
22 DWORD dwSize = Base64EncodeGetRequiredLength((int)dwBufSize);
23 LPSTR pEncodedString = NULL;
24 LPBYTE pRandomBuf = NULL;
25 TCHAR* pTRandomPwd = NULL;
26
27 try
28 {
29 pEncodedString = new char[dwSize];
30 pRandomBuf = new BYTE[dwBufSize];
31
32 // Try to acquire context to Crypto provider.
33 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT))
34 {
35 if (GetLastError() == NTE_BAD_KEYSET) //Test for non-existent keyset
36 {
37 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_NEWKEYSET))
38 throw(GetLastError());
39 }
40 else
41 throw(GetLastError());
42 }
43
44 //Generate a random sequence.
45 if (!CryptGenRandom(hProv, dwBufSize, pRandomBuf))
46 {
47 throw(GetLastError());
48 }
49
50 //Get a handle to a hash, then hash the random stream.
51 if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
52 {
53 throw(GetLastError());
54 }
55
56 if (!CryptHashData(hHash, pRandomBuf, dwBufSize, NULL))
57 {
58 throw(GetLastError());
59 }
60
61 //Destroy the hash object.
62 CryptDestroyHash(hHash);
63 //Release Provider context
64 CryptReleaseContext(hProv, 0);
65
66 //Encode the hash value to base64.
67 if (!Base64Encode(pRandomBuf, dwBufSize, pEncodedString, (int*) &dwSize, 0))
68 {
69 throw(GetLastError());
70 }
71
72 //Determine how many tchars you need to convert string to base64.
73 int nTchars = (int) strlen(pEncodedString);
74
75 pTRandomPwd = new TCHAR[nTchars];
76
77 #ifdef UNICODE
78 if (MultiByteToWideChar(CP_UTF8, 0, pEncodedString, nTchars, pTRandomPwd, nTchars) == 0)
79 {
80 throw(GetLastError());
81 }
82 #else
83 _tcsncpy( pTRandomPwd, pEncodedString, nLen);
84 #endif
85
86 //Copy the first x characters of random string to output buffer.
87 _tcsncpy(ppwd, pTRandomPwd, nLen);
88 //Add null terminator to ppwd string.
89 ppwd[nLen] = _T('\0');
90
91 bResult = TRUE;
92
93 }
94 catch (DWORD)
95 {
96 //Set return value to false.
97 bResult = FALSE;
98 }
99 catch (...)
100 {
101 //Unknown error, throw.
102 throw;
103 }
104
105 //Clean up memory.
106 if (pRandomBuf)
107 {
108 delete[] pRandomBuf;
109 pRandomBuf = NULL;
110 }
111
112 if (pEncodedString)
113 {
114 delete[] pEncodedString;
115 pEncodedString = NULL;
116 }
117
118 if (pTRandomPwd)
119 {
120 delete[] pTRandomPwd;
121 pTRandomPwd = NULL;
122 }
123
124 return bResult;
125 }
126
127
GenerateRandomPassword(tstring & strPassword,DWORD dwDesiredLength)128 BOOL GenerateRandomPassword( tstring& strPassword, DWORD dwDesiredLength )
129 {
130 TCHAR szBuffer[512];
131 BOOL bReturnValue = FALSE;
132
133 bReturnValue = GenPwd(szBuffer, dwDesiredLength);
134
135 strPassword = szBuffer;
136
137 return bReturnValue;
138 }
139
140