gpt4 book ai didi

php - 使用/发送 POST 数据时的 libcurl C 问题(不是 C++)

转载 作者:行者123 更新时间:2023-11-30 17:43:04 26 4
gpt4 key购买 nike

好吧,我一直在尝试重现这个 PHP 脚本的功能:

<?php

function api_query($method, array $req = array()) {
// API settings
$key = ''; // your API-key
$secret = ''; // your Secret-key

$req['method'] = $method;
$mt = explode(' ', microtime());
$req['nonce'] = $mt[1];

// generate the POST data string
$post_data = http_build_query($req, '', '&');

$sign = hash_hmac("sha512", $post_data, $secret);

// generate the extra headers
$headers = array(
'Sign: '.$sign,
'Key: '.$key,
);

// our curl handle (initialize if required)
static $ch = null;
if (is_null($ch)) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; Cryptsy API PHP client; '.php_uname('s').'; PHP/'.phpversion().')');
}
curl_setopt($ch, CURLOPT_URL, 'https://www.cryptsy.com/api');
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

// run the query
$res = curl_exec($ch);

if ($res === false) throw new Exception('Could not get reply: '.curl_error($ch));
$dec = json_decode($res, true);
if (!$dec) throw new Exception('Invalid data received, please make sure connection is working and requested API exists');
return $dec;
}

我已经(至少我相信我已经)通过自己构建查询来创建 C 所没有的 http_build_query 调用。我通过使用 gettimeofday() 在 mtStr 中拥有 $mt 变量,并且使用 openSSL 中的 HMAC 函数用我的 key 对 post_data 进行签名。

我发现C中的CURLOPT_HTTPHEADER选项需要一个curl_slist链接列表,而不仅仅是像PHP中的数组,但我似乎遇到问题的是在发布数据中。请求将通过,但会返回一个错误,提示“检查您的 POST 数据”。所以我回到 libcurl 文档,发现 CURLOPT_POSTFIELDS 需要一个 void* 来发送您想要发布的数据。所以我创建了 void *pData = post_data (其中 post_data 只是一个字符数组,而不是指针,所以我在这里没有看到探针),但它仍然说它无法验证我的身份,请检查 POST 数据。因此,如果您能看一下这个并告诉我哪里出错了,我将不胜感激......

请注意,我没有显示我的 API 和 key ,因为我无法自己更改它们,我宁愿不透露它们,但我知道这使得在没有加密帐户的情况下很难通过自己编译来检查我的东西,但我现在想保密,但里面有一些虚拟 key ,这样就可以对长度合适的哈希值等进行哈希处理。

