11

私の最終的な目標は、一意で推測/予測できないURLを作成することです。このURLの目的は、ユーザーがメールアドレスの確認やパスワードのリセットなどの操作を実行できるようにすることです。これらのURLは、設定された時間(現在は24時間に設定されています)内に期限切れになります。

私はもともとGuidこの目的でを使用していましたが、聞いている専門家によっては、これが「問題ない」と「非常に安全でない」の間のどこかにあることがわかりました。ですから、念のため、コードを少し強化したいと思いました。最初は、を使用することに固執すると思いましたが、ファクトリメソッドGuidではなくランダムバイトから生成します。Guid.NewGuid()これが私が思いついた方法です:

public static Guid GetRandomGuid()
{
    var bytes = new byte[16];
    var generator = new RNGCryptoServiceProvider();
    generator.GetBytes(bytes);
    return new Guid(bytes);
}

new Guid(bytes)の代わりにを使用するとどうなるかはよくわかりませんが、この方法ではランダムなバイト配列を生成してデータ構造に格納Guid.NewGuid()するだけだと思います。つまり、一意であることが保証されるのではなく、ランダムであることが保証されるだけです。Guid

私のURLは一意でランダムである必要があるため、これは確実な解決策のようには思えません。私は今考えています。URLは、一意のID(Guidまたは、使用可能な場合はデータベースの自動インクリメントID)とから生成されたランダムシーケンスの両方の組み合わせに基づいて作成する必要がありますRNGCryptoServiceProvider

質問

一意であることが保証され、予測/推測が非常に困難/不可能である検証/パスワードリセットURLを生成するための最良の方法は何ですか?

  • 一意の文字列をランダムな文字列と連結してURLを作成するだけでよいですか?

  • .NET Frameworkには、URLに使用できる一意ランダムな(予測できない)シーケンスを簡単に生成する方法が組み込まれていますか?

  • そうでない場合、利用可能なオープンソースの良いソリューションはありますか?

アップデート

誰かが同様の要件を持っている場合、私は現在次の方法を使用しています:

public static string GenerateUniqueRandomToken(int uniqueId)
    // generates a unique, random, and alphanumeric token
{
    const string availableChars =
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    using (var generator = new RNGCryptoServiceProvider())
    {
        var bytes = new byte[16];
        generator.GetBytes(bytes);
        var chars = bytes
            .Select(b => availableChars[b % availableChars.Length]);
        var token = new string(chars.ToArray());
        return uniqueId + token;
    }
}

これで問題が発生した場合はコメントしてください。

4

5 に答える 5

6

Guidは、セキュリティ機能を目的としたものではありません。Guidを作成するための標準は、Guidがどれほど安全であるか、または推測するのがどれほど簡単/難しいかについては何も主張していません。それは単にそれの独自性について主張するだけです。

Guidを使用してシステムを保護しようとすると、安全なシステムが得られません。

于 2012-09-03T01:08:17.267 に答える
0

[編集:上記のRNGCryptoServiceProviderへの呼び出しを逃しました。それについてお詫びします。]

あなたの場合のRNGCryptoServiceProviderのようなRNGジェネレーターの問題は、それらが一意性を保証しないことです。ご存知のように、GUIDは統計的に一意である可能性は低いですが、それを保証するものではありません。一意性とランダム性の両方を保証する唯一の実際の方法は、データベーステーブルなどの検索可能なストアに配置したようにGUIDを生成することです。新しい値を生成するときはいつでも、それがまだ存在していないことを確認してください。そうである場合は、それを破棄して新しい値を生成します。

于 2012-09-03T03:26:26.987 に答える
0

ランダムキーでキー設定されたAESカウンターを介してカウンターを実行することにより、128ビットの「ランダムな」一意の番号を生成できます。同じキーが使用されている限り、これは出力を繰り返すことはありません。

static byte[] AESCounter(byte[] key, ulong counter) {
    byte[] InputBlock = new byte[16];
    InputBlock[0] = (byte)(counter & 0xffL);
    InputBlock[1] = (byte)((counter & 0xff00L) >> 8);
    InputBlock[2] = (byte)((counter & 0xff0000L) >> 16);
    InputBlock[3] = (byte)((counter & 0xff000000L) >> 24);
    InputBlock[4] = (byte)((counter & 0xff00000000L) >> 32);
    InputBlock[5] = (byte)((counter & 0xff0000000000L) >> 40);
    InputBlock[6] = (byte)((counter & 0xff000000000000L) >> 48);
    InputBlock[7] = (byte)((counter & 0xff00000000000000L) >> 54);
    using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
    {
        AES.Key = key;
        AES.Mode = CipherMode.ECB;
        AES.Padding = PaddingMode.None;
        using (ICryptoTransform Encryptor = AES.CreateEncryptor())
        {
            return Encryptor.TransformFinalBlock(InputBlock, 0, 16);
        }
    }
}
于 2012-09-05T05:46:44.493 に答える
0

すべてのユーザーログイン資格情報のmd5を取得し、Guid.NewGuid()。ToString()によって生成されたGUIDと連結して、URLで使用すると正常に機能するはずです。

于 2013-04-21T20:01:58.300 に答える
0

linkIDとDatesent列を使用してデータベースにテーブルを作成し、リンクの生成時にDateTime.Nowテーブルに挿入を送信してlinkIdを返し、activityLinkのクエリ文字列パラメーターとしてlinkIDを設定します。

アクティベーションページのロード時に、linkIdを取得し、それを使用して、対応するlinkIdがパラメーターとして渡されたときに日付を返すストアドプロシージャを呼び出します。日付を取得したときに、リンクをアクティブに保つ期間を追加できます。.AddDays()/を使用します.AddMonths(これは日時のC#メソッドです)。次に、戻ってきた日付を今日の日付と比較します。日または月の長さを過ぎている場合は、エラーメッセージを表示するか、続行してページのコンテンツを表示します。

ページの内容をパネルに保持して設定し、日付がまだ範囲内にある場合にvisible = "false"のみパネルを作成することをお勧めします。visible="true"

于 2015-03-05T17:34:55.620 に答える