c#中的RSA签名和Crypto ++的C ++validation

我想在C#中签名一些字节感谢RSACryptoServiceProvider类,并使用Crypto ++库在C ++中进行validation。 尽pipe我所有的尝试,尽pipe我确定我的钥匙和签名确认失败。

在C#中我签署如下:

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

我的密钥生成如下:

 CspParameters parameters = new CspParameters(); parameters.KeyNumber = (int)KeyNumber.Signature; using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024, parameters)) { privateKeyInfo = rsa.ExportParameters(true); publicKeyInfo = rsa.ExportParameters(false); } 

在C ++中,我创build公钥并尝试validation它如下:

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

模数和指数是从c#中使用rsa.ToXmlString(false)获得的XML中的复制/过去。 函数base64toHex由(在另一个SOpost中find)给出:

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

我不想使用任何外部文件,只有字节(或string)variables。 此外,我不确定我定义我的validation器的方式: RSASS<PSS, SHA256>::Verifier

你可以帮我吗?

Solutions Collecting From Web of "c#中的RSA签名和Crypto ++的C ++validation"

这个答案适用于crypto ++和windows API。

经过大量的试验/错误,我终于成功了,问题来自于我构建crypto ++ rsa键的方式( Integer类型:模数和指数)。

我创建了一个新函数GetIntegerFromBase64String ,它将我们从rsa.ToXmlString的xml输出获得的模数和指数直接转换为Integer类型,以初始化cryptopp中的键。

完整的加密++例子:

  string signature_64str = "G+PQaArLByTNYF5c5BZo2X3Guf1AplyJyik6NXCJmXnZ7CD5AC/OKq+Iswcv8GboUVsMTvl8G+lCa9Od0DfytnDui7kA/c1qtH7BZzF55yA5Yf9DGOfD1RHOl3OkRvpK/mF+Sf8nJwgxsg51C3pk/oBFjA450q2zq8HfFG2KJcs="; string modulus_64str = "0Z8GUI/rxlXanCCjkiP+c9HyvdlOibst2YD5XmZk4F86aLr7LbLtI7FMnr6rcQZa6RXkAykb5MIbasmkOmkLzSjhdTThnaZyuKBOBoybYB5mDecF2VMXfUIryEBFn4i6y58qhy0BnDnIhucdNXX0px10HL3uYzR2KBTC0lSFFmE="; string exponent_64str = "AQAB"; Integer mod_integer = GetIntegerFromBase64String(modulus_64str); Integer pub_integer = GetIntegerFromBase64String(exponent_64str); InvertibleRSAFunction param; param.Setmoduleus(mod_integer); param.SetPublicExponent(pub_integer); RSA::PublicKey pubkey(param); string decoded_sig = DecodeBase64String(signature_64str); if(!pubkey.Validate(rnd, 3)) cout << "Rsa public key validation failed" << endl; else cout << " key validation success"<< endl; RSASS<PKCS1v15, SHA512>::Verifier verif(pubkey); bool res = verif.VerifyMessage( reinterpret_cast<const byte*>(message.c_str()), message.length(), reinterpret_cast<const byte*>(decoded_sig.c_str()), decoded_sig.length() ); if( res ) { cout << "Signature on message verified " << endl; } else { cout << "Message verification failed " << endl; } 

与:

 string DecodeBase64String(string encoded ) { string decoded; Base64Decoder decoder; decoder.Attach( new StringSink( decoded ) ); decoder.Put( (byte*)encoded.data(), encoded.size() ); decoder.MessageEnd(); return decoded; } Integer GetIntegerFromBase64String(string encoded) { string decoded = DecodeBase64String(encoded); Integer integer( (byte*)decoded.c_str(),decoded.length()); return integer; } 

另外,我已经复制了与Windows API验证,对于这种情况下,我不使用XML密钥,但直接从我从rsa.ExportCspBlob(假)获得的blob密钥(编码在64位)

全窗口api的例子:

