新しいオンライン サービスのベータ版を開始しようとしています。ベータ版のサブスクライバーには、サービスに登録できる固有の「アクセス コード」が送信されます。
アクセス コードのリストを保存するのではなく、電子メールに基づいてコードを生成するだけでよいと考えました。これ自体が一意であるためです。
私が最初に考えたのは、電子メールを一意の文字列と組み合わせてから、Base64でエンコードすることでした。しかし、私はもう少し短いコード、たとえば 5 桁の長さのコードを探していました。
新しいオンライン サービスのベータ版を開始しようとしています。ベータ版のサブスクライバーには、サービスに登録できる固有の「アクセス コード」が送信されます。
アクセス コードのリストを保存するのではなく、電子メールに基づいてコードを生成するだけでよいと考えました。これ自体が一意であるためです。
私が最初に考えたのは、電子メールを一意の文字列と組み合わせてから、Base64でエンコードすることでした。しかし、私はもう少し短いコード、たとえば 5 桁の長さのコードを探していました。
アクセス コード自体を一意にする必要がある場合は、衝突を防ぐことが難しくなります。偶然にも 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();
}
メールから 6 文字未満の特別なハッシュを作成することもできますが、それは実際には「一意」にはなりません。このような小さなスペースでは常に衝突が発生します。とにかく、より長いキーを使用するか、事前に生成されたコードをテーブルに保存したいと思います。
したがって、ここでやりたいことは、@can poyragzoglu が指摘したように、メール専用のハッシュ関数を作成することのようです。非常に単純なものは次のようになります。
(疑似コード) foreach char c in email: 累計 += [大きい素数] * [unicode 値]
次に、合計 % の大きな 5 桁の数字を実行します
ただし、彼が指摘したように、優れたハッシュ関数がない限り、これは一意ではありません。衝突する可能性があります。それが重要かどうかはわかりません。
有効な電子メールを既に知っている場合は、登録時にユーザーの電子メールを有効な電子メールのリストと照合するだけで簡単に思えますか? なぜコードを気にする必要があるのでしょうか。
ただし、一意の識別子が本当に必要な場合は、これを行う最も簡単な方法は、おそらく GUID と呼ばれるものを使用することです。C# はこれをネイティブにサポートしています。これを Users テーブルに保存できます。ただし、ユーザーが覚えたり入力したりするには長すぎますが、それがあなたがやろうとしていることであれば、ほぼ確実にそれぞれに固有のものになります。