Генерация короткого кода на основе уникальной строки в C # - PullRequest
3 голосов
/ 25 июля 2011

Я собираюсь запустить бета-версию нового онлайн-сервиса. Абонентам бета-версии будет выслан уникальный «код доступа», который позволяет им зарегистрироваться для получения услуги.

Вместо того, чтобы хранить список кодов доступа, я подумал, что просто сгенерирую код на основе их электронной почты, поскольку сам по себе он уникален.

Сначала я хотел объединить письмо с уникальной строкой, а затем Base64 закодировать ее. Однако я искал коды, которые немного короче, скажем, 5 цифр.

Ответы [ 3 ]

6 голосов
/ 25 июля 2011

Если сам код доступа должен быть уникальным, будет трудно обеспечить защиту от коллизий. Если вы допустите случай, когда два пользователя по совпадению могут использовать один и тот же код доступа, это станет значительно проще.

Использование предложенного в кодировке 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();
}
2 голосов
/ 25 июля 2011

Вы можете создать специальный хеш из их электронной почты, который составляет менее 6 символов, но это не сделает его уникальным, в таком маленьком пространстве всегда будут столкновения. Я бы предпочел пойти с более длинным ключом или хранить предварительно сгенерированные коды в таблице.

0 голосов
/ 25 июля 2011

Похоже, что здесь вы хотите создать хеш-функцию специально для электронных писем, как указал @can poyragzoglu. Очень простой может выглядеть примерно так:

(псевдокод) foreach char c в электронной почте: промежуточный итог + = [большое простое число] * [значение в юникоде]

затем выполните общее%% 5-значное число

Как он указал, это не будет уникальным, если у вас не будет отличной хэш-функции. У вас могут быть столкновения. Не уверен, что это имеет значение.

Что кажется мне более простым: если вы уже знаете действительные электронные письма, просто проверьте электронную почту пользователя по списку действительных электронных писем при регистрации? Зачем вообще беспокоиться о коде?

Если вам действительно нужен уникальный идентификатор, то самый простой способ сделать это, вероятно, просто использовать то, что называется GUID. C # изначально поддерживает this . Вы можете сохранить это в вашей таблице пользователей. Хотя для пользователя было бы слишком долго запоминать / печатать, почти наверняка он будет уникальным для каждого, если вы пытаетесь это сделать.

...