在C#中我得到了CspBlob如下:

  using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { rsa.ImportParameters(privateKey); var cspBlob = rsa.ExportCspBlob(false); var cspBlobBase_64str = Convert.ToBase64String(cspBlob);// <---- HERE 

然后在c ++中,我加载blob并验证签名如下:

 #include <windows.h> ... string ErrorMessage; string signature_64str = "G+PQaArLByTNYF5c5BZo2X3Guf1AplyJyik6NXCJmXnZ7CD5AC/OKq+Iswcv8GboUVsMTvl8G+lCa9Od0DfytnDui7kA/c1qtH7BZzF55yA5Yf9DGOfD1RHOl3OkRvpK/mF+Sf8nJwgxsg51C3pk/oBFjA450q2zq8HfFG2KJcs="; string public_key_blob_64_bit_encoded = "BgIAAACkAABSU0ExAAQAAAEAAQBhFoVU0sIUKHY0Y+69HHQdp/R1NR3nhsg5nAEthyqfy7qIn0VAyCtCfRdT2QXnDWYeYJuMBk6guHKmneE0deEozQtpOqTJahvC5BspA+QV6VoGcau+nkyxI+2yLfu6aDpf4GRmXvmA2S27iU7ZvfLRc/4jkqMgnNpVxuuPUAaf0Q=="; string message = "hello"; if( RSA_VerifySignature(message, signature_64str, public_key_blob_64_bit_encoded, ErrorMessage)) { cout << "OK : Signature on message verified " << endl; } else { cout << "Message verification failed, Error : " << ErrorMessage << endl; } 

与:

  bool RSA_VerifySignature(string message, string signature_64BitEncoded, string publickeyBlob_64BitEncoded, string &ErrorMessage) { const size_t LENGHT_SIGNATURE = 128; // 128 bytes == 1024 RSA Key bits const size_t LENGHT_BLOB_PUBLIC_KEY = 148; // 148 bytes bool isSigOk = false; HCRYPTHASH hash; byte decoded_Blob[LENGHT_BLOB_PUBLIC_KEY] ; size_t size_pubkey = Base64Decode(publickeyBlob_64BitEncoded, decoded_Blob, LENGHT_BLOB_PUBLIC_KEY); byte decoded_signature[LENGHT_SIGNATURE] ; size_t size_signature =Base64Decode(signature_64BitEncoded, decoded_signature, LENGHT_SIGNATURE); //reverse bytes byte reverse_decoded_signature[LENGHT_SIGNATURE]; for(int i=0;i<sizeof(reverse_decoded_signature);i++) reverse_decoded_signature[i] = decoded_signature[LENGHT_SIGNATURE-i-1]; HCRYPTPROV cryptProvider; // Get a handle to the PROV_RSA_AES (for CALG_SHA_512). if (!CryptAcquireContext(&cryptProvider, 0, 0, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ ErrorMessage = "Failure to acquire context"; goto Exit; } HCRYPTKEY publicKeyc; // convert the blob to the public key if(!CryptImportKey(cryptProvider, decoded_Blob, LENGHT_BLOB_PUBLIC_KEY, 0, 0, &publicKeyc)){ ErrorMessage = "Failure to import key"; goto Exit; } // create the hash object if(!CryptCreateHash(cryptProvider, CALG_SHA_512 , 0, 0, &hash)){ ErrorMessage = "Failure to creat Hash" ; goto Exit; } //hash the message if(!CryptHashData(hash, (byte*) message.c_str(), message.length(), 0)){ ErrorMessage = "Failure to Hash Data" ; goto Exit; } isSigOk = CryptVerifySignature(hash, reverse_decoded_signature, sizeof(reverse_decoded_signature), publicKeyc, nullptr, 0); if(!isSigOk) ErrorMessage = "Invalid Signature" ; Exit: // After processing, hHash and cryptProvider must be released. if(hash) CryptDestroyHash(hash); if(cryptProvider) CryptReleaseContext(cryptProvider,0); return isSigOk; } 

Base64Decode来自这个答案 。

PS:请注意,我已经在这个答案切换到SHA512。

关于这个:

 string DecodeBase64String(string encoded ) { string decoded; Base64Decoder decoder; decoder.Attach( new StringSink( decoded ) ); decoder.Put( (byte*)encoded.data(), encoded.size() ); decoder.MessageEnd(); return decoded; } Integer GetIntegerFromBase64String(string encoded) { string decoded = DecodeBase64String(encoded); Integer integer( (byte*)decoded.c_str(),decoded.length()); return integer; } 

你可能会觉得这个更容易一些(或者不是):

 $ cat test.cxx #include "cryptlib.h" #include "integer.h" #include "filters.h" #include "base64.h" #include "files.h" #include "hex.h" #include <iostream> #include <string> int main() { using CryptoPP::Integer; using CryptoPP::StringSource; using CryptoPP::Base64Decoder; std::string signature_64str = "G+PQaArLByTNYF5c5BZo2X3Guf1AplyJyik6NXCJmXnZ7CD5AC/OKq+Iswcv8GboUVsMTvl8G+lCa9Od0DfytnDui7kA/c1qtH7BZzF55yA5Yf9DGOfD1RHOl3OkRvpK/mF+Sf8nJwgxsg51C3pk/oBFjA450q2zq8HfFG2KJcs="; std::string modulus_64str = "0Z8GUI/rxlXanCCjkiP+c9HyvdlOibst2YD5XmZk4F86aLr7LbLtI7FMnr6rcQZa6RXkAykb5MIbasmkOmkLzSjhdTThnaZyuKBOBoybYB5mDecF2VMXfUIryEBFn4i6y58qhy0BnDnIhucdNXX0px10HL3uYzR2KBTC0lSFFmE="; std::string exponent_64str = "AQAB"; StringSource mod64(modulus_64str, true, new Base64Decoder()); StringSource exp64(exponent_64str, true, new Base64Decoder()); Integer mod_integer(mod64, mod64.MaxRetrievable()); Integer pub_integer(exp64, exp64.MaxRetrievable()); std::cout << mod_integer << std::endl; std::cout << pub_integer << std::endl; return 0; } 

代码使用这个Integer构造函数 :

 Integer (BufferedTransformation &bt, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order=BIG_ENDIAN_ORDER) 

代码产生:

 $ ./test.exe 14720100561434965959279660783734794237717246172864229085441100391073349113964189 60745884288272734508848163730385929321875027666547189267336228176446737079038557 84643451276687447934542940291651491826423492370177748998568853020003645093067936 387415713280978250634089486257964777026826174628998219103122976216673. 65537.