如何使用公钥密码术加密字符串

亚力山大

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

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?♠→☻►♦;♂?♠♂♠?♠

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

亚力山大

注意:我更新了此答案。请向下滚动至该更新,以了解应如何实际实施该更新,因为此第一种方法不是进行RSA加密的正确方法。

我可以想到的一种方法是这样的(但可能不符合标准),而且请注意,这不能填充:

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

这有可能成为跨平台的,因为您可以选择使用其他数据类型来表示e或n,并将其传递给这样的C#后端服务。这是一个测试:

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加密的正确方法:

  • 将您的字符串转换为BigInteger数据类型。
  • 确保您的整数小于您为算法计算出的n的值,否则将无法对其解密。
  • 加密整数。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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用给定的RSA公钥OpenSSL加密字符串

来自分类Dev

从Angular密码术解密AES字符串的Java方法

来自分类Dev

如何使用公钥字符串创建OpenSSL :: PKey?

来自分类Dev

使用Objective C在iOS中使用公钥加密或签名字符串

来自分类Dev

Java-使用现有的公钥文件加密字符串

来自分类Dev

Android Java-使用RSA公钥.PEM加密字符串

来自分类Dev

无法在量角器中使用公钥加密字符串

来自分类Dev

使Android应用程序使用FIPS 140-2加密密码术

来自分类Dev

椭圆曲线密码术:在Eclipse Android中使用NFC发送加密的消息

来自分类Dev

分别使用椭圆曲线密码术加密和解密文本消息

来自分类Dev

用于存储敏感数据的加密或密码术

来自分类Dev

GPG密码与公钥加密

来自分类Dev

使用字符串中的公钥验证JWT

来自分类Dev

使用字符串生成公钥和私钥

来自分类Dev

如何使用Bouncycastle Java将PGP公钥存储和读取为字符串?

来自分类Dev

从字符串创建RSA公钥

来自分类Dev

用公钥加密密码(RSA)

来自分类Dev

如何使用GnuPG加密字符串?

来自分类Dev

快速使用公钥加密

来自分类Dev

密码术的排列和排列

来自分类Dev

从VBA调用.NET密码术

来自分类Dev

从VBA调用.NET密码术

来自分类Dev

在ruby中用密码加密字符串

来自分类Dev

在ruby中用密码加密字符串

来自分类Dev

仅使用Java中的密码加密来加密字符串字符

来自分类Dev

仅使用Java中的密码加密来加密字符串字符

来自分类Dev

如何使用 Fernet 加密对字符串变量进行加密

来自分类Dev

JSch addIdentity-如何传递私钥和公钥字符串与文件路径

来自分类Dev

如何在Ruby中使用PKI(公钥/私钥)加密?

Related 相关文章

热门标签

归档