【问题标题】:RSA Encryption and Decryption with X509certificate2使用 X509certificate2 进行 RSA 加密和解密
【发布时间】:2017-07-02 18:35:47
【问题描述】:

那么,接下来我需要的是:

  1. 为开发创建证书,为客户端获取一份,为服务器获取一份
  2. 通过从客户端编码的 API 检索密码并在服务器上对其进行解码

现在,我设法在this link 之后创建了证书。那里的女孩一步一步地说明了如何获得自签名证书,将它们存放在商店等......现在,我遇到问题的部分:

我已设法使用此代码加密我的数据:

public static string Encrypt(string stringForEncription, string PathToPrivateKey)
    {
        X509Certificate2 myCertificate;
        try
        {
            myCertificate = new X509Certificate2(PathToPrivateKey, "Test123");
        }
        catch (Exception e)
        {
            throw new CryptographicException("Unable to open key file.");
        }

        RSACryptoServiceProvider rsaObj;
        if (myCertificate.HasPrivateKey)
        {
            rsaObj = (RSACryptoServiceProvider)myCertificate.PrivateKey;
        }
        else
            throw new CryptographicException("Private key not contained within certificate.");

        if (rsaObj == null)
            return String.Empty;

        byte[] decryptedBytes;
        byte[] array = Encoding.UTF8.GetBytes(stringForEncription);
        try
        {
            decryptedBytes = rsaObj.Encrypt(array, false);
            //decryptedBytes = rsaObj.Encrypt(Convert.FromBase64String(Base64EncryptedData), false);
        }
        catch (Exception e)
        {
            throw new CryptographicException("Unable to encrypt data.");
        }

        //    Check to make sure we decrpyted the string 
        if (decryptedBytes.Length == 0)
            return String.Empty;
        else
            return System.Text.Encoding.UTF8.GetString(decryptedBytes);
    }

对于 PathToPrivate 密钥变量,我使用的是客户端 ClientCert.pfx 的路径。我不知道我是否应该使用任何其他,但这里是包含我制作的所有证书的文件夹的快照:

现在,为了解密,我使用下一个代码:

 public static string DecryptEncryptedData(string Base64EncryptedData, string PathToPrivateKey)
    {
        X509Certificate2 myCertificate;
        try
        {
            myCertificate = new X509Certificate2(PathToPrivateKey, "Test123");
        }
        catch (Exception e)
        {
            throw new CryptographicException("Unable to open key file.");
        }

        RSACryptoServiceProvider rsaObj;
        if (myCertificate.HasPrivateKey)
        {
            rsaObj = (RSACryptoServiceProvider)myCertificate.PrivateKey;
        }
        else
            throw new CryptographicException("Private key not contained within certificate.");

        if (rsaObj == null)
            return String.Empty;

        byte[] decryptedBytes;
        try
        {
            decryptedBytes = rsaObj.Decrypt(Convert.FromBase64String(Base64EncryptedData), false);
        }
        catch (Exception e)
        {
            throw new CryptographicException("Unable to decrypt data.");
        }

        //    Check to make sure we decrpyted the string 
        if (decryptedBytes.Length == 0)
            return String.Empty;
        else
            return System.Text.Encoding.UTF8.GetString(decryptedBytes);
    }

无论我尝试做什么,它都会给我一个例外:

{"The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. "}

真的很感激有人帮助我。

【问题讨论】:

  • @KayLee 试过了,不工作,证书没问题,密钥在那里,我认为问题在于转换为 Base64String 和从 Base64String
  • 尝试测试 DecryptEncryptedData("hello", string PathToPrivateKey);也许,根据我的经验,会显示相同的异常消息。这意味着参数格式不正确(未正确加密)。希望这能提供一些线索。我确信这完全是关于字节、base64string、decryptedplainstring 的格式。仔细分析一些像MSDN这样的示例博客,并不难。
  • 我会在检查完我的代码后明天早上回来。这是深夜。
  • @KayLee 好的,谢谢!
  • 你能用 Encrypt 方法返回的字符串更新你的问题吗?我的意思是您也尝试解密的字符串。从客户端编码是什么意思?如果您不限制用户,黑人用户可能会创建他们的登录名、密码并连接到 Sever。

标签: c# security encryption rsa x509certificate2


【解决方案1】:

您收到错误的原因是您尝试从一个实际上不是 base-64 字符串的值Convert.FromBase64String 的字符串。

加密数据后,您应该将字节数组转换为 base-64 字符串。 为此使用Convert.ToBase64String

return Convert.ToBase64String(decryptedBytes);

然后您的解密行将起作用:

decryptedBytes = rsaObj.Decrypt(Convert.FromBase64String(Base64EncryptedData), false);

【讨论】:

  • Convert.ToBase64String(stringForEncription);返回字符串,而不是 byte[],有什么建议吗?
  • 好的,明白你的意思,我返回了 Convert.ToBase64String(decryptedBytes);之后,在 decrtypt 方法中,我得到:{“参数不正确。\r\n”}
  • 尝试 {decryptedBytes = rsaObj.Decrypt(Convert.FromBase64String(Base64EncryptedData), false); } catch (Exception e) { throw new CryptographicException("无法解密数据。"); }
【解决方案2】:

这不是您可能期望的确切答案,但我写在这里,因为它作为评论太长了。

我认为解密本身完全没有问题(我发现你的代码示例博客使用 php 加密)这就是为什么我评论说我对作为解密目标的加密字符串感到好奇。

几个月来我也一直在努力理解安全性,现在我同时使用对称 (AES) 和非对称 (RSA)。理解真的很重要,每个人都需要时间..

RSA 是非对称且单向的,这意味着加密只能通过公钥完成,而解密只能通过私钥完成。 您在加密方法中使用了私钥,它似乎只是从解密中复制的。

Zesty 的答案仅在格式方面是正确的。您还需要了解格式。我们需要 Convert.ToBase64String 和 Convert.FromBase64String 在从字节到 base64string 的加密和解密中,反之亦然。然而,这个 base64string 不仅像 'hello' 一样简单,而且 'SABlAGwAbABvACAAVwBvAHIAbABkAA==' 如您所见here

我强烈建议使用像blog这样的完整解决方案(不是像php加密那样的一半),这样加密和解密就可以和谐了。

正如我上次评论的那样,如果从客户端进行加密并且您不仅拥有良好的用户,那么您需要考虑如何防止黑用户。

我希望我的经验有助于理解最重要的安全性。

【讨论】:

    猜你喜欢
    • 2012-04-07
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 2014-12-13
    • 2017-05-24
    相关资源
    最近更新 更多