charT CPasswordCharPool::GetRandomChar() const { ASSERT(m_char_array.length() > 0); PWSrand *ri = PWSrand::GetInstance(); uint r = ri->RangeRand(static_cast<uint32>(m_char_array.length())); return m_char_array.at(r); }
StringX CPasswordCharPool::MakePronounceable() const { /** * Following based on gpw.C from * http://www.multicians.org/thvv/tvvtools.html * Thanks to Tom Van Vleck, Morrie Gasser, and Dan Edwards. */ charT c1, c2, c3; /* array indices */ long sumfreq; /* total frequencies[c1][c2][*] */ long ranno; /* random number in [0,sumfreq] */ long sum; /* running total of frequencies */ uint nchar; /* number of chars in password so far */ PWSrand *pwsrnd = PWSrand::GetInstance(); stringT password(m_pwlen, 0); /* Pick a random starting point. */ /* (This cheats a little; the statistics for three-letter combinations beginning a word are different from the stats for the general population. For example, this code happily generates "mmitify" even though no word in my dictionary begins with mmi. So what.) */ sumfreq = sigma; // sigma calculated by loadtris ranno = static_cast<long>(pwsrnd->RangeRand(sumfreq+1)); // Weight by sum of frequencies sum = 0; for (c1 = 0; c1 < 26; c1++) { for (c2 = 0; c2 < 26; c2++) { for (c3 = 0; c3 < 26; c3++) { sum += tris[int(c1)][int(c2)][int(c3)]; if (sum > ranno) { // Pick first value password[0] = charT('a') + c1; password[1] = charT('a') + c2; password[2] = charT('a') + c3; c1 = c2 = c3 = 26; // Break all loops. } // if sum } // for c3 } // for c2 } // for c1 /* Do a random walk. */ nchar = 3; // We have three chars so far. while (nchar < m_pwlen) { c1 = password[nchar-2] - charT('a'); // Take the last 2 chars c2 = password[nchar-1] - charT('a'); // .. and find the next one. sumfreq = 0; for (c3 = 0; c3 < 26; c3++) sumfreq += tris[int(c1)][int(c2)][int(c3)]; /* Note that sum < duos[c1][c2] because duos counts all digraphs, not just those in a trigraph. We want sum. */ if (sumfreq == 0) { // If there is no possible extension.. break; // Break while nchar loop & print what we have. } /* Choose a continuation. */ ranno = static_cast<long>(pwsrnd->RangeRand(sumfreq+1)); // Weight by sum of frequencies sum = 0; for (c3 = 0; c3 < 26; c3++) { sum += tris[int(c1)][int(c2)][int(c3)]; if (sum > ranno) { password[nchar++] = charT('a') + c3; c3 = 26; // Break the for c3 loop. } } // for c3 } // while nchar /* * password now has an all-lowercase pronounceable password * We now want to modify it per policy: * If m_usedigits and/or m_usesymbols, replace some chars with * corresponding 'leet' values * Also enforce m_useuppercase & m_uselowercase policies */ if (m_usesymbols || m_usedigits) { // fill a vector with indices of substitution candidates vector<int> sc; FillSC fill_sc(sc, (m_usedigits == TRUE), (m_usesymbols == TRUE)); for_each(password.begin(), password.end(), fill_sc); if (!sc.empty()) { // choose how many to replace (not too many, but at least one) unsigned int rn = pwsrnd->RangeRand(sc.size() - 1)/2 + 1; // replace some of them RandomWrapper rnw; random_shuffle(sc.begin(), sc.end(), rnw); for (unsigned int i = 0; i < rn; i++) leet_replace(password, sc[i], m_usedigits, m_usesymbols); } } // case uint i; if (m_uselowercase && !m_useuppercase) ; // nothing to do here else if (!m_uselowercase && m_useuppercase) for (i = 0; i < m_pwlen; i++) { if (_istalpha(password[i])) password[i] = static_cast<charT>(_totupper(password[i])); } else if (m_uselowercase && m_useuppercase) // mixed case for (i = 0; i < m_pwlen; i++) { if (_istalpha(password[i]) && pwsrnd->RandUInt() % 2) password[i] = static_cast<charT>(_totupper(password[i])); } return password.c_str(); }
charT CPasswordCharPool::GetRandomChar(CPasswordCharPool::CharType t) const { PWSrand *ri = PWSrand::GetInstance(); uint r = ri->RangeRand(static_cast<uint>(m_lengths[t])); return GetRandomChar(t, r); }