2017-05-20 58 views
1

我需要簽署一個字符串,將公鑰作爲字符串發佈,然後在其他地方使用公鑰來驗證簽名的消息。這是該消息被簽署的部分:爲什麼我的OpenSSL/libcrypto簽名不正確?

 // RSA keypair generation 
     EVP_PKEY *keypair = NULL; 
     EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); 
     if (1 != EVP_PKEY_keygen_init(ctx)) { 
      initFail = true; 
     } 
     if (1 != EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048)) { 
      initFail = true; 
     } 
     if (1 != EVP_PKEY_keygen(ctx, &keypair)) { 
      initFail = true; 
     } 
     EVP_PKEY_CTX_free(ctx); 


     // Create public key string. 
     BIO* bo = BIO_new(BIO_s_mem()); 
     PEM_write_bio_PUBKEY(bo, keypair); 
     char buff[1000]; 
     BIO_read(bo, &buff[0], 1000); 
     BIO_free(bo); 
     pubkey = buff; 


     // Create signature 
     size_t *slen = new size_t; 
     unsigned char *sig = NULL; 
     std::string msg; 
     msg = stuffThatCreatesMessage(); 
     EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); 
     if (1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), 
        NULL, keypair)) { 
      initFail = true; 
     } 
     if (1 != EVP_DigestSignUpdate(mdctx, msg.c_str(), msg.length())) { 
      initFail = true; 
     } 
     if (1 != EVP_DigestSignFinal(mdctx, NULL, slen)) { 
      initFail = true; 
     } 
     sig = (unsigned char *) OPENSSL_malloc(
       sizeof(unsigned char) * (*slen)); 
     if (1 != EVP_DigestSignFinal(mdctx, sig, slen)) { 
      initFail = true; 
     } 
     signature = *sig; 
     OPENSSL_free(sig); 

     bool isSuccess = verifySignature(signature, pubkey, msg); 

如下是字符串信息和關鍵的代碼和實際驗證簽名:

bool verifySignature(std::string sig, std::string key_str, std::string msg) { 
    BIO* bo = BIO_new(BIO_s_mem()); 
    BIO_write(bo, key_str.c_str(), key_str.length()); 
    EVP_PKEY *key = EVP_PKEY_new(); 
    PEM_read_bio_PUBKEY(bo, &key, 0, 0); 
    BIO_free(bo); 

    unsigned char *unsigned_sig = new unsigned char[sig.length()+1]; 
    strcpy((char *) unsigned_sig, sig.c_str()); 
    EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); 
    if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key)) { 
     return false; 
    } 
    if (1 != EVP_DigestVerifyUpdate(mdctx, msg.c_str(), msg.length())) { 
     return false; 
    } 
    bool retval = (1 == EVP_DigestVerifyFinal(mdctx, unsigned_sig, 
       sig.length())); 
    delete unsigned_sig; 
    return retval; 
} 

每次我做到這一點,後者的功能告訴我的簽名無效,isSuccess變量等於0.這是因爲EVP_DigestSignFinal返回0,表示簽名不正確。我哪裏錯了?

+0

您是否驗證了生成的密鑰,保存到磁盤然後再次回讀的內存在內存中是否保持相同? – didiz

+0

是!我在測試中打印了他們兩個,他們是相同的。 –

+0

請提供調用verifySignature()的代碼 – Oleg

回答

0

@jww指出的問題是行signature = *sig。我結束時只有第一個字節作爲我的簽名字符串。正確的方法是:

std::string temp_sig = reinterpret_cast<char*>(sig); 
signature = temp_sig.substr(0, *slen);