I need to replicate the functionality of the following JAVA code that receives a string with the exponent and modulus of a public key to generate a public key with said parameters and encrypt a string:
package snippet;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.Security;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
public class Snippet {
public static void main(String ... strings) {
try {
// Needed if you don't have this provider
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//String and received public key example
String ReceivedString = "1234";
String publicRSA = "010001|0097152d7034a8b48383d3dba20c43d049";
EncryptFunc(ReceivedString, publicRSA);
//The result obtained from the ReceivedString and the publicRSA is as follows:
//Result in hex [1234] -> [777786fe162598689a8dc172ed9418cb]
} catch (Exception ex) {
System.out.println("Error: " );
ex.printStackTrace();
}
}
public static String EncryptFunc(String ReceivedString, String clavePublica) throws Exception {
String result = "";
//We separate the received public string into exponent and modulus
//We receive it as "exponent|modulus"
String[] SplitKey = clavePublica.split("\\|");
KeyFactory keyFactory = KeyFactory.getInstance("RSA","BC");
RSAPublicKeySpec ks = new RSAPublicKeySpec(new BigInteger(hex2byte(SplitKey[1])), new BigInteger(hex2byte(SplitKey[0])));
//With these specs, we generate the public key
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(ks);
//We instantiate the cypher, with the EncryptFunc and the obtained public key
Cipher cipher= Cipher.getInstance("RSA/None/NoPadding","BC");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
//We reverse the ReceivedString and encrypt it
String ReceivedStringReverse = reverse(ReceivedString);
byte[] cipherText2 = cipher.doFinal(ReceivedStringReverse.getBytes("UTF8"));
result = byte2hex(cipherText2);
System.out.println("result in hex ["+ReceivedString+"] -> ["+result+"]");
return result;
}
public static byte[] hex2byte(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static String byte2hex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte aByte : bytes) {
result.append(String.format("%02x", aByte));
// upper case
// result.append(String.format("%02X", aByte));
}
return result.toString();
}
public static String reverse(String source) {
int i, len = source.length();
StringBuilder dest = new StringBuilder(len);
for (i = (len - 1); i >= 0; i--){
dest.append(source.charAt(i));
}
return dest.toString();
}
}
I've tried several approaches with this one, And I have done some searching here, here, here, here and here.
I Managed to create the public key with the given parameters, but the results are always different when I encrypt the string:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace RSACypherTest
{
public class Program
{
public static RSACryptoServiceProvider rsa;
static void Main(string[] args)
{
string str = "1234";
string publicRSA = "010001|0097152d7034a8b48383d3dba20c43d049";
string encrypted = "";
Console.WriteLine("Original text: " + str);
encrypted = Encrypt(str, publicRSA);
Console.WriteLine("Encrypted text: " + encrypted);
Console.ReadLine();
}
public static string Encrypt(string str, string PublicRSA)
{
string[] Separated = PublicRSA.Split('|');
RsaKeyParameters pubParameters = MakeKey(Separated[1], Separated[0], false);
IAsymmetricBlockCipher eng = new Pkcs1Encoding(new RsaEngine());
eng.Init(true, pubParameters);
byte[] plaintext = Encoding.UTF8.GetBytes(Reverse(str));
byte[] encdata = eng.ProcessBlock(plaintext, 0, plaintext.Length);
return ByteArrayToString(encdata);
}
public static string Reverse(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
public static string ByteArrayToString(byte[] ba)
{
return BitConverter.ToString(ba).Replace("-", "");
}
public static byte[] StringToByteArray(string hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
private static RsaKeyParameters MakeKey(string modulusHexString, string exponentHexString, bool isPrivateKey)
{
var modulus = new BigInteger(modulusHexString, 16);
var exponent = new BigInteger(exponentHexString, 16);
return new RsaKeyParameters(isPrivateKey, modulus, exponent);
}
}
}
I'm trying to use BouncyCastle because it seems to be the most effcient way of dealing with the key generation and everything. Any help concerning this would be very much appreciated.
Thanks in advance.