我正在尝试实现自己的RSA加密引擎。给定这些RSA algorithm值:

p = 61. // A prime number.
q = 53. // Also a prime number.
n = 3233. // p * q.
totient = 3120. // (p - 1) * (q - 1)
e = 991. // Co-prime to the totient (co-prime to 3120).
d = 1231. // d * e = 1219921, which is equal to the relation where 1 + k * totient = 1219921 when k = 391.


我正在尝试编写一种方法来加密字符串中的每个字节并返回加密的字符串:

public string Encrypt(string m, Encoding encoding)
{
    byte[] bytes = encoding.GetBytes(m);
    for (int i = 0; i < bytes.Length; i++)
    {
        bytes[i] = (byte)BigInteger.ModPow(bytes[i], e, n);
    }
    string encryptedString = encoding.GetString(bytes);
    Console.WriteLine("Encrypted {0} as {1}.", m, encryptedString);
    return encryptedString;
}


这里很明显的问题是BigInteger.ModPow(bytes[i], e, n)可能太大而无法容纳字节空间。可能导致值超过8位。如何解决此问题,同时仍然能够将加密的字节字符串解密回常规字符串?

更新:即使从byte []到byte []进行加密,您也会遇到以下情况:使用RSA算法加密该字节超出了字节的大小限制:

public byte[] Encrypt(string m, Encoding encoding)
{
    byte[] bytes = encoding.GetBytes(m);
    for (int i = 0; i < bytes.Length; i++)
    {
        bytes[i] = (byte)BigInteger.ModPow(bytes[i], e, n);
    }
    return bytes;
}


更新:我的问题是,加密将导致比初始输入字符串更多的字节数:

public byte[] Encrypt(string m, Encoding encoding)
{
    byte[] bytes = encoding.GetBytes(m);
    byte[] returnBytes = new byte[0];
    for (int i = 0; i < bytes.Length; i++)
    {
        byte[] result = BigInteger.ModPow(bytes[i], (BigInteger)e, n).ToByteArray();
        int preSize = returnBytes.Length;
        Array.Resize(ref returnBytes, returnBytes.Length + result.Length);
        result.CopyTo(returnBytes, preSize);
    }
    return returnBytes;
}

public string Decrypt(byte[] c, Encoding encoding)
{
    byte[] returnBytes = new byte[0];
    for (int i = 0; i < c.Length; i++)
    {
        byte[] result = BigInteger.ModPow(c[i], d, n).ToByteArray();
        int preSize = returnBytes.Length;
        Array.Resize(ref returnBytes, returnBytes.Length + result.Length);
        result.CopyTo(returnBytes, preSize);
    }
    string decryptedString = encoding.GetString(returnBytes);
    return decryptedString;
}


如果您运行如下代码:

byte[] encryptedBytes = engine.Encrypt("Hello, world.", Encoding.UTF8);
Console.WriteLine(engine.Decrypt(encryptedBytes, Encoding.UTF8));


输出将是这样的:

?♥D
?♥→☻►♦→☻►♦oD♦8? ?♠oj?♠→☻►♦;♂?♠♂♠?♠


显然,输出不是原始字符串,因为我不能一次尝试解密每个字节,因为有时两个或多个字节的密文代表一个整数的值,我需要将其解密回一个字节。原始字符串...所以我想知道处理这个问题的标准机制是什么。

最佳答案

您用于加密和解密每个字节的基本代码(对ModPow的调用)正在工作,但是您将不恰当地“拆分消息并加密每个片段”。

为了证明ModPow部分-即数学-很好,这是基于您的代码,将string加密为BigInteger[]并重新加密:

using System;
using System.Linq;
using System.Numerics;
using System.Text;

class Test
{
    const int p = 61;
    const int q = 53;
    const int n = 3233;
    const int totient = 3120;
    const int e = 991;
    const int d = 1231;

    static void Main()
    {
        var encrypted = Encrypt("Hello, world.", Encoding.UTF8);
        var decrypted = Decrypt(encrypted, Encoding.UTF8);
        Console.WriteLine(decrypted);
    }

    static BigInteger[] Encrypt(string text, Encoding encoding)
    {
        byte[] bytes = encoding.GetBytes(text);
        return bytes.Select(b => BigInteger.ModPow(b, (BigInteger)e, n))
                    .ToArray();
    }

    static string Decrypt(BigInteger[] encrypted, Encoding encoding)
    {
        byte[] bytes = encrypted.Select(bi => (byte) BigInteger.ModPow(bi, d, n))
                                .ToArray();
        return encoding.GetString(bytes);
    }
}


接下来,您需要阅读更多有关如何使用RSA将byte[]加密为另一个byte[]的信息,包括所有不同的填充方案等。除了在每个字节上调用ModPow之外,还有很多其他功能。

但是重申一下,您不应该这样做来结束生产RSA实施。做到这一点而没有任何安全漏洞的机会确实很小。这样做是出于学术兴趣,可以学习更多有关密码学的原理,但将真正的实现方法留给专家是可以的。 (我与该领域的专家相去甚远-无法开始实施自己的加密...)

关于c# - 如何使用公钥密码术加密字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24267332/

10-17 00:02