char *handle_url( char *url )
{
CURL *curl;

struct url_data data;
data.size = 0;
data.data = malloc( 4096 );
if ( NULL == data.data )
{
fprintf( stderr, "failed to allocate memory.\n" );
return NULL;
}

data.data[0] = '\0';

CURLcode res;

// API settings, API key and secret key for your account
char key[] = "9498fbb723961a42816a10bc559cgda7ded2ed8e";
char secret[] = "687cd29def08a7861446c3b4b9c97996c8472e7dd8922da147d3b1343e52e99125d24ace90729fbb";

// method to use against the API, will make changable later
char *method = "mytrades";

// This is required to replace the microtime()/explode methods to
// generate the nonce value required to use the cryptsy API
struct timeval time;
gettimeofday( &time, NULL );
long mt = ( (unsigned long long)time.tv_sec * 1000000 ) + time.tv_usec;
// C is much morer strict than PHP about types so we create a buffer for the
// string representation of the nonce
char mtStr[ 128 ];

sprintf( mtStr, "%lu", mt );

// C does not have a build_http_query as PHP does so
// we just create the string neccessary with strcpy
// and strcat
char post_data[ strlen("method=") + strlen(method) + strlen("&nonce=") + strlen(mtStr) + 1];
strcpy( post_data, "method=" );
strcat( post_data, method );
strcat( post_data, "&" );
strcat( post_data, "nonce=" );
strcat( post_data, mtStr );

printf( "%s", post_data);
printf( "\n");

void *pData = post_data;

//sha512 needs 128 characters
unsigned char *result;
unsigned int len = 128;

result = (unsigned char *)malloc( sizeof(char) * len );

HMAC_CTX ctx;
HMAC_CTX_init( &ctx );

// using sha512
HMAC_Init_ex( &ctx, secret, strlen(secret), EVP_sha512(), NULL );
HMAC_Update( &ctx, (unsigned char *)&post_data, strlen(post_data) );
HMAC_Final( &ctx, result, &len );
HMAC_CTX_cleanup( &ctx );
/*
printf( "\nHMAC digest: " );

for ( int i = 0; i != len; i++ )
{
printf( "%02x", (unsigned int)result[i] );
} */
printf("\n");

// This is the start of setting up the $headers array as in the PHP script
const char *header1 = "Sign: ";
size_t PrefixL = strlen(header1);
char resBuffer[PrefixL + 2 * len + 1];
strcpy( resBuffer, header1);
char *p = &resBuffer[PrefixL];

for ( unsigned int i = 0; i < len; i++ )
{
sprintf( p, "%02x", (unsigned int)result[i]);
p += 2;
}

printf( "%s\n", resBuffer );

const char *header2 = "Key: ";
size_t PrefixR = strlen(header2);
char keyBuffer[PrefixR + 2 * strlen(key) + 1];
strcpy( keyBuffer, header2);
strcat( keyBuffer, key);

printf( "\n%s\n", keyBuffer );


// So now resBuffer is Sign: <128 character sha512 hash here>
// and keyBuffer is Key: <API key here>

free(result);

//struct curl_httppost *chttppostlist = NULL; //a possibility about sending chunked post data not currently used

// originally I set this up so that Sign and Key would be in the array in the same
// manner as the PHP script but libcurl in C needs a curl_slist
const char *headerArray[2];
headerArray[0] = resBuffer;
headerArray[1] = keyBuffer;

// So then we just create a curl_slist and add the resBuffer and keyBuffer (headerArray
// [0] and headerArray[1] respectively) to the curl_slist.
struct curl_slist *cslist= NULL;
curl_slist_append(cslist, headerArray[0]);
curl_slist_append(cslist, headerArray[1]);

curl = curl_easy_init();
if ( curl )
{
curl_easy_setopt( curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible Cryptsy API C Client)");
curl_easy_setopt( curl, CURLOPT_URL, url );
curl_easy_setopt( curl, CURLOPT_POST, 1 ); // is this necessary? isnt in PHP
curl_easy_setopt( curl, CURLOPT_POSTFIELDS, pData ); // <--- something wrong here?
curl_easy_setopt( curl, CURLOPT_HTTPHEADER, cslist );
curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_data );
curl_easy_setopt( curl, CURLOPT_WRITEDATA, &data );
curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 0 );
res = curl_easy_perform( curl );
if ( res != CURLE_OK )
{
fprintf( stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
curl_slist_free_all( cslist );
curl_easy_cleanup( curl );
}
return data.data;
}

最佳答案

#include <iostream>
#include <cstdlib>
#include <cstring>
#include "json_parsers.h"
extern "C" {
#include <curl/curl.h>
#include <sys/time.h>
#include <limits.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
}

#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2

using namespace std;

struct url_data {
size_t size;
char *data;
};

size_t write_data( void *ptr, size_t size, size_t nmemb, struct url_data *data )
{
size_t index = data->size;
size_t n = ( size * nmemb );
char *tmp;

data->size += ( size * nmemb );

#ifdef DEBUG
fprintf( stderr, "data at %p size=%ld nmemb=%ld\n", ptr,
size, nmemb );
#endif

tmp = (char *)realloc( data->data, data->size + 1); // + 1 for \n

if ( tmp )
{
data->data = tmp;
}
else
{
if ( data->data )
{
free( data->data );
}
fprintf( stderr, "Failed to allocate memory.\n" );
return 0;
}

memcpy( ( data->data + index ), ptr, n );
data->data[ data->size ] = '\0';

return size * nmemb;
}

