4

新しいオンライン サービスのベータ版を開始しようとしています。ベータ版のサブスクライバーには、サービスに登録できる固有の「アクセス コード」が送信されます。

アクセス コードのリストを保存するのではなく、電子メールに基づいてコードを生成するだけでよいと考えました。これ自体が一意であるためです。

私が最初に考えたのは、電子メールを一意の文字列と組み合わせてから、Base64でエンコードすることでした。しかし、私はもう少し短いコード、たとえば 5 桁の長さのコードを探していました。

4

3 に答える 3

8

アクセス コード自体を一意にする必要がある場合は、衝突を防ぐことが難しくなります。偶然にも 2 人のユーザーが同じアクセス コードを共有する可能性がある場合を許容できれば、非常に簡単になります。

提案されているように、既知の文字列と連結された電子メール アドレスの base-64 エンコーディングを使用すると、セキュリティ上の脆弱性が生じる可能性があります。既知の単語と連結された電子メール アドレスの base64 出力を使用した場合、ユーザーはアクセス コードのエンコードを解除し、コードの生成に使用されたアルゴリズムを導き出すことができます。

1 つのオプションは、既知の秘密鍵を使用して電子メール アドレスの 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();
}
于 2011-07-24T23:41:43.537 に答える
2

メールから 6 文字未満の特別なハッシュを作成することもできますが、それは実際には「一意」にはなりません。このような小さなスペースでは常に衝突が発生します。とにかく、より長いキーを使用するか、事前に生成されたコードをテーブルに保存したいと思います。

于 2011-07-24T22:25:16.950 に答える
0

したがって、ここでやりたいことは、@can poyragzoglu が指摘したように、メール専用のハッシュ関数を作成することのようです。非常に単純なものは次のようになります。

(疑似コード) foreach char c in email: 累計 += [大きい素数] * [unicode 値]

次に、合計 % の大きな 5 桁の数字を実行します

ただし、彼が指摘したように、優れたハッシュ関数がない限り、これは一意ではありません。衝突する可能性があります。それが重要かどうかはわかりません。

有効な電子メールを既に知っている場合は、登録時にユーザーの電子メールを有効な電子メールのリストと照合するだけで簡単に思えますか? なぜコードを気にする必要があるのでしょうか。

ただし、一意の識別子が本当に必要な場合は、これを行う最も簡単な方法は、おそらく GUID と呼ばれるものを使用することです。C# はこれをネイティブにサポートしています。これを Users テーブルに保存できます。ただし、ユーザーが覚えたり入力したりするには長すぎますが、それがあなたがやろうとしていることであれば、ほぼ確実にそれぞれに固有のものになります。

于 2011-07-24T22:45:05.950 に答える