如何将一个字符串使用公钥加密加密字符串、如何将、公钥

2023-09-04 22:37:38 作者:痘肤西施

我想实现我自己的RSA加密引擎。鉴于这些 RSA算法值:

I am trying to implement my own RSA encryption engine. Given these RSA algorithm values:

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.

我试图写一个方法,以每个字节的字符串加密,并返回一个加密的字符串:

I am trying to write a method to encrypt each byte in a string and return back an encrypted string:

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(字节[我],E,N)可能过大而无法转化为字节空间;它可能会导致超过8位大小的值。你如何解决这个问题,得到的同时仍然能够字节的字符串加密解密回普通字符串?

The obvious issue here is that BigInteger.ModPow(bytes[i], e, n) may be too large to fit into a byte-space; it could result in values over 8 bits in size. How do you get around this issue while still being able to decrypt an encrypted string of bytes back into a regular string?

更新:即使从byte []的加密为byte [],你到达那里加密使用RSA算法的字节超出一个字节的大小限制的情况:

Update: Even encrypting from byte[] to byte[], you reach a case where encrypting that byte using the RSA algorithm goes beyond the size limit of a byte:

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;
}

更新:我的问题是,加密会造成更多的比初始输入字符串字节有:

Update: My issue is that encryption would cause a greater number of bytes than the initial input string had:

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;
}

如果你运行此code是这样的:

If you ran this code like this:

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

输出结果是这样的:

The output would be this:

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

显然,输出不是原始字符串,因为我不能只是尝试解密每个字节的时间,因为有时两个或多个字节的CYPHER文本重新present有一个整数的,我需要的价值解密回原始字符串的一个字节...所以我想知道是什么标准处理机制,这是。

Obviously, the output is not the original string because I can't just try decrypting each byte at a time, since sometimes two or more bytes of the cypher-text represent the value of one integer that I need to decrypt back to one byte of the original string...so I want to know what the standard mechanism for handling this is.

推荐答案

注意:我更新了这个答案。请向下滚动到应该如何真正实施,因为这样做的这第一条路是不是做RSA加密的正确方法的更新。

我觉得这样做是这样的(但可能不符合标准),而且,要注意的一种方式,这并不垫:

One way I can think to do it is like this (but may not be compliant to standards), and also, note this does not pad:

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 + 1);
        (new byte[] { (byte)(result.Length) }).CopyTo(returnBytes, preSize);
        result.CopyTo(returnBytes, preSize + 1);
    }
    return returnBytes;
}

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

这是具有跨平台的潜力,因为你使用的是不同的数据类型来重新present E或n和它传递给这样的一个C#后端服务的选项。下面是测试:

This has the potential of being cross-platform because you have the option of using a different datatype to represent e or n and pass it to a C# back-end service like that. Here is a test:

string stringToEncrypt = "Mary had a little lamb.";
Console.WriteLine("Encrypting the string: {0}", stringToEncrypt);
byte[] encryptedBytes = engine.Encrypt(stringToEncrypt, Encoding.UTF8);
Console.WriteLine("Encrypted text: {0}", Encoding.UTF8.GetString(encryptedBytes));
Console.WriteLine("Decrypted text: {0}", engine.Decrypt(encryptedBytes, Encoding.UTF8));

输出:

Encrypting the string: Mary had a little lamb.
Encrypted text: ☻6☻1♦☻j☻☻&♀☻g♦☻t☻☻1♦☻?  ☻g♦☻1♦☻g♦☻?♥☻?☻☻7☺☻7☺☻?♥☻?♂☻g♦☻?♥☻1♦☻$☺☻
c       ☻?☻
Decrypted text: Mary had a little lamb.

更新:一切我前面说的是RSA的实现完全错误的。错,错,错!这是做的RSA加密的正确方式:

Update: Everything I said earlier is completely wrong in the implementation of RSA. Wrong, wrong, wrong! This is the correct way to do RSA encryption:

将您的字符串为BigInteger类型。 确保您的整数比为n的,你已经计算出你的算法,数值越小,否则你将无法正是DeCypher它。 加密整数。 RSA工作仅整数加密。这是显而易见的。 从加密的整数解密。 在我不禁纳闷了BigInteger类的加密大部分是创建。

作为一个例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace BytePadder
{
    class Program
    {
        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(string[] args)
        {
            // ---------------------- RSA Example I ----------------------
            // Shows how an integer gets encrypted and decrypted.
            BigInteger integer = 1000;
            BigInteger encryptedInteger = Encrypt(integer);
            Console.WriteLine("Encrypted Integer: {0}", encryptedInteger);
            BigInteger decryptedInteger = Decrypt(encryptedInteger);
            Console.WriteLine("Decrypted Integer: {0}", decryptedInteger);
            // --------------------- RSA Example II ----------------------
            // Shows how a string gets encrypted and decrypted.
            string unencryptedString = "A";
            BigInteger integer2 = new BigInteger(Encoding.UTF8.GetBytes(unencryptedString));
            Console.WriteLine("String as Integer: {0}", integer2);
            BigInteger encryptedInteger2 = Encrypt(integer2);
            Console.WriteLine("String as Encrypted Integer: {0}", encryptedInteger2);
            BigInteger decryptedInteger2 = Decrypt(encryptedInteger2);
            Console.WriteLine("String as Decrypted Integer: {0}", decryptedInteger2);
            string decryptedIntegerAsString = Encoding.UTF8.GetString(decryptedInteger2.ToByteArray());
            Console.WriteLine("Decrypted Integer as String: {0}", decryptedIntegerAsString);
            Console.ReadLine();
        }

        static BigInteger Encrypt(BigInteger integer)
        {
            if (integer < n)
            {
                return BigInteger.ModPow(integer, e, n);
            }
            throw new Exception("The integer must be less than the value of n in order to be decypherable!");
        }

        static BigInteger Decrypt(BigInteger integer)
        {
            return BigInteger.ModPow(integer, d, n);
        }
    }
}

输出示例:

Encrypted Integer: 1989
Decrypted Integer: 1000
String as Integer: 65
String as Encrypted Integer: 1834
String as Decrypted Integer: 65
Decrypted Integer as String: A
 
精彩推荐
图片推荐