char *cryptsy_api( char *url, char *method_in, char *marketid, int limit, char *ordertype, char *quantity, char *price, char *orderid ) {

CURL *curl;

struct url_data data;
data.size = 0;
data.data = (char *)malloc(4096);
if (data.data == NULL)
{
cerr << "Failed to allocate memory.\n" << endl;
return NULL;
}

data.data[0] = '\0';

CURLcode res;

char strInt[5];
if (limit != NULL)
{
sprintf(strInt, "%d", limit);
}

// API settings, API key and secret key for your account
char key[] = "9498fbb723961a42816a10bc559cfda7ded2ed8f";
char secret[] = "687cd29def08a7861446c3b4b9c97996c8472e7dd8922da147d3b1346e52e99125d24ace90729fb3";

char *method = method_in;

// This is required to replace the microtime()/explode methods to
// generate the nonce value required to use the cryptsy API
struct timeval time;
gettimeofday(&time, NULL);
long mt = (unsigned long long)time.tv_sec;

char mtStr[10];
sprintf(mtStr, "%ul", mt);


// C does not have a build_http_query as PHP does so
// we just create the string neccessary with strcpy
// and strcat
char post_data[ strlen("method=") + strlen(method) + strlen("&nonce=") + strlen(mtStr) + strlen("&marketid=110") + strlen("&limit=1000") + strlen("&ordertype=sell&quantity=1000000&price=0.00000000")+ 1];
strcpy(post_data, "method=");
strcat(post_data, method);
strcat(post_data, "&nonce=");
strcat(post_data, mtStr);
if (marketid != NULL)
{
strcat(post_data, "&marketid=");
strcat(post_data, marketid);
}
if (limit != NULL)
{
strcat(post_data, "&limit=");
strcat(post_data, strInt);
}
if (ordertype != NULL)
{
strcat(post_data, "&ordertype=");
strcat(post_data, ordertype);
}
if (quantity != NULL)
{
strcat(post_data, "&quantity=");
strcat(post_data, quantity);
}
if (price != NULL)
{
strcat(post_data, "&price=");
strcat(post_data, price);
}
if (orderid != NULL)
{
strcat(post_data, "&orderid=");
strcat(post_data, orderid);
}

unsigned char *result;
unsigned int len = SHA512_DIGEST_LENGTH;

result = (unsigned char *)malloc(sizeof(char) * len);

HMAC_CTX ctx;
HMAC_CTX_init( &ctx );

// using SHA512
HMAC_Init_ex( &ctx, secret, strlen(secret), EVP_sha512(), NULL);
HMAC_Update( &ctx, (unsigned char *)&post_data, strlen(post_data));
HMAC_Final( &ctx, result, &len);
HMAC_CTX_cleanup( &ctx );

const char *header1 = "Sign: ";
size_t PrefixL = strlen(header1);
char resBuffer[PrefixL + 2 * len + 1];
strcpy(resBuffer, header1);
char *p = &resBuffer[PrefixL];

for (unsigned int i = 0; i < len; i++)
{
sprintf(p, "%02x", (unsigned int)result[i]);
p += 2;
}

const char *header2 = "Key: ";
size_t PrefixR = strlen(header2);
char keyBuffer[PrefixR + 2 * strlen(key) + 1];
strcpy(keyBuffer, header2);
strcat(keyBuffer, key);

free(result);

struct curl_slist *cslist = NULL;
cslist = curl_slist_append(cslist, resBuffer);
cslist = curl_slist_append(cslist, keyBuffer);

curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible Cryptsy API C Client)");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(post_data));
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, cslist);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
cerr << "curl_easy_perform() failed " << curl_easy_strerror(res) << "\n" << endl;
}
curl_slist_free_all(cslist);
curl_easy_cleanup(curl);
}
return data.data;
}

抱歉无法格式化最后一位,但您明白了,是的,我更改了 API key :)

关于php - 使用/发送 POST 数据时的 libcurl C 问题(不是 C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20320605/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com