Для операций RSA используются разные ключи.
- Encrypt - открытый ключ (public key);
- Verify - открытый ключ (public key);
- Decrypt - закрытый ключ (private key);
- Sign - закрытый ключ (private key).
В примере на Java генерируется новый закрытый ключ:
PrivateKey generatePrivate = KeyFactory.getInstance("RSA").generatePrivate(new RSAPrivateKeySpec(new BigInteger("test1", 16), new BigInteger("test2", 16)));
А в примере на С# ключ состоит из Modulus и Exponent:
RSAParameters rsaparam = new RSAParameters();
rsaparam.Modulus = StringToByteArray(modF);
rsaparam.Exponent = StringToByteArray(privExpF);
Насколько я понял, для публичного ключа этого достаточно. А закрытому нужно указать все параметры:
Modulus
,
Exponent
,
D
- закрытый Exponent,
Q
, P
- пара ключей, P * Q = Modulus,
DP
, DQ
, InverseQ
- промежуточные значения для увеличения производительности дешифровки.
Пример работы RSA в C# (.NET 6):
using System.Security.Cryptography;
using System.Text;
// генерируем параметры
RSAParameters privateKey;
RSAParameters publicKey;
RSAEncryptionPadding padding = RSAEncryptionPadding.Pkcs1;
using (RSACryptoServiceProvider provider = new(4096))
{
privateKey = provider.ExportParameters(true);
publicKey = provider.ExportParameters(false);
}
// шифрование
string message = "{ Some example of data }";
Console.WriteLine("Data: " + message);
byte[] data = Encoding.UTF8.GetBytes(message);
byte[] encrypted;
using (RSACryptoServiceProvider provider = new())
{
provider.ImportParameters(publicKey);
encrypted = provider.Encrypt(data, padding);
}
Console.WriteLine("Encrypted: " + string.Join("-", encrypted.Select(x => x.ToString("X"))));
// дешифровка
byte[] decrypted;
using (RSACryptoServiceProvider provider = new())
{
provider.ImportParameters(privateKey);
publicKey = provider.ExportParameters(false);
decrypted = provider.Decrypt(encrypted, padding);
}
Console.WriteLine("Decrypted: " + Encoding.UTF8.GetString(decrypted));
// пример по modulus, exponent
byte[] publicModulus = publicKey.Modulus;
byte[] publicExponent = publicKey.Exponent;
RSAParameters test = new RSAParameters() { Modulus= publicModulus, Exponent = publicExponent };
using (RSACryptoServiceProvider provider = new())
{
provider.ImportParameters(test);
encrypted = provider.Encrypt(data, padding);
}
// дешифруем вручную
// источник https://stackoverflow.com/questions/15702718/public-key-encryption-with-rsacryptoserviceprovider
byte[] privateModulus = privateKey.Modulus.Reverse().Concat(new byte[] { 0 }).ToArray();
byte[] privateExponent = privateKey.D.Reverse().Concat(new byte[] { 0 }).ToArray();
byte[] encConv = encrypted.Reverse().Concat(new byte[] { 0 }).ToArray();
BigInteger intModulus = new BigInteger(privateModulus);
BigInteger intExponent = new BigInteger(privateExponent);
BigInteger intEncrypted = new BigInteger(encConv);
decrypted = BigInteger.ModPow(intEncrypted, intExponent, intModulus).ToByteArray().Reverse().ToArray();
decrypted = decrypted.SkipWhile(x => x != 0).Skip(1).ToArray();
Console.WriteLine("Decrypted: " + Encoding.UTF8.GetString(decrypted));