I'm trying to sign some bytes in C# thanks to the class RSACryptoServiceProvider and to verify it in C++ with the Crypto++ library. Despite all my attempts, the validation fail although I'm sure of my key and signature.
In C# I sign as follow :
var message = "hello";
var bytes = System.Text.Encoding.UTF8.GetBytes(message);
byte[] signedHash;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
// Import the key information.
rsa.ImportParameters(privateKey);
// Sign the data, using SHA256 as the hashing algorithm
signedHash = rsa.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
}
My keys are generated as follow :
CspParameters parameters = new CspParameters();
parameters.KeyNumber = (int)KeyNumber.Signature;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024, parameters))
{
privateKeyInfo = rsa.ExportParameters(true);
publicKeyInfo = rsa.ExportParameters(false);
}
In C++, I create the public key and try to verify it as follow :
RSA::PublicKey publicKey;
byte signature[128];
signature[0]= 150;
//....fill up to 127 , corresponds to "signedHash" variable from c# code
signature[127]= 89;
string simplemessage = "hello";
string modulus = "0Z8GUI/rxlXanCCjkiP+c9HyvdlOibst2YD5XmZk4F86aLr7LbLtI7FMnr6rcQZa6RXkAykb5MIbasmkOmkLzSjhdTThnaZyuKBOBoybYB5mDecF2VMXfUIryEBFn4i6y58qhy0BnDnIhucdNXX0px10HL3uYzR2KBTC0lSFFmE=";
string exponent = "AQAB";
char modulusCharred[1024];
strncpy_s(modulusCharred, base64ToHex(modulus).c_str(), sizeof(modulusCharred));
modulusCharred[sizeof(modulusCharred) - 1] = 0;
char exponentCharred[1024];
strncpy_s(exponentCharred, base64ToHex(exponent).c_str(), sizeof(exponentCharred));
exponentCharred[sizeof(exponentCharred) - 1] = 0;
Integer n(modulusCharred);
Integer e(exponentCharred);
publicKey.Initialize(n, e);
AutoSeededRandomPool rnd;
if(!publicKey.Validate(rnd, 3))
throw runtime_error("Rsa public key validation failed"); // no error is thrown
RSASS<PSS, SHA256>::Verifier verifier(publicKey);
bool result = verifier.VerifyMessage((const byte*)simplemessage.c_str(),simplemessage.length(), signature,128);
if(true == result) {
cout << "Signature on message verified" << endl;
} else {
cout << "Message verification failed" << endl; // always fail...
}
Modulus and exponent are copy/past from the xml obtained in c# using rsa.ToXmlString(false). The function base64toHex
is given by (found on another SO post):
std::string base64ToHex(std::string base64String)
{
std::string decodedString, finalString;
CryptoPP::StringSource river(base64String, true,
new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decodedString)));
CryptoPP::StringSource stream(decodedString, true,
new CryptoPP::HexEncoder(new CryptoPP::StringSink(finalString)));
finalString.erase(std::remove(finalString.begin(), finalString.end(), '\n'), finalString.end());
return finalString;
}
I do not want to use any external files, only bytes (or string) variable. Also I'm not sure of the way I define my verifier : RSASS<PSS, SHA256>::Verifier
.
Could you help me with this ?