适用于客户端的App.config的WCF加密解决方案?

时间:2009-05-13 00:04:43

标签: .net wcf web-services

我有一个桌面应用程序,其中包含App.config(发布时为program.exe.config),其中包含明确可见的元素,用于定义我的WCF端点和WCF实现。

我希望从用户眼中隐藏这一点,从简单的黑客攻击,查看和更改。

我应该: -

  1. 以编程方式在代码中创建和存储我的WCF端点和绑定配置。或;
  2. 在App.config上实现一些保护方案(如果是,如何,如何),从公共视图中有效地混淆/加密这些元素,但我的代码可以理解?
  3. 我已经利用.NET Reactor来模糊和保护我的程序免受反射技术的影响。

    更新13-May-09 3:32 GMT + 10 好吧,我设法加密system.serviceModel但是当应用程序在抛出异常时被证明无法使用它(System.TypeInitializationException:'System.ServiceModel.DiagnosticUtility'的类型初始值设定器引发异常。)

      <system.serviceModel>
        <!-- [bindings] -->
        <bindings configProtectionProvider="DPAPIProtection">
          <EncryptedData>
            <CipherData>
              <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+...
    

    所以有了这个想法。我要么放弃这个想法,要么在加密背后的代码中设置我的端点
    是不是其他人担心他们的端点地址在config ???

    中清晰可见

4 个答案:

答案 0 :(得分:4)

  

我希望从用户眼中隐藏这一点,从简单的黑客攻击,查看和更改。

你真的无法防范这种情况,因为任何想要弄清楚它在做什么的人只是在WCF Endpoint类构造函数上设置一个断点然后点击“go”。没有多少混淆会帮助你。

答案 1 :(得分:3)

保护它免受更改更容易保护它免受查看。

如果您只是担心改变/黑客攻击,您可以使用公钥在包含不可更改的WCF设置的XML元素上计算数字签名。如果客户更改了任何内容,则sig将不匹配。

我不知道保护它免受观看的好方法,因为一个坚定的人将能够找到你在WCF中所做的事情(正如之前的海报指出的那样)。你可能会让它变得更加困难,但这并不妨碍某人查看或学习这些信息。

<强>更新

您需要使用自己的RSA私钥进行签名。也许您已经拥有RSA密钥对。如果没有,您可以生成一次密钥对,以进行签名。像这样。

        int keySize = 1024; // you choose
        byte[] key = Keys.GenerateKeyPair(keySize);

        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
        rsaKey.ImportCspBlob(key);

完成后,您可以导出并保存它。为了您自己的使用,签名,您需要私钥。要进行验证,应用会使用公钥。这就是你得到它们的方式。

        string PublicKeyXml = rsaKey.ToXmlString(false);
        string PrivateKeyXml = rsaKey.ToXmlString(true);

存储这些。如果您想使用相同的私钥再次签名,请使用FromXmlString()方法获取RSA CSP,并传递PrivateKeyXml。如果要验证,请使用传递PublicKeyXml的FromXmlString()。

获得密钥和XML后,您可以进行签名。在打包和部署期间,当您创建并完成配置时,会发生这种情况。

    // Sign an XML file. 
    // This document cannot be verified unless the verifying 
    // code has the key with which it was signed.
    public static void SignXml(System.Xml.XmlDocument Doc, RSA Key)
    {
        // Check arguments.
        if (Doc == null)
            throw new ArgumentException("Doc");
        if (Key == null)
            throw new ArgumentException("Key");

        // Create a SignedXml object.
        System.Security.Cryptography.Xml.SignedXml signedXml = new SignedXml(Doc);

        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;

        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "";

        // Add an enveloped transformation to the reference.
        var env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);

        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);

        // Compute the signature.
        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
    }

然后,将签名的XML嵌入到app.config中或作为应用程序中的字符串嵌入,或者其他任何内容。当应用程序运行时,您可以使用公钥blob在运行时验证签名。

        // Verify the signature of the signed XML.
        RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
        rsaCsp.FromXmlString(PublicKeyXml);

        bool isValid = VerifyXml(xmlDoc, rsaCsp);

以下是一些进行签名验证的代码:

    // Verify the signature of an XML file against an asymmetric 
    // algorithm and return the result.
    public Boolean VerifyXml(XmlDocument Doc, RSA Key)
    {
        // Check arguments.
        if (Doc == null)
            throw new ArgumentException("Doc");
        if (Key == null)
            throw new ArgumentException("Key");

        // Create a new SignedXml object and pass it
        // the XML document class.
        System.Security.Cryptography.Xml.SignedXml signedXml = new SignedXml(Doc);

        // Find the "Signature" node and create a new XmlNodeList object.
        XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

        // Throw an exception if no signature was found.
        if (nodeList.Count <= 0)
        {
            throw new CryptographicException("Verification failed: No Signature was found in the document.");
        }

        // Though it is possible to have multiple signatures on 
        // an XML document, this app only supports one signature for
        // the entire XML document.  Throw an exception 
        // if more than one signature was found.
        if (nodeList.Count >= 2)
        {
            throw new CryptographicException("Verification failed: More that one signature was found for the document.");
        }

        // Load the first <signature> node.  
        signedXml.LoadXml((XmlElement)nodeList[0]);

        // Check the signature and return the result.
        return signedXml.CheckSignature(Key);
    }

要测试您的签名和验证是否确实有效,请修改已签名的签名或xml内容。您应该看到验证失败。在验证失败的情况下,您的应用可能会抛出或退出等等。

答案 2 :(得分:2)

我猜选项1可能是你最好的选择。也就是说,我确实想知道它是否值得(假设您在配置文件中没有任何真正敏感的内容,如凭据或其他任何内容)。我提出这个问题的原因是,如果你担心你的端点URL等等,那么任何拥有非常基本工具的人都可以使用网络协议分析器在几秒钟内解决这个问题。

答案 3 :(得分:2)

您可以尝试在.NET中使用protected configuration,但这并不是很简单。您需要加密客户端计算机上的配置文件,因为受保护的配置提供程序可能会生成特定于计算机的加密数据。换句话说,如果您加密计算机或构建计算机上的配置部分,则可能无法在客户端计算机上对其进行解密。您还可以将加密密钥导出并导入到客户端计算机上。因此,在安装过程中,您必须在客户端计算机上安装密钥并使用该密钥加密配置部分时执行某些操作。看看Implementing Protected Configuration With Windows Apps。正如您所看到的,这实际上不是一个非常简单和干净的解决方案,并且在部署方面增加了复杂性。

另一方面,以编程方式在客户端配置WCF很容易。您可以在代码中设置绑定和端点。如果您仍希望通过配置保留一些灵活性以将客户端定向到不使用新构建的其他URL,您可能希望将地址或URL保留在配置文件中。我认为这是最好的方法,因为我认为一旦测试和部署应用程序,您的绑定和端点就不会发生变化。但是你更了解你的要求:-)我想说不要过度工作或者将重型和昂贵的解决方案应用于可能不是真正关注的问题。