Если сам код доступа должен быть уникальным, будет трудно обеспечить защиту от коллизий. Если вы допустите случай, когда два пользователя по совпадению могут использовать один и тот же код доступа, это станет значительно проще.
Использование предложенного в кодировке Base-64 адреса электронной почты, объединенного с известной строкой, может привести к уязвимости системы безопасности. Если вы используете вывод base64 адреса электронной почты, объединенного с известным словом, пользователь может просто расшифровать код доступа и получить алгоритм, использованный для генерации кода.
Один из вариантов - взять хеш SHA-1-HMAC (System.Cryptography.HMACSHA1) адреса электронной почты с известным секретным ключом. Выход хеша представляет собой 20-байтовую последовательность. Затем вы могли бы урезать хэш детерминистически. Например, в следующем примере GetCodeForEmail("test@example.org")
дает код 'PE2WEG':
// define characters allowed in passcode. set length so divisible into 256
static char[] ValidChars = {'2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H',
'J','K','L','M','N','P','Q',
'R','S','T','U','V','W','X','Y','Z'}; // len=32
const string hashkey = "password"; //key for HMAC function -- change!
const int codelength = 6; // lenth of passcode
string GetCodeForEmail(string address)
{
byte[] hash;
using (HMACSHA1 sha1 = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(hashkey)))
hash = sha1.ComputeHash(UTF8Encoding.UTF8.GetBytes(address));
int startpos = hash[hash.Length -1] % (hash.Length - codelength);
StringBuilder passbuilder = new StringBuilder();
for (int i = startpos; i < startpos + codelength; i++)
passbuilder.Append(ValidChars[hash[i] % ValidChars.Length]);
return passbuilder.ToString();
}