I have an application running on c# and another server application in go. I need to implement secure communication using rsa.
What i'am doing is I've initialized the RSA provider in my C# application and generated public key to extract Modulus and Exponent. Then concatenated the modulus (Hexadecimal) and exponent (int) and converted this string to Base64 string, send it to a GO endpoint.
Here is C# code snippet
public string ConvertToPublicKey()
{
CspParameters rsaParameters = GetCspParameters();
RSACryptoServiceProvider provider = newRSACryptoServiceProvider(rsaParameters);
string paramsXml = RsaProvider.ToXmlString(false);
XDocument xDocument = XDocument.Parse(paramsXml);
string modulus = xDocument.Descendants().FirstOrDefault(x => x.Name == "Modulus")?.Value ?? string.Empty;
string exponent = xDocument.Descendants().FirstOrDefault(x => x.Name == "Exponent")?.Value ?? string.Empty;
byte[] base64BytesOfModulus = Convert.FromBase64String(modulus);
string hexaDecimalofModulus = BitConverter.ToString(base64BytesOfModulus).Replace("-", string.Empty);
byte[] base64BytesOfExponent = Convert.FromBase64String(exponent);
string hexadecimalOfExponent = BitConverter.ToString(base64BytesOfExponent).Replace("-", string.Empty);
int intOfExponent = Convert.ToInt32(hexadecimalOfExponent, 16);
byte[] publicKey = Encoding.UTF8.GetBytes($"{hexaDecimalofModulus};{intOfExponent}");
return Convert.ToBase64String(publicKey);
}
private static CspParameters GetCspParameters()
{
const string containerName = "KeyContainer";
return new CspParameters
{
KeyContainerName = containerName,
Flags = CspProviderFlags.UseMachineKeyStore
};
}
At Go endpoint I received public key and modulus correctly. Then I encrypted the message using public key and sent it back to c# application in response after converting encrypted message byte[] to base64.
Here is GO code snippet
func GetLicenseInfo(responseWriter http.ResponseWriter,request*http.Request)
{
encryptionKey := request.Header.Get("Authorization")
var decodedStringBytes, errors = b64.StdEncoding.DecodeString(encryptionKey)
if errors == nil {
var decodedString = string(decodedStringBytes)
result := strings.Split(decodedString, ";")
modulus := new(big.Int)
modulus.SetString(result[0], 16)
exponent, exponentErrors := strconv.Atoi(result[1])
if exponentErrors == nil {
var someInfo = utils.GetInfo()
var InfoInJson = ToJson(someInfo)
publicKey := &rsa.PublicKey{N: modulus, E: exponent}
var encryptedMessage, err = rsa.EncryptOAEP(sha256.New(),rand.Reader, publicKey,[]byte(InfoInJson), []byte(""))
var response = b64.StdEncoding.EncodeToString(encryptedMessage)
if err == nil {
json.NewEncoder(responseWriter).Encode(response)
}
}
}
}
func ToJson(model InfoModel) string {
InfoInJson, errors := json.Marshal(model)
if errors != nil {
panic("An error occurred while serializing the response")
}
return string(InfoInJson)
}
When i received the response back in Base64 string i converted it to Byte[]
and tried decrypting that with same instance of RSACryptoServiceProvider
then it throws the following exception
Error occurred while decoding OAEP padding.
any help?
UPDATE for example here is the base64 string that i received in GO
QUQ2NDlFRTlCQTA3Q0IxNEI1MTNDMzczQzBBMjNBOEQyMDI5MkVGQTBFMjgyNUIyMEEyMzM1MEE3OTUyNjgyQ0Y3MEFBQjJBMTZGMzQyNTM4MkU2RDZBRjU5M0IxRTI2MTE0OEIyQkFFRTY3MUVDMTQ1NDk1NjBDRkNEQUNCQzI3RUUxNDRFODZDQUI4RDBDOUY2OENBNTUwNUMxQjZGQkVBQjQ0MTlBMjg3RDhBRjgxRDUyREY3MEM0RDZDQTA5MkREMzk5Q0NEODU5Q0FGQzAzQ0JEQ0JBQzgwOTg3NDY0NThBMkY4NEREOTc1QjU5QTJBMUNBNzQxQTBDNkQ2RDs2NTUzNw==
and here is what my GO app sent back
QuWpWdEPSJR+l9UJTkh+heJJ/NpPwhz/hVVu1VdKYdz37YGWWdKTj7Fc5lZ3A8p1WjtC4F+yieZCz0tEatCqTpRmm9g6Oioyjbtr9qGTxO/PE+GA33YyBe6nmMRe674SPePx/fg6l3nnfSZ4/+iLCV4bNgyNqFHCaXc7H4Snms8=
UPDATE 2 I've updated the code snippet and included the data types and here is the part that dscrypts the content received from GO end point
public byte[] Decrypt(byte[] encryptedData, RSAParameters rsaParameters)
{
RsaProvider.ImportParameters(rsaParameters);
return RsaProvider.Decrypt(encryptedData, true);
}
i receive a base64 string then i convert to byte[] using this
byte[] b = Convert.FromBase64String(responseString); byte[] decryptedBytes=crypto.Decrypt(b, crypto.RsaProvider.ExportParameters(false));
crypto is the instance of the class that contains decryption logic,instacne of RSACryptoServiceProvider
and that method(ConvertToPublicKey) given above returning the public key