簡體   English   中英

在PHP中使用openssl簽名文件並在c ++中進行驗證

[英]sign a file with openssl in php and verify in c++

我寫了一個Web服務,其中服務器是用php編寫的,而客戶端是用c ++編寫的,並且我使用openssl包來生成rsa對密鑰來保護數據傳輸。 最初,我用php編寫了兩個客戶機,用於准備服務,並且一切正常。 但是,當我開始將客戶端php代碼轉換為c ++時,我遇到了openssl方法的問題。 最大的問題是,簽名的數據在php和c ++代碼中均不匹配。 我得到數據的md5,並使用openssl_sign方法對md5數據進行簽名,然后在純數據的末尾附加符號並發送給客戶端(過去已為客戶端發送了公鑰)。 在客戶端中,我再次取得了這一進步。 但是該標志不能正確驗證。

可能程序出了什么問題?

請幫助,謝謝。

php端(webservice)代碼:

function sign($cleartext)
$msg_hash = md5($cleartext);
$sig      = "";
            $ok       = openssl_sign($msg_hash, $sig, $this->private_key);
if ($ok == 1)
{
    $signed_data = $cleartext . "----SIGNATURE:----" . base64_encode($sig);
    //$signed_data = $this->encryptAES($signed_data, $this->password);
    return base64_encode(mysql_real_escape_string($signed_data));
}
elseif ($ok == 0)
{
    $eroor = "bad";
    return base64_encode($eroor);
}
else
{
    $eroor = "ugly, error checking signature";
    return base64_encode($eroor);
}
}

和C ++端(客戶端)代碼:

int Crypto::rsaVerify(string msgStr, const char *pk) {

int length;

char *pkStr = new char[this->publicKey.length() + 1];
strcpy_s(pkStr, this->publicKey.length()+1,this->publicKey.c_str());

this->setPubKey((unsigned char *)pkStr,strlen(pkStr));

// Find and Splite Data
size_t current = 0;
string delimiters = "----SIGNATURE:----";
size_t next = msgStr.find( delimiters, current );
string dataStr = msgStr.substr( current, next - current );
char *msg = new char[dataStr.length() + 1];
strcpy_s(msg, dataStr.length()+1,dataStr.c_str());

// Find and Split sign
string signData = msgStr.substr(next + delimiters.length(), msgStr.length());
Coding *codingObj = new Coding();
signData = codingObj->base64_decode(signData);
char *signBuf = new char[signData.length() + 1];
strcpy_s(signBuf, signData.length()+1, signData.c_str());

unsigned char *dataMD5 = new unsigned char [MD5_DIGEST_LENGTH];
MD5((const unsigned char *)msg,strlen(msg),dataMD5);

char md5String[MD5_DIGEST_LENGTH + 1];
AsciiString2HexString(dataMD5,(unsigned char *)md5String, MD5_DIGEST_LENGTH);
md5String[MD5_DIGEST_LENGTH] = '\0';

char md5String1[MD5_DIGEST_LENGTH + 1];
AsciiString2HexString((unsigned char *)md5String1,(unsigned char *)md5String1, MD5_DIGEST_LENGTH);
md5String1[MD5_DIGEST_LENGTH] = '\0';

unsigned char * key2;
getPubKey(&key2);

unsigned int signLen = 256;//strlen(md5String);
char errorBuffer[120];

unsigned char message_digest[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *)md5String1, strlen(md5String1), message_digest);

if(RSA_verify(NID_sha1,(const unsigned char *)message_digest, SHA_DIGEST_LENGTH,(const unsigned char *)signBuf,signLen,this->keyPair))
{
    return 1;
}
else
{
    ERR_error_string(ERR_get_error(), errorBuffer); 
}

if(RSA_verify(NID_sha1,(const unsigned char *)md5String1, strlen(md5String1),(const unsigned char *)signBuf,signLen,this->keyPair))
{
    return 1;
}
else
{
    ERR_error_string(ERR_get_error(), errorBuffer); 
}

if(RSA_verify(NID_sha1,(const unsigned char *)md5String, strlen(md5String),(const unsigned char *)signBuf,signLen,this->keyPair))
{
    return 1;
}
else
{
    ERR_error_string(ERR_get_error(), errorBuffer); 
}

if(RSA_verify(NID_sha1,(const unsigned char *)dataMD5, strlen((char *)dataMD5),(const unsigned char *)signBuf,signLen,this->keyPair))
{
    return 1;
}
else
{
    ERR_error_string(ERR_get_error(), errorBuffer); 
}

return 0;
}


int Crypto::getPriKey(unsigned char **priKey) {

BIO *bio = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(bio, this->keyPair, NULL, NULL, NULL, NULL, NULL);

int priKeyLen = BIO_pending(bio);
*priKey = (unsigned char*)malloc(priKeyLen);
if(priKey == NULL) return FAILURE;

BIO_read(bio, *priKey, priKeyLen);

// Insert the NUL terminator
(*priKey)[priKeyLen-1] = '\0';

BIO_free_all(bio);

return priKeyLen;
}

可能是因為openssl_sign需要數據作為第一個參數,而不是數據的哈希。 默認情況下,此函數使用OPENSSL_ALGO_SHA1計算哈希值。

而且,如果可以的話,最好使用SHA2、256位或更多。 不建議將MD5和SHA1用於新項目...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM