簡體   English   中英

WCF,C#:發送簽名的LicenseKey(RSA)

[英]WCF, C#: Send a signed LicenseKey (RSA)

我閱讀了多個教程等,但我仍然不確定正確的方法是什么。

這里的場景:

我們的客戶(客戶端始終是服務器)在我們的網絡中安裝我們的Web應用程序。 每個客戶端都需要一個包含多個模塊的許可證密鑰。 為了確保它們不會篡改許可證密鑰(包含他們購買的模塊等),我想用非對稱密鑰簽名。

客戶端(客戶端始終是服務器)想要在我們的服務器上激活許可證。 服務器知道客戶購買了哪種許可證/模塊。 所以它創建一個應該包含簽名許可證密鑰的響應。

響應看起來像這樣(客戶是服務返回的)

public class Customer 
{
   public string Identifier {get; set;}
   public LicenseKey LicenseKey {get; set; }

}

public class LicenseKey 
{
   public List<License>{get; set;}
}

public class License 
{
  //actual LicensingData
}

我想要做的是簽署“LicenseKey”。 客戶端收到此許可證密鑰並將其存儲在數據庫中,並且每隔X分鍾就會驗證其完整性。

所以這是我的問題/問題。

我應該如何簽署LicenseKey,以便只簽署WCF響應的“LicenseKey”部分,並且重要的是,可以在WCF-Request之外存儲和使用/驗證?

我知道WCF提供了“ProtectionLevel.Sign”,但是我必須創建X509證書才能讓它工作,對嗎? 這甚至可以在WCF之外工作/驗證嗎?

或者我應該編寫一個消息攔截器來手動簽署我的LicenseKey?

謝謝你的幫助

由於使用簽名保護許可證密鑰的完整性是一項業務要求,我認為它應該是關鍵數據結構本身的一部分。 類似地,簽名應該在創建密鑰時創建,而不是稍后在WCF堆棧中應用(這在技術上可能當然是錯誤的地方恕我直言)。

如何簽署仲裁數據?

  • 創建數據的哈希表示
  • 計算哈希上的簽名

這是使用RSACryptoServiceProvider的快速演示。 當然,如果需要,也可以使用完整的X.509證書。

using System.Security.Cryptography;
using System.Text;

namespace SignatureDemo
{
    public class Demo
    {
        static void Main(string[] args)
        {
            // "Main" is from the client point of view

            LicenseServer server = new LicenseServer();
            Signer signer = new Signer();

            // Obtain a key from the server
            LicenseKey key = server.GetKey("nodots");

            // Verify the signature of the unchanged key, this will result to true
            bool isValid1 = signer.VerifySignature(key, server.PublicKey);

            // Manipulate the license
            key.License.FeatureB = true;

            // Verify the signature of the changed key, this will result to false
            bool isValid2 = signer.VerifySignature(key, server.PublicKey);
        }
    }

    public class LicenseServer
    {
        // Contains both public and private key. This must stay secret!
        private readonly string _keyPair;

        private readonly Signer _signer = new Signer();

        public LicenseServer()
        {
            // Create demo key pair
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                _keyPair = rsa.ToXmlString(true);
                PublicKey = rsa.ToXmlString(false);
            }
        }    

        public string PublicKey
        {
            get;
        }

        public LicenseKey GetKey(string customerName)
        {
            LicenseKey key = new LicenseKey(new License(customerName, true, false));
            key.Signature = _signer.CreateSignature(key, _keyPair);

            return key;
        }
    }

    public class LicenseKey
    {
        public LicenseKey(License license)
        {
            License = license;
        }

        public License License
        {
            get;
            set;
        }

        public byte[] Signature
        {
            get;
            set;
        }
    }

    public class License
    {
        public License(string customerName, bool featureA, bool featureB)
        {
            CustomerName = customerName;
            FeatureA = featureA;
            FeatureB = featureB;
        }

        public string CustomerName
        {
            get;
            set;
        }

        public bool FeatureA
        {
            get;
            set;
        }

        public bool FeatureB
        {
            get;
            set;
        }
    }

    public class Signer
    {
        public byte[] CreateSignature(LicenseKey key, string privateKey)
        {
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(privateKey);
                return rsa.SignData(ComputeHash(key), CryptoConfig.MapNameToOID("SHA256"));
            }
        }

        public bool VerifySignature(LicenseKey key, string publicKey)
        {
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(publicKey);
                return rsa.VerifyData(ComputeHash(key), CryptoConfig.MapNameToOID("SHA256"), key.Signature);
            }
        }

        private static byte[] ComputeHash(LicenseKey key)
        {
            // Create a hash from the given key. 
            // For demo purposes I'm using a very simple string concatenation of the relevant properties.

            string simplifiedHash = string.Concat(key.License.CustomerName, key.License.FeatureA, key.License.FeatureB);
            return Encoding.UTF8.GetBytes(simplifiedHash);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM