限制是什么对于可以使用rsacryptoserviceprovider(C#)加密/解密的各种字符串?

发布于 2025-01-24 16:02:20 字数 6542 浏览 3 评论 0 原文

以下是我对RSA加密和解密方法的实现,我基于Microsoft文档。

public string Encrypt(string plainText)
{
    rsaCsp.ImportParameters(publicKey);

    byte[] data = Encoding.UTF8.GetBytes(plainText);
    byte[] cypher = rsaCsp.Encrypt(data, fOAEP: true);

    string cypherText = Convert.ToBase64String(cypher);

    return cypherText;
}

public string Decrypt(string cypherText)
{
    rsaCsp.ImportParameters(privateKey);

    byte[] data = Convert.FromBase64String(cypherText);
    byte[] decrypted = rsaCsp.Decrypt(data, fOAEP: true);

    string plainText = Encoding.UTF8.GetString(decrypted);

    return plainText;
}

我正在注入密钥和提供商,以便我可以重复使用特定的密钥,以便我什至可以解密程序的其他执行中加密的字符串。 (例如:我在测试中加密并保存在数据库中,在另一个测试中,我在数据库中搜索了加密的字符串和解密)。如果我允许自动生成公共钥匙和私钥,则不可能。

private readonly RSAParameters privateKey;
private readonly RSAParameters publicKey;

private readonly RSACryptoServiceProvider rsaCsp;

public RsaCryptoService(
    RSACryptoServiceProvider rsaCsp,
    RSAParameters privateKey,
    RSAParameters publicKey)
{
    this.rsaCsp = rsaCsp;
    this.privateKey = privateKey;
    this.publicKey = publicKey;
}

以下是依赖关系的构造:

public static void InjectRsaCryptoService(this IServiceCollection services, string userName = "default", int keySize = 2048)
        {
            Services = services;

            RsaKeyPair rsaKeyPair = SecuritySettings.RsaKeys.SingleOrDefault(p => p.UserName == userName);
            if (rsaKeyPair == null)
                throw new lsilvpin_securityException(
                    $"O usuário {userName} não está autorizado a utilizar as ferramentas de segurança.");

            RSAParameters privateKey = rsaKeyPair.PrivateKey.AsParameter();
            RSAParameters publicKey = rsaKeyPair.PublicKey.AsParameter();

            RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(keySize);

            rsaCsp.ImportParameters(publicKey);
            rsaCsp.ImportParameters(privateKey);

            Services.AddTransient(sp =>
            {
                IRsaCryptoService rsa = new RsaCryptoService(rsaCsp, privateKey, publicKey);

                return rsa;
            });
        }

”在此处输入图像描述

一开始我认为它工作正常,但是要安全起见,我决定进行性能测试,将随机字符串发送到被加密和解密。

这是我的性能测试:

[Fact]
public void TestRsaCryptionPerformance()
{
    for (int i = 0; i < 1000; i++)
    {
        var plainText = RandomWordGenerator.Next(new RandomWordParameters(WordMaxLength: 495)) + "@eA8";

        IRsaCryptoService rsa = Services
        .BuildServiceProvider()
        .GetRequiredService<IRsaCryptoService>();

        string publicKey = rsa.GetPublicKey();
        string cypherText = rsa.Encrypt(plainText);
        string decrypted = rsa.Decrypt(cypherText);

        Assert.True(!string.IsNullOrWhiteSpace(publicKey));
        Assert.True(!string.IsNullOrWhiteSpace(cypherText));
        Assert.True(!string.IsNullOrWhiteSpace(decrypted));
        Assert.True(plainText.Equals(decrypted));

        Debug.WriteLine($"PublicKey: {publicKey}");
        Debug.WriteLine($"CypherText: {cypherText}");
        Debug.WriteLine($"Decrypted: {decrypted}");
    }
}

“在此处输入图像描述”

我正在使用以下方法生成100至499之间的随机单词:

public static string Next(RandomWordParameters? randomWordParameters = null)
        {
            randomWordParameters ??= new RandomWordParameters();
            if (randomWordParameters.CharLowerBound <= 0 || randomWordParameters.CharUpperBound <= 0)
                throw new RandomGeneratorException("Os limites inferior e superior devem ser positivos.");

            if (randomWordParameters.CharLowerBound >= randomWordParameters.CharUpperBound)
                throw new RandomGeneratorException("O limite inferior deve ser menor do que o limite superior.");

            var rd_char = new Random();
            var rd_length = new Random();
            var wordLength = rd_length.Next(randomWordParameters.WordMinLength, randomWordParameters.WordMaxLength);
            var sb = new StringBuilder();
            int sourceNumber;
            for (int i = 0; i < wordLength; i++)
            {
                sourceNumber = rd_char.Next(randomWordParameters.CharLowerBound, randomWordParameters.CharUpperBound);
                sb.Append(Convert.ToChar(sourceNumber));
            }
            var word = sb.ToString();
            return word;
        }

“在此处输入映像说明”

注意:我使用通过传递33和33和33和33和126 to convert.tochar(int)方法。

当我运行1000个随机单词的循环时,我总是会发现一个引发以下例外的循环:

insenter.cryptography.cryptothrowhelper.windowscryptographicexception:“ comprimentoinválido。” (长度无效)

“在此处进行”

在测试中的字符串:a_bdh [(4/6-9m&gt;,9a_j/^t2gcsxo {{{{ w#j*!r! :nei7!vtfm8w.5q1,d?i9dr&gt; u {m0,$ yxp1cd] mc(gnd $){x [x [x [@l9c7e&gt; z() kckc%usv'] 958^} a2p(shun'= vr

? “ https://i.sstatic.net/lhfl2.png” rel =“ nofollow noreferrer”>

想在我正在实现的系统上使用RSA加密,但是任何人都不知道该问题来自何处?

我 密码模拟长度长度约为20,从弱到非常强的密码)

Following is my implementation of Rsa encryption and decryption methods, to do it I based myself on microsoft documentation.

https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rsacryptoserviceprovider?redirectedfrom=MSDN&view=net-6.0

public string Encrypt(string plainText)
{
    rsaCsp.ImportParameters(publicKey);

    byte[] data = Encoding.UTF8.GetBytes(plainText);
    byte[] cypher = rsaCsp.Encrypt(data, fOAEP: true);

    string cypherText = Convert.ToBase64String(cypher);

    return cypherText;
}

enter image description here

public string Decrypt(string cypherText)
{
    rsaCsp.ImportParameters(privateKey);

    byte[] data = Convert.FromBase64String(cypherText);
    byte[] decrypted = rsaCsp.Decrypt(data, fOAEP: true);

    string plainText = Encoding.UTF8.GetString(decrypted);

    return plainText;
}

enter image description here

I am injecting the keys and the provider so that I can reuse specific keys, so that I can even decrypt strings that were encrypted in other executions of the program. (Example: I encrypt in a test and save in a database and in another test I search in the database the encrypted string and decrypt). If I allowed public and private keys to be generated automatically this behavior would not be possible.

private readonly RSAParameters privateKey;
private readonly RSAParameters publicKey;

private readonly RSACryptoServiceProvider rsaCsp;

public RsaCryptoService(
    RSACryptoServiceProvider rsaCsp,
    RSAParameters privateKey,
    RSAParameters publicKey)
{
    this.rsaCsp = rsaCsp;
    this.privateKey = privateKey;
    this.publicKey = publicKey;
}

enter image description here

Below is the construction of the dependencies:

public static void InjectRsaCryptoService(this IServiceCollection services, string userName = "default", int keySize = 2048)
        {
            Services = services;

            RsaKeyPair rsaKeyPair = SecuritySettings.RsaKeys.SingleOrDefault(p => p.UserName == userName);
            if (rsaKeyPair == null)
                throw new lsilvpin_securityException(
                    
quot;O usuário {userName} não está autorizado a utilizar as ferramentas de segurança.");

            RSAParameters privateKey = rsaKeyPair.PrivateKey.AsParameter();
            RSAParameters publicKey = rsaKeyPair.PublicKey.AsParameter();

            RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(keySize);

            rsaCsp.ImportParameters(publicKey);
            rsaCsp.ImportParameters(privateKey);

            Services.AddTransient(sp =>
            {
                IRsaCryptoService rsa = new RsaCryptoService(rsaCsp, privateKey, publicKey);

                return rsa;
            });
        }

enter image description here

At first I thought it was working fine, but to be safe, I decided to do a performance test, sending random strings to be encrypted and decrypted.

Here's my performance test:

[Fact]
public void TestRsaCryptionPerformance()
{
    for (int i = 0; i < 1000; i++)
    {
        var plainText = RandomWordGenerator.Next(new RandomWordParameters(WordMaxLength: 495)) + "@eA8";

        IRsaCryptoService rsa = Services
        .BuildServiceProvider()
        .GetRequiredService<IRsaCryptoService>();

        string publicKey = rsa.GetPublicKey();
        string cypherText = rsa.Encrypt(plainText);
        string decrypted = rsa.Decrypt(cypherText);

        Assert.True(!string.IsNullOrWhiteSpace(publicKey));
        Assert.True(!string.IsNullOrWhiteSpace(cypherText));
        Assert.True(!string.IsNullOrWhiteSpace(decrypted));
        Assert.True(plainText.Equals(decrypted));

        Debug.WriteLine(
quot;PublicKey: {publicKey}");
        Debug.WriteLine(
quot;CypherText: {cypherText}");
        Debug.WriteLine(
quot;Decrypted: {decrypted}");
    }
}

enter image description here

I'm generating random words of size between 100 and 499 with the following method:

public static string Next(RandomWordParameters? randomWordParameters = null)
        {
            randomWordParameters ??= new RandomWordParameters();
            if (randomWordParameters.CharLowerBound <= 0 || randomWordParameters.CharUpperBound <= 0)
                throw new RandomGeneratorException("Os limites inferior e superior devem ser positivos.");

            if (randomWordParameters.CharLowerBound >= randomWordParameters.CharUpperBound)
                throw new RandomGeneratorException("O limite inferior deve ser menor do que o limite superior.");

            var rd_char = new Random();
            var rd_length = new Random();
            var wordLength = rd_length.Next(randomWordParameters.WordMinLength, randomWordParameters.WordMaxLength);
            var sb = new StringBuilder();
            int sourceNumber;
            for (int i = 0; i < wordLength; i++)
            {
                sourceNumber = rd_char.Next(randomWordParameters.CharLowerBound, randomWordParameters.CharUpperBound);
                sb.Append(Convert.ToChar(sourceNumber));
            }
            var word = sb.ToString();
            return word;
        }

enter image description here

Note: I use characters obtained by passing integers between 33 and 126 to the Convert.ToChar(int) method.

When I run a loop of 1000 random words, I always find one that throws the exception below:

Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'Comprimento inválido.' (Invalid length)

enter image description here

String under test: a_BdH[(4/6-9m>,9a_J/^t2GCsxo{{W#j*!R![h;TMi/42Yw7Z0yWOb3f15&P:NEI7!vTFm8W.5Q1,d?I9DR>u{M0,$YxP1Cd ]MC(gnd$){x[`@L9C7E>z()PS,>w:|?<|j3!KCkC%usV']958^}a2P(SHun'=VR?^qLcj_1nu"UUR|Bu{UlP =mEJ0RIJP#9O$a^g7&I|Q^]_pG0!h}RjiEu_Df8*(@eA8

enter image description here

I want to use RSA encryption on a system I'm implementing, but this test made me unsure. Does anyone see where this problem comes from?

Note: The encrypt/decrypt methods worked perfectly with smaller and simpler strings. (Password simulations up to about 20 in length, from weak to very strong passwords)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风蛊 2025-01-31 16:02:20

根据KlausGütte和Topaco的评论,我对回应感到满意!

问题是由输入字符串的大小引起的,输入的限制是根据Klaus链接的问题的输入的大小,并且此大小取决于Topaco所述的加密密钥的大小!

链接引起澄清的链接: rsacryptoserviceprovider

链接链接到澄清输入尺寸限制: https://crypto.stackexchange.com/questions/42097/what--is-the-maximum-size-size-of-plaint-plaintext-message-for-rsa-rsa-oaep/42100# << /a> 42100

更具体地说:

​img src =“ https://i.sstatic.net/un0an.png” alt =“在此处输入图像说明”>

在我的具体情况下,加密/decrypt方法接受的最大字符串长度为214 (长度)。用100K随机字符串进行测试,并且效果很好!但是,传递字符串大小&gt; = 215已经生成了“不良长度”例外。

长度&lt; = 214

”输入图像说明在此处“

失败

“在此处输入图像说明”

非常感谢您的帮助!

Based on comments from Klaus Gütte and Topaco, I'm satisfied with the response!

The problem is caused by the size of the input string, the limit of the input so is the size of the input according to the question linked by Klaus, and this size depends on the size configured for the encryption key as mentioned by Topaco!

Link to cause clarification: System.Security.Cryptography.CryptographicException : Bad length in RSACryptoserviceProvider

Link to clarify input size limit: https://crypto.stackexchange.com/questions/42097/what-is-the-maximum-size-of-the-plaintext-message-for-rsa-oaep/42100# 42100

More specifically: https://www.rfc-editor.org/rfc/rfc8017#section-7.1.1

Print RSAES-OAEP-ENCRYPT standars

enter image description here

In my specific case, the maximum length of strings accepted by the encrypt/decrypt methods was 214 (Length). Test with 100k random strings and it worked perfectly! However, passing a string size >= 215 already generates the "Bad length" exception.

Success with length <= 214

enter image description here

Fail with 215

enter image description here

Thanks a lot for the help guys!!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文