web-dev-qa-db-ja.com

ライセンスキー/シリアル番号ジェネレーターおよびチェッカー

シリアル番号ジェネレーターと付随するチェッカーが必要です。私は塩を(そしておそらく長さを)設定できるようにしたいと思います。ジェネレータは、チェッカーのテストに合格したシリアル番号のみを生成する必要があります。それらの数は、与えられた長さのすべての可能な数のほんの一部を占めるべきです。

アルゴリズム暗号的に安全である必要はありません。むしろ、(JavaScriptで)実装するのは非常に簡単で、非常に高速でなければなりません。

明確にするために:市販のソフトウェアを購入すると、シリアル番号/キーで保護される場合があります。入力すると、ソフトウェアは巨大なデータベースを検索するのではなく、(特定のプロパティを満たすかどうかをチェックすることにより)アルゴリズムで検証します。また、キーはすべて手作業ではなくアルゴリズムで生成されたと確信しています。そして、指定された長さのすべての可能なキーのほんの一部のみが実際に有効であるため、キーを推測することは困難です。

ソルト:ソルトが正しいWordかどうかはわかりませんが、アルゴリズムには少なくとも1つのパラメーターが必要です。パラメーターを選択すると、生成されたキーが変更されます(複数の人が同じアルゴリズムを使用でき、衝突を恐れる必要がないため)。

16
Dave

セキュリティが本当に必要ない場合は、チェッカー付きの非常に高速なシリアル番号ジェネレータを次に示します。

  • カウンターを使用します。 0で初期化します。新しいシリアル番号が必要な場合は、カウンターを1000ずつ増やします。新しいカウンター値はシリアル番号です。チェッカーは次のように機能します。3つのゼロで終わるシリアル番号は有効です。チェッカーが受け入れるのは、1000ごとに1つだけです。

このソリューションで満足できない場合は、doセキュリティが必要であり、暗号化が必要です。

暗号化された安全なソリューションは、署名されたシリアル番号を持つことです。シリアル番号は、いくつかのペイロード(たとえば、生成したすべてのシリアル番号のカウンター)のエンコードと、ペイロードに対する署名です。ジェネレーターには秘密鍵があり、署名の計算に使用されます。チェッカーは、対応する公開鍵のみを認識します。このセットアップの問題は、JavaScriptであっても、検証時間に関するものではありません。むしろ、問題となるのは署名のsizeです。シリアル番号は、ある時点でユーザーによって入力されると思います。暗号的に安全な署名の理論上の最小サイズは約80ビットです(署名は公開鍵のみで検証できるため、攻撃者はすべての可能なビットシーケンスを試すことができ、通常、少なくとも2のセキュリティレベルが必要です)80)。ただし、「安全なスキームであると想定されている」の中で最小の署名は160ビットに近い( [〜#〜] bls [〜#〜] であり、これはペアリングを使用します。実装する)または320ビット( [〜#〜] dsa [〜#〜] または [〜#〜] ecdsa [〜#〜] を使用)。短い署名( Quartz 、または McEliece-Niederreiter )の署名システムでいくつかの作業がありますが、そのセキュリティにはかなりの論争があります。

大文字と数字の両方(可能な36文字で、「I」と「1」の両方、「O」と「0」もある)でも、160ビットの署名では31文字を使用します。ペイロードとともに、最終的には長さが35程度のシリアル番号になります。これは、おそらく平均的なユーザーが入力するには多すぎます(ただし、余白を大きくすることはできません。80ビットの署名はうまく適合します)。

署名スキームを使用しない場合は、合理的に決定された攻撃者willが逆アセンブルによってチェッカーを迂回できること、またはチェッカーを生成するのに十分なことさえ学べることに注意する必要があります。独自のシリアル番号(チェッカーが喜んで受け入れる)その時点では、定量化されたセキュリティは得られません。「私のスキームは38億ドルの予算まで安全です」とは言えません。むしろ、「十分に機知に富んだ退屈な学生がやって来て、チェッカーコードをリバースエンジニアリングし、結果をFacebookに公開するまで、私のスキームは安全です」のようになります。

従来の非真に安全なスキームは次のようになります。

  • 前のスキーム(最後に3つのゼロがあるスキーム)のカウンターを使用します。 64ビットブロックとしてエンコードします。ブロック暗号を使用して、ハードコードされた対称鍵でそのブロックを暗号化します。チェッカーはキーを知っており、シリアル番号を(ハードコードされた同じ対称キーを使用して)復号化し、最後のゼロを確認して検証します。

これは通常のカウンタよりも安全ではありませんが、少なくともシリアル番号はランダムに見えます。 34文字のアルファベット(「O」と「I」を除く数字と大文字)では、64ビットブロックには13文字が必要ですが、これはおそらく許容されます(通常のMicrosoftシリアル番号は25文字です)。 64ビットブロック暗号の場合は、 [〜#〜] xtea [〜#〜] をお勧めします。これは、実装するのに十分高速でシンプルである必要があります。

26
Thomas Pornin

暗号化された安全な方法が必要な場合は、シリアルを確認するためにインターネット接続を回避する必要はありません。つまり、このような保護スキームは、従来のシェルフソフトウェアよりもサブスクリプションベースのソフトウェアに適しています。

インターネット接続は簡単です(JSを使用しているので、それが必要なものだと思います)。

  1. 誰かが鍵を作成し、その当事者は秘密を知る必要があります
  2. サーバーは秘密を知っており、データをデコードできます
  3. クライアントは、 Base32 でエンコードされたバイナリBLOBであるキーを送信します( this も参照)
  4. サーバーはキーを復号化し、それが有効であるかどうかを確認します(構文的にまたは意味的に)

インターネット接続がなくても、ユーザーが入力したblobが自分で作成されたことを確認するために、PGP署名と同様のスキームを使用できます。暗号化は同じようには機能しません。なぜなら、復号化は常に秘密を知る必要があり、ここでの大きな問題は次のとおりだからです。

  1. ユーザーを信頼していません(そうでなければ、保護スキームは必要ありません)
  2. バイナリにコンパイルされた秘密をユーザーに与える

明らかに、両方の点は互いに矛盾しています。一方ではユーザーを信頼せず、他方では復号化に使用されるシークレットを展開する必要があります。

結局のところ、インターネット接続とサーバーベースの有効性チェックがなければ、ある程度の知識(例:長い間だけ役立つコンテンツ)が明らかになる保護スキームがないと結論付けなければなりませんこれまでのところ、クラッカーとベンダーの間の武装競争が見られます。


さて、暗号的に安全なシステムを持つことが重要ではない場合でも、単純なCRCなどで保護できるバイナリデータを使用します。頭に浮かぶのは:

  1. 単調に増加するシリアル番号を持っている
  2. ソルト値とXOR(またはその他の可逆操作)
  3. その値のCRC32(またはAdler32など)を取得します-必要に応じてここにソルトを追加します
  4. Base32 でエンコードします(読みやすさなどを支援します)
  5. CRC32の妥当性のみを確認してください...
6
0xC0000022L

OPは、「(JavaScriptで)実装するのは非常に簡単で、非常に高速でなければならない」と書いています。

「JavaScriptで」がジェネレーターまたはチェッカー、あるいはその両方を指しているのか、「ブラウザーでのJavaScript」を指しているのか、それとも他のJava/ecmascript実装(Webサーバーのサーバー側など)を指しているのかは明確ではありません。

実装言語としてのJavaScriptは必ずしも問題ではなく、JavaScript用の暗号ライブラリがいくつかあります(MD5、DES、AES、SHA、PBKDF2、HMACをサポートしています)。

速度もそれほど問題ではないはずです(ブラウザのJavaScriptエンジンは、IE6/7を通過すると、その点でかなり使いやすくなります)。

ただし、上記のいずれも公開鍵暗号をサポートしていません(「チェッカー」が信頼されていないユーザーに配布され、シリアル番号の作成に使用される鍵へのアクセスを許可されない場合のセキュリティに必要です)。トーマス、上。 GoogleはJavaScriptでの公開鍵実装のヒットをいくつか確認しています(http://www-cs-students.stanford.edu/~tjw/jsbn/、 http://ohdave.com/rsa/ =、 http://www.hanewin.net/encrypt/rsa/rsa.htm )が、個人的には、上記の「より大きな」ライブラリよりも、バグのないことについてさらに神経質になります。 。

おそらくさらに重要なのは、公開鍵ベースのアプローチでも、ジェネレーターまたはチェッカーのいずれかが信頼できないユーザーに配布されている場合、スキームは安全ではないということです。信頼できないユーザーがジェネレータコードを使用できる場合は、好きなだけキーを生成できます。一方、信頼できないユーザーがチェッカーを使用できる場合は、JavaScriptコードを変更してチェックをスキップできます。 [もちろん、ネイティブコードでも同じ問題が発生しますが、難読化を行ったとしても、JavaScriptはローカルの変更を通じて攻撃する方が間違いなく簡単です。]

JavaScriptでセキュリティスキームを実装する前に、より広い信頼の問題も考慮する必要があります。次を参照してください http://rdist.root.org/2010/11/29/final-post-on-javascript-crypto/ 有用な要約について。

3
Misha