C#の一意の文字列に基づいて短いコードを生成する
-
25-10-2019 - |
質問
私はちょうど新しいオンラインサービスのベータを立ち上げようとしています。ベータサブスクライバーには、サービスに登録できる一意の「アクセスコード」が送信されます。
アクセスコードのリストを保存するのではなく、電子メール自体が一意であるため、電子メールに基づいてコードを生成するだけだと思いました。
私の最初の考えは、電子メールを一意の文字列と組み合わせることでした。 base64 それをエンコードします。しかし、私は少し短く、たとえば5桁の長さのコードを探していました。
解決
アクセスコード自体が一意である必要がある場合、衝突に対して確保することは困難です。 2人のユーザーが偶然に同じアクセスコードを共有する可能性のあるケースを許容できる場合、それは大幅に簡単になります。
提案されているように、既知の文字列と連結された電子メールアドレスをベース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:running total += [large prime] * [unicode値
次に、合計5桁の合計%を実行します
しかし、彼が指摘したように、あなたが優れたハッシュ機能を持っていない限り、これはユニークではありません。衝突が発生する可能性があります。それが重要かどうかはわかりません。
私にとって簡単に思えるのは、有効なメールをすでに知っている場合、登録時に有効なメールリストに対してユーザーのメールを確認するだけですか?なぜコードを気にするのですか?
ただし、ユニークな識別子が本当に必要な場合は、これを行う最も簡単な方法は、おそらくGUIDと呼ばれるものを使用することです。 C#はネイティブにサポートされます これ. 。これをユーザーテーブルに保存できます。ユーザーが覚えて/入力するにはあまりにも長すぎるでしょうが、それがあなたがやろうとしていることであれば、それはほぼ確実にユニークです。