22

Web アプリケーションの場合、シンプルで効果的なライセンス システムを作成したいと考えています。C# では、Reflector がインストールされていれば誰でも復号化メソッドを表示できるため、これは少し難しくなります。

かなり改ざん防止されているC#でファイルを暗号化する方法は何ですか?

4

9 に答える 9

39

改ざんを検出できるように、パブリック/プライベート暗号化を使用してライセンストークン(XMLフラグメントやファイルなど)に署名したいようです。これを処理する最も簡単な方法は、次の手順を実行することです。

1)会社のキーペアを生成します。これは、SNツールを使用してVisualStudioコマンドラインで実行できます。構文は次のとおりです。

sn -k c:\keypair.snk

2)キーペアを使用して、クライアントアプリケーションに厳密な名前を付けます(つまり、署名します)。これは、アプリケーションのプロパティページの[署名]タブを使用して設定できます

3)クライアントのライセンスを作成します。これはXMLドキュメントであり、秘密鍵を使用して署名する必要があります。これには、デジタル署名の計算が含まれ、それを実現するための手順は次の場所にあります。

http://msdn.microsoft.com/en-us/library/ms229745.aspx

4)クライアントで、ライセンスを確認するときにXmlDocumentをロードし、公開鍵を使用して署名を検証し、ライセンスが改ざんされていないことを証明します。これを行う方法の詳細は、次の場所にあります。

http://msdn.microsoft.com/en-us/library/ms229950.aspx

鍵の配布を回避するために(つまり、クライアントが正しい公開鍵を使用していることを確認するために)、署名されたアセンブリ自体から実際に公開鍵を引き出すことができます。したがって、配布する別のキーがないことを確認し、誰かがアセンブリを改ざんした場合でも、厳密な名前がアセン​​ブリ自体と一致しなくなるため、.netFrameworkはセキュリティ例外で停止します。

クライアントアセンブリから公開鍵を取得するには、次のようなコードを使用します。

    /// <summary>
    /// Retrieves an RSA public key from a signed assembly
    /// </summary>
    /// <param name="assembly">Signed assembly to retrieve the key from</param>
    /// <returns>RSA Crypto Service Provider initialised with the key from the assembly</returns>
    public static RSACryptoServiceProvider GetPublicKeyFromAssembly(Assembly assembly)
    {
        if (assembly == null)
            throw new ArgumentNullException("assembly", "Assembly may not be null");

        byte[] pubkey = assembly.GetName().GetPublicKey();
        if (pubkey.Length == 0)
            throw new ArgumentException("No public key in assembly.");

        RSAParameters rsaParams = EncryptionUtils.GetRSAParameters(pubkey);
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.ImportParameters(rsaParams);

        return rsa;
    }

Sniptに役立つ暗号化ユーティリティを多数備えたサンプルクラスをhttp://snipt.net/Wolfwyrd/encryption-utilities/にアップロードしました。

https://snipt.net/Wolfwyrd/sign-and-verify-example/にサンプルプログラムも含まれています。このサンプルでは、​​暗号化utilsライブラリを使用してソリューションに追加し、署名用のテストXMLファイルとSNKファイルを提供する必要があります。プロジェクトは、生成したSNKで署名されるように設定する必要があります。SNKの秘密鍵を使用してテストXMLファイルに署名し、アセンブリの公開鍵から検証する方法を示します。

アップデート

ライセンスファイルの詳細な説明を含む最新のブログ投稿を追加しました

于 2008-12-11T16:17:16.843 に答える
7

署名付き XML ファイルを使用します。キーペアの秘密鍵部分で署名し、ソフトウェアの公開鍵部分で確認します。これにより、ライセンスが変更されているかどうかを確認したり、ライセンス ファイルが有効かどうかを確認したりできます。

署名付き XML ファイルの署名とチェックについては、MSDN に記載されています。

もちろん、自分の会社でライセンス ファイルに署名し、ライセンス ファイルを顧客に送信して、顧客がそのライセンス ファイルをフォルダに入れて読み取れるようにすることは当然のことです。

もちろん、人々は分散アセンブリを切り取ったりハッキングしたり、xml 署名チェックを取り除いたりすることができますが、繰り返しますが、あなたが何をしようとも、いつでもそうすることができます。

于 2008-12-11T14:05:03.850 に答える
6

GetPublicKeyFromAssemblyWolfwyrd の回答は優れていますが、Wolfwyrd のメソッド (Wolfwyrd が提供するライブラリの多くのヘルパー メソッドを使用する)のより単純なバージョンを提供したかっただけです。

このバージョンでは、これが必要なすべてのコードです。

/// <summary>
/// Extracts an RSA public key from a signed assembly
/// </summary>
/// <param name="assembly">Signed assembly to extract the key from</param>
/// <returns>RSA Crypto Service Provider initialised with the public key from the assembly</returns>
private RSACryptoServiceProvider GetPublicKeyFromAssembly(Assembly assembly)
{
    // Extract public key - note that public key stored in assembly has an extra 3 headers
    // (12 bytes) at the front that are not part of a CAPI public key blob, so they must be removed
    byte[] rawPublicKeyData = assembly.GetName().GetPublicKey();

    int extraHeadersLen = 12;
    int bytesToRead = rawPublicKeyData.Length - extraHeadersLen;
    byte[] publicKeyData = new byte[bytesToRead];
    Buffer.BlockCopy(rawPublicKeyData, extraHeadersLen, publicKeyData, 0, bytesToRead);

    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
    publicKey.ImportCspBlob(publicKeyData);

    return publicKey;
}
于 2009-10-29T11:25:29.530 に答える
1

MSDN のサンプルは既定のパラメーターを使用しているようで、これによりマシン固有の署名が行われるため、あるマシンでサインオンして別の任意のマシンで検証することはできません。これらのサンプルのロジックを変更して、署名マシンの SNK のキーと検証マシンのアセンブリのキーを使用しました。これは、MSDN サンプルのロジックと、上にリンクされている ExcryptionUtils.cs サンプル (非常によくできています) のルーチンを使用して行われました。

ファイルに署名するために、私はこれを使用しました:

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetRSAFromSnkFile(keyFilePath);

ファイルを確認するために、私はこれを使用しました:

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetPublicKeyFromAssembly
   (System.Reflection.Assembly.GetExecutingAssembly());

ところで: XML 署名の検証では XML コメントが無視されることがわかりました。

于 2009-08-22T20:02:32.080 に答える
1

ライセンスで何らかのセキュリティを提供する唯一の方法は、自分が保持している資格情報に対してオンライン ログインを強制することです (非常に抽象的な話です)。

他のすべての方法は、ライセンスを購入する代わりにソフトウェアをクラックして悪用するため、実装に時間がかかるため、より多くの費用がかかります.

.NET には優れた暗号化クラスがいくつかありますが、おっしゃったように、ライセンスの en-/decription をコーディングしている場合は、誰でも簡単に逆コンパイルできます。

于 2008-12-11T13:53:20.490 に答える
1

なぜ暗号化する必要があるのですか?改ざんされている場合 (たとえば、誰かがユーザー数を増やしているなど)、代わりに組織のデジタル証明書などで署名していただけないでしょうか?

于 2008-12-11T13:36:28.010 に答える
0

または、たとえば、PC の c ドライブの md5 値に基づいてライセンス キーを生成するなどして、ライセンスを特定のマシンに結び付けたい場合があります。その場合、ライセンスはマシン固有になります。

于 2008-12-11T13:41:20.810 に答える
0

署名/検証コードを実装するときは、別のアセンブリに配置しないように注意してください。CAS Tamper-Proofing is Broken: Consequences for Software Licensingの記事で説明されているように、コード アクセス セキュリティの改ざん防止は非常に簡単に回避できるようになりました。

必須の免責事項とプラグイン: 私が共同設立した会社は、OffByZero Cobalt ライセンス ソリューションを提供しています。

于 2009-11-07T06:43:31.957 に答える
-1

RE: キー全体をコードに含めないでください。sn -p を使用して、公開部分をファイルに抽出します。配布するコードでそれを使用して、ライセンスを確認します。

MSDN 記事のコードを使用して、これを容易にする小さなアプリ (LicMaker) を作成しました。アプリは完全な鍵ペアで署名されています。入力は、署名されていない .XML ライセンス ファイルです。出力は、署名付き .LIC ファイル内の元の XML + 署名です。私の製品も、同じ完全な鍵ペア ファイルによって署名されています。製品は、.LIC ファイルが改ざんされていないことを確認します。よく働く。このソリューションには sn -p を使用しませんでした。

于 2009-08-21T19:50:25.497 に答える