【发布时间】:2019-12-05 23:40:17
【问题描述】:
我有以下字符串:ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=
我想对其应用 SHA256 并获取其哈希值。
然后我想用 RSA 和私钥对该哈希进行签名。
这是我想得到的签名(没有换行符):
Zg8ftxJqRyoreMQtMKAZNrjHHcD/rOSkU29Ty8zV9aItwHBDO0WpzaaPrqnX6/vdayUAndDVvSBoOc9g0WBkFHQHtB/auLlq+ABeBP4jxy
d7ypPxBbJFecfZiBDaGCq4jAxUnhQ2HjT5R23DHOOcf/i50TrWXr2G5k8enqa754TUn1JiDOJJT2JkfnKmgM7EPpCjHV/eCJsOQFXNaxht
h7zHz5hZ4aOfy6EGGveOggzIjKSLeo0pIE8jBc1wy9V8vZkhPTpkeLguCxnwvpMIV1X7zF3m5OoM0PbC5yXgPUYPrz0JNSlvCKR9q5CsFm
rnit5vBfi5el1ZmevP2MgyEA==
这是我得到的签名:
AR1X19H5wyb9IEi9WHrhatkR1jtTc7TovX23tdx8yID5CEWz+DF5kBNCXZxttJ8v
ctsbOL0rrQ0b4Gqa2ld00+nfzZJNg1osWwKb+sj6yNLy1XLqxFvfn1wrZ9Y8yOwS
oqJ0tTCpYbbbMo1mSVO4YuD18GbZJEDBUhBYY5D8H0MoHCSWLXsAjThAImyxw4ch
Hr2d1Sli4n6OA+CckGOQ15uLk6JiO6rNzNWfbbSb8a9trJ7bAdVPiKoln1X9tnWF
s3HK6fnfro9jlRQQ/Z0bCpF+FQrWrLouvLk+mjuTeiC+86HeeqzqlReAtpqtcO5/
9lWmrxXV2qZIqfuPYMovcA==
我正在使用的代码:
#include <iostream>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <assert.h>
#include <string.h>
#include <cstring>
std::string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n"\
"MIIEogIBAAKCAQEAjdKXiqYHzi++YmEb9X6qvqFWLCz1VEfxom2JhinPSJxxcuZW\n"\
"Bejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvYJumKO4R5zg0QSA7qdxiEhcwf/ekf\n"\
"SvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ7EgEcWUTvCs/GZJLI9s6XmKY2SMm\n"\
"v9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/yJ4vZwXvXGFqNDJyqG+ww7f77HYu\n"\
"bQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/BeZlL1YJHHM7CIBnb3/bzED0n944wo\n"\
"io+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/JRQIDAQABAoIBAG2AzvWE4L346z02\n"\
"0cmptdhe5hRR2lLrAc1yWh83JQ9hi881vfHuMtRql+3cZ218SV4nRNarIo6612NJ\n"\
"JFfM3SaeZ9cwoIPSXmHk8nBmg9xzEbiRSVIzA09uPZB4t9EB+sNYQvDkPMuPn0b3\n"\
"EWaq+LWRnayYaLZ/hccOx+m1mcnJnIs27+EPnufrUKVniCguburQoU3VEXSFCzBk\n"\
"23rhSu20vUOikLuuU4gcvWfnfUoOwdhb2iBhjgMbsjTTmg3+GQuPtblCSTKjk11F\n"\
"YX2MJHEDFfwVzSurmbqAZC9rjr7PbflC8GMmPfa1LCb7IG5s9AIM4v9Fea0SyZP+\n"\
"/pM9mzkCgYEAyjLPU7ieqly9+mgeb2fmWh7pYgO49KuFIqqHnP+LaXXYK/TvCJ8X\n"\
"zJ3PxBgwVMOT94nXSDNjzNLzp0hl8OWWBH0tN0fiq1OEyySM3Mlji6o8KpGcU1k4\n"\
"jFkXMK1rVQcW8ckLmzMrQF3SphQi4UiEpLX1Zba4YQ4fNHK8NHHHaEMCgYEAs48m\n"\
"Oe4iEZcVDnag+Mp0Zjgu4mYJeeeGtVUZFCJOeyLDsQVmnt5mJIgGwrxg4o3qljut\n"\
"aAUXzf8aYZ0fURAsLcwnQg03THFKeIt94Rw/72n2UWT+AZTU3GQtuwf+osZHUfS3\n"\
"XTLaQE+A1JBC4XLJ99j/95sxt6xZy5YyfhfY09cCgYAbqyhDxJexqE823NiNViJn\n"\
"YqN9DhVZJb9qJvu3uCBTphSWr0WmYF7ZWR79LnIupzSwQuR6tM2LUbKVyYpplIEa\n"\
"zCZL0kJqP1uEkNPVwpkkm37wNEy3+xWJ3wcVWiW91OKG44P7EN1ySWRx5X+AZHQC\n"\
"NgQGjyJb5ZrPioPGiWtIEQKBgE/0B/N3o9ftTET6cccWbootDkNlaAbOH1+TGu2q\n"\
"MQQHgNfMLdvD7/uITmpb81AuHSz0Ocy9p9HkK90XV6CC8QkbhMeWlu8E60It6slY\n"\
"COgUaMfpjmkp2nagbPSBJNNaMtu9egCX6jMEs7ry2bUFpgUkrSWWB1df+UP8B1O6\n"\
"TqRVAoGAVQoCUPVm6C6h6V5dgPvsJMxJ8EjOCgwkXNucAHWcpBV3/LlxLiCGRuEL\n"\
"B+epYxqwKLpSQBhldasKmmKB0M6MFTwxXwxCmCi80+DBdP5A7GIK52ZGth63i22t\n"\
"FI8MeDIzA5HqAI24P7ltozoEYAB7GIdJQXq9oT/DRagTwQUzQ8E=\n"\
"-----END RSA PRIVATE KEY-----\n";
/*std::string privateKey ="-----BEGIN PRIVATE KEY-----\n"\
"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCN0peKpgfOL75i\n"\
"YRv1fqq+oVYsLPVUR/GibYmGKc9InHFy5lYF6OTYjnIIvmkOdRobbGlCUxORX/tL\n"\
"sl8Ya9gm6Yo7hHnODRBIDup3GISFzB/96R9K/MzYQOcscMIoBDARaycnLvy7FlMv\n"\
"O7/rlVnsSARxZRO8Kz8Zkksj2zpeYpjZIya/369+oGqQk1cTRkHo59JvJ4Tfbk/3\n"\
"iIyf4H/Ini9nBe9cYWo0MnKob7DDt/vsdi5tA8mMtA953LapNyCZIDCRQQlUGNgD\n"\
"qY9/8F5mUvVgkcczsIgGdvf9vMQPSf3jjCiKj7j6ucxl1+FwJWmbvgNmiaUR/0q4\n"\
"m2rm78lFAgMBAAECggEAbYDO9YTgvfjrPTbRyam12F7mFFHaUusBzXJaHzclD2GL\n"\
"zzW98e4y1GqX7dxnbXxJXidE1qsijrrXY0kkV8zdJp5n1zCgg9JeYeTycGaD3HMR\n"\
"uJFJUjMDT249kHi30QH6w1hC8OQ8y4+fRvcRZqr4tZGdrJhotn+Fxw7H6bWZycmc\n"\
"izbv4Q+e5+tQpWeIKC5u6tChTdURdIULMGTbeuFK7bS9Q6KQu65TiBy9Z+d9Sg7B\n"\
"2FvaIGGOAxuyNNOaDf4ZC4+1uUJJMqOTXUVhfYwkcQMV/BXNK6uZuoBkL2uOvs9t\n"\
"+ULwYyY99rUsJvsgbmz0Agzi/0V5rRLJk/7+kz2bOQKBgQDKMs9TuJ6qXL36aB5v\n"\
"Z+ZaHuliA7j0q4Uiqoec/4tpddgr9O8InxfMnc/EGDBUw5P3iddIM2PM0vOnSGXw\n"\
"5ZYEfS03R+KrU4TLJIzcyWOLqjwqkZxTWTiMWRcwrWtVBxbxyQubMytAXdKmFCLh\n"\
"SISktfVltrhhDh80crw0ccdoQwKBgQCzjyY57iIRlxUOdqD4ynRmOC7iZgl554a1\n"\
"VRkUIk57IsOxBWae3mYkiAbCvGDijeqWO61oBRfN/xphnR9RECwtzCdCDTdMcUp4\n"\
"i33hHD/vafZRZP4BlNTcZC27B/6ixkdR9LddMtpAT4DUkELhcsn32P/3mzG3rFnL\n"\
"ljJ+F9jT1wKBgBurKEPEl7GoTzbc2I1WImdio30OFVklv2om+7e4IFOmFJavRaZg\n"\
"XtlZHv0uci6nNLBC5Hq0zYtRspXJimmUgRrMJkvSQmo/W4SQ09XCmSSbfvA0TLf7\n"\
"FYnfBxVaJb3U4objg/sQ3XJJZHHlf4BkdAI2BAaPIlvlms+Kg8aJa0gRAoGAT/QH\n"\
"83ej1+1MRPpxxxZvKi0OQ2VoBs4fX5Ma7aoxBAeA18wt28Pv+4hOalvzUC4dLPQ5\n"\
"zL2n0eQr3RdXoILxCRuEx5aW7wTrQi3qyVgI6BRox+mOaSnadqBs9IEk01oy2716\n"\
"AJfqMwSzuvLZtQWmBSStJZYHV1/5Q/wHU7pOpFUCgYBVCgJQ9WboLqHpXl2A++wk\n"\
"zEnwSM4KDCRc25wAdZykFXf8uXEuIIZG4QsH56ljGrAoulJAGGV1qwqaYoHQzowV\n"\
"PDFfDEKYKLzT4MF0/kDsYgrnZka2HreLba0Ujwx4MjMDkeoAjbg/uW2jOgRgAHsY\n"\
"h0lBer2hP8NFqBPBBTNDwQ==\n"\
"-----END PRIVATE KEY-----\n";
*/
std::string publicKey ="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjdKXiqYHzi++YmEb9X6q\n"\
"vqFWLCz1VEfxom2JhinPSJxxcuZWBejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvY\n"\
"JumKO4R5zg0QSA7qdxiEhcwf/ekfSvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ\n"\
"7EgEcWUTvCs/GZJLI9s6XmKY2SMmv9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/\n"\
"yJ4vZwXvXGFqNDJyqG+ww7f77HYubQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/Be\n"\
"ZlL1YJHHM7CIBnb3/bzED0n944woio+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/J\n"\
"RQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";
RSA* createPrivateRSA(std::string key) {
RSA *rsa = NULL;
const char* c_string = key.c_str();
BIO * keybio = BIO_new_mem_buf((void*)c_string, -1);
if (keybio==NULL) {
return 0;
}
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
return rsa;
}
RSA* createPublicRSA(std::string key) {
RSA *rsa = NULL;
BIO *keybio;
const char* c_string = key.c_str();
keybio = BIO_new_mem_buf((void*)c_string, -1);
if (keybio==NULL) {
return 0;
}
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
return rsa;
}
bool RSASign( RSA* rsa,
const unsigned char* Msg,
size_t MsgLen,
unsigned char** EncMsg,
size_t* MsgLenEnc) {
EVP_MD_CTX* m_RSASignCtx = EVP_MD_CTX_create();
EVP_PKEY* priKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(priKey, rsa);
if (EVP_DigestSignInit(m_RSASignCtx,NULL, EVP_sha256(), NULL,priKey)<=0) {
return false;
}
if (EVP_DigestSignUpdate(m_RSASignCtx, Msg, MsgLen) <= 0) {
return false;
}
if (EVP_DigestSignFinal(m_RSASignCtx, NULL, MsgLenEnc) <=0) {
return false;
}
*EncMsg = (unsigned char*)malloc(*MsgLenEnc);
if (EVP_DigestSignFinal(m_RSASignCtx, *EncMsg, MsgLenEnc) <= 0) {
return false;
}
EVP_MD_CTX_free(m_RSASignCtx);
return true;
}
bool RSAVerifySignature( RSA* rsa,
unsigned char* MsgHash,
size_t MsgHashLen,
const char* Msg,
size_t MsgLen,
bool* Authentic) {
*Authentic = false;
EVP_PKEY* pubKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pubKey, rsa);
EVP_MD_CTX* m_RSAVerifyCtx = EVP_MD_CTX_create();
if (EVP_DigestVerifyInit(m_RSAVerifyCtx,NULL, EVP_sha256(),NULL,pubKey)<=0) {
return false;
}
if (EVP_DigestVerifyUpdate(m_RSAVerifyCtx, Msg, MsgLen) <= 0) {
return false;
}
int AuthStatus = EVP_DigestVerifyFinal(m_RSAVerifyCtx, MsgHash, MsgHashLen);
if (AuthStatus==1) {
*Authentic = true;
EVP_MD_CTX_free(m_RSAVerifyCtx);
return true;
} else if(AuthStatus==0){
*Authentic = false;
EVP_MD_CTX_free(m_RSAVerifyCtx);
return true;
} else{
*Authentic = false;
EVP_MD_CTX_free(m_RSAVerifyCtx);
return false;
}
}
void Base64Encode( const unsigned char* buffer,
size_t length,
char** base64Text) {
BIO *bio, *b64;
BUF_MEM *bufferPtr;
b64 = BIO_new(BIO_f_base64());
bio = BIO_new(BIO_s_mem());
bio = BIO_push(b64, bio);
BIO_write(bio, buffer, length);
BIO_flush(bio);
BIO_get_mem_ptr(bio, &bufferPtr);
BIO_set_close(bio, BIO_NOCLOSE);
BIO_free_all(bio);
*base64Text=(*bufferPtr).data;
}
size_t calcDecodeLength(const char* b64input) {
size_t len = strlen(b64input), padding = 0;
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
padding = 2;
else if (b64input[len-1] == '=') //last char is =
padding = 1;
return (len*3)/4 - padding;
}
void Base64Decode(const char* b64message, unsigned char** buffer, size_t* length) {
BIO *bio, *b64;
int decodeLen = calcDecodeLength(b64message);
*buffer = (unsigned char*)malloc(decodeLen + 1);
(*buffer)[decodeLen] = '\0';
bio = BIO_new_mem_buf(b64message, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
*length = BIO_read(bio, *buffer, strlen(b64message));
BIO_free_all(bio);
}
unsigned char * strToHex(std::string plainText){
unsigned char * hexArray;
hexArray = (unsigned char*)malloc(plainText.length());
for(int i = 0; i < plainText.size();i++){
hexArray[i] = std::strtol(&plainText[i],NULL,64);
}
return hexArray;
}
char* signMessage(std::string privateKey, std::string plainText) {
RSA* privateRSA = createPrivateRSA(privateKey);
unsigned char* encMessage;
char* base64Text;
size_t encMessageLength;
RSASign(privateRSA, (unsigned char*) plainText.data(), plainText.length(), &encMessage, &encMessageLength);
Base64Encode(encMessage, encMessageLength, &base64Text);
free(encMessage);
return base64Text;
}
bool verifySignature(std::string publicKey, std::string plainText, char* signatureBase64) {
RSA* publicRSA = createPublicRSA(publicKey);
unsigned char* encMessage;
size_t encMessageLength;
bool authentic;
Base64Decode(signatureBase64, &encMessage, &encMessageLength);
bool result = RSAVerifySignature(publicRSA, encMessage, encMessageLength, plainText.c_str(), plainText.length(), &authentic);
return result & authentic;
}
int main() {
std::string plainText = "ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=";
char* signature = signMessage(privateKey, plainText);
bool authentic = verifySignature(publicKey, "ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=", signature);
if ( authentic ) {
std::cout << "Authentic" << std::endl;
std::cout << signature << std::endl;
} else {
std::cout << "Not Authentic" << std::endl;
}
}
我实际上想要做的是“翻译”第三方使用的 C# 代码,我需要执行相同的操作,我尝试查找此处使用的库的文档,但我不能发现很多,我试图复制的代码如下:
using System;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace KeyPairLoad
{
class Program
{
static void Main(string[] args)
{
string cadena = ComputeSha256Hash("ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=");
string pathPrivateKey = @"C:\Users\xxx\Downloads\Fieles de pruebas\FOO1\some.key";
string password = "12345678a";
byte[] privBytes = System.IO.File.ReadAllBytes(pathPrivateKey);
AsymmetricKeyParameter llavePrivada = PrivateKeyFactory.DecryptKey(password.ToCharArray(), privBytes);
var rsaPriv = DotNetUtilities.ToRSA(llavePrivada as RsaPrivateCrtKeyParameters);
var csp = new CspParameters();
csp.KeyContainerName = "KeyContainer";
var rsaPrivate = new RSACryptoServiceProvider(csp);
string fin = Convert.ToBase64String(rsaPrivate.SignHash(Convert.FromBase64String(cadena), "SHA256"));
}
static string ComputeSha256Hash(string rawData)
{
using (SHA256 sha256Hash = SHA256.Create())
{
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
return Convert.ToBase64String(bytes);
}
}
}
}
这个第三方给了我我应该得到的签名。我尝试了很多东西,但没有任何效果,我得到了不同的签名,但不是我要找的那个。
我的翻译是否遗漏了什么?我做错了吗?
感谢您的耐心等待和时间。如果您需要更多信息,请告诉我。
问候!
【问题讨论】:
-
不用说,您不会将这个特定的私钥用于任何事情。
-
是的,不用担心它只是为了测试目的:3
-
请您澄清您的问题。在您的问题和 C 代码中,您声明要签名的字符串是“ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg”。但是在.Net 代码中,您正在操作的字符串是“TextoconCadenaOriginalaFirmar” - 这显然不是同一个字符串!为什么?
-
提供的 .NET 代码不是我制作的,但您可以假装我们正在签署相同的字符串,我会为您修改问题。
-
我无法使用您提供的 C# 代码和私钥生成任一输出。您能否提供在 base64 中被散列的值、在 PEM 中的私钥以及可以生成您当前获得的签名的最小代码段(显然不是您想要的签名)。
标签: c++ .net openssl cryptography rsa