libs3-c:構造URL返回“SignatureDoesNotMatch”的修復

問題描述

https://github.com/bji/libs3下載C版libs3庫源碼,編譯安裝(參見libs3-c:編譯安裝和基礎命令操作)后哎榴,put和get命令都能正確使用,執(zhí)行gqs命令生成對象URL涨缚,瀏覽器訪問該URL時報“SignatureDoesNotMatch”錯誤家制,如下:

SignatureDoesNotMatch

分析思路

從提示看是url的簽名有誤導致服務端拒絕,大致思路為
1不同、分析源代碼厉膀,梳理gqs命令的執(zhí)行流程;
2二拐、從亞馬遜官網(wǎng)找到S3的
Authenticating Requests: Using Query Parameters (AWS Signature Version 4)章節(jié)服鹅,分析URL生成標準流程和參考example;
3百新、查找當前gqs流程與標準流程的差異點企软,解決差異并試驗。

S3官網(wǎng)中該文檔有幾處重點:
1饭望、提供了一個標準的預簽名URL仗哨,方便對照差異形庭;
2、提示換行符只是方便閱讀實際字符串是連續(xù)的厌漂,“/”也是方便閱讀實際是%2F萨醒;
3、對URL中每項都進行了詳細解釋桩卵;
4验靡、給出了計算簽名(Calculating Signature)的流程和詳細示例。

試驗流程

打開Signature調(diào)試開關雏节,重新編譯安裝胜嗓,并運行gqs指令

/* Macro in request.c */
#define SIGNATURE_DEBUG

$ sudo make uninstall && make clean && make && sudo make install
$ s3 gqs -u nvrbucket/dog.jpeg

詳細輸出(host域名做了替換)

--
Canonical Request:
GET
/nvrbucket/dog.jpeg

host:xxxx.xxxx.xxxx.cn
x-amz-content-sha256:UNSIGNED-PAYLOAD
x-amz-date:20191031T034215Z

host;x-amz-content-sha256;x-amz-date
UNSIGNED-PAYLOAD
--
String to Sign:
AWS4-HMAC-SHA256
20191031T034215Z
20191031/us-east-1/s3/aws4_request
49fd66dead2dfc009233c802aafdfd188bc8871a053531c452d0cd58845b77ed
--
Authorization Header:
Authorization: AWS4-HMAC-SHA256 Credential=cKc863uvDSWJZZkRijts/20191031/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=669b2ae3a0897f1ce5074564a255a2b8a9ca3652daf35a1574752866acf97f56

--
AMZ Headers:
x-amz-date: 20191031T034215Z
x-amz-content-sha256: UNSIGNED-PAYLOAD
http://xxxx.xxxx.xxxx.cn/nvrbucket/dog.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=cKc863uvDSWJZZkRijts/20191031/us-east-1/s3/aws4_request&X-Amz-Date=20191031T034215Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host;x-amz-content-sha256;x-amz-date&X-Amz-Signature=669b2ae3a0897f1ce5074564a255a2b8a9ca3652daf35a1574752866acf97f56

標準流程


Calculating Signature

正確示例

/* 基礎環(huán)境配置 */
AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE,
AWSSecretAccessKey=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY钩乍,
bucket=examplebucket辞州,
object=test.txt,
expires=86400,
region=us-east-1,
/* 正確參考示例 */
--
Canonical Request:
GET
/test.txt
X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20130524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host
host:examplebucket.s3.amazonaws.com

host
UNSIGNED-PAYLOAD
--
String to Sign:
AWS4-HMAC-SHA256
20130524T000000Z
20130524/us-east-1/s3/aws4_request
3bfa292879f6447bbcda7001decf97f4a54dc650c8942174ae0a9121cf58ad04
--
SigningKey:
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request")

--
URL:
https://examplebucket.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20130524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=aeeed9bbccd4d02ee5c0109b86d86835f995330da4c265957d157751f604d404

修改代碼寥粹,確保輸出與example一致
1变过、compose_auth_header( )中values->canonicalQueryString為NULL,與示例不符需要賦值涝涤,在setup_request()中添加代碼

/* request.c && setup_request() */
    // Compute the canonicalized resource
    canonicalize_resource(&params->bucketContext, computed->urlEncodedKey,
                          computed->canonicalURI,
                          sizeof(computed->canonicalURI));
    snprintf(computed->authCredential, sizeof(computed->authCredential),
             "%s%%2F%.8s%%2F%s%%2Fs3%%2Faws4_request", params->bucketContext.accessKeyId,
             computed->requestDateISO8601, S3_DEFAULT_REGION);

    // compose params
    char queryParams[sizeof("X-Amz-Algorithm=AWS4-HMAC-SHA256") +
                     sizeof("&X-Amz-Credential=") +
                     sizeof(computed->authCredential) +
                     sizeof("&X-Amz-Date=") +
                     sizeof(computed->requestDateISO8601) +
                     sizeof("&X-Amz-Expires=") + 64 +
                     sizeof("&X-Amz-SignedHeaders=") +
                     sizeof(computed->signedHeaders) + 1] = { 0 };
    snprintf(queryParams, sizeof(queryParams),
             "X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=%s"
             "&X-Amz-Date=%s&X-Amz-Expires=%d"
             "&X-Amz-SignedHeaders=%s",
             computed->authCredential, computed->requestDateISO8601, expires,
             computed->signedHeaders);

    canonicalize_query_string(queryParams, params->subResource,
                              computed->canonicalQueryString,
                              sizeof(computed->canonicalQueryString));

2媚狰、去掉對compose_auth_header()中的values->authCredential的重復賦值,上面添加代碼時阔拳,已經(jīng)賦值完成崭孤,且用%2F替換了‘/’

/* request.c && compose_auth_header() */
    len = 0;
    values->requestSignatureHex[0] = '\0';
    for (i = 0; i < S3_SHA256_DIGEST_LENGTH; i++) {
        buf_append(values->requestSignatureHex, "%02x", finalSignature[i]);
    }
#if 0
    snprintf(values->authCredential, sizeof(values->authCredential),
             "%s/%.8s/%s/s3/aws4_request", params->bucketContext.accessKeyId,
             values->requestDateISO8601, awsRegion);
#endif
    snprintf(values->authorizationHeader,
             sizeof(values->authorizationHeader),
             "Authorization: AWS4-HMAC-SHA256 Credential=%s,SignedHeaders=%s,Signature=%s",
             values->authCredential, values->signedHeaders,
             values->requestSignatureHex);

3、去掉canonicalize_signature_headers()中對amzHeader的多余添加

/* request.c && canonicalize_signature_headers() */
    // Make a copy of the headers that will be sorted
    const char *sortedHeaders[S3_MAX_METADATA_COUNT + 3];

#if 0
    memcpy(sortedHeaders, values->amzHeaders,
           (values->amzHeadersCount * sizeof(sortedHeaders[0])));

    // add the content-type header and host header
    int headerCount = values->amzHeadersCount;
#else
    int headerCount = 0;
#endif

    if (values->contentTypeHeader[0]) {
        sortedHeaders[headerCount++] = values->contentTypeHeader;
    }

完成上述環(huán)境配置和代碼修改糊肠,即可實現(xiàn)gqs命令的正確URL輸出辨宠,協(xié)議對比符合預期且URL可以訪問,不過在重新進行put货裹,list等其他命令時發(fā)生“SignatureDoesNotMatch”錯誤嗤形,為了保持對原命令的兼容性,該部分修改需為gqs命令單獨執(zhí)行弧圆。

總結

以上是幾個關鍵點的修改茬缩,完成修改優(yōu)化并通過測試的libs3庫晶渠,已放入地址https://github.com/Doawen/protocol-libs3-c.git可參考茬暇。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓤狐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子斯撮,更是在濱河造成了極大的恐慌经伙,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異帕膜,居然都是意外死亡枣氧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門垮刹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來达吞,“玉大人,你說我怎么就攤上這事荒典±医伲” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵寺董,是天一觀的道長覆糟。 經(jīng)常有香客問我,道長遮咖,這世上最難降的妖魔是什么滩字? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮御吞,結果婚禮上麦箍,老公的妹妹穿的比我還像新娘。我一直安慰自己陶珠,他們只是感情好挟裂,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著揍诽,像睡著了一般诀蓉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寝姿,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天交排,我揣著相機與錄音划滋,去河邊找鬼饵筑。 笑死,一個胖子當著我的面吹牛处坪,可吹牛的內(nèi)容都是我干的根资。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼同窘,長吁一口氣:“原來是場噩夢啊……” “哼玄帕!你這毒婦竟也來了?” 一聲冷哼從身側響起想邦,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤裤纹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹰椒,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡锡移,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了漆际。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淆珊。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖奸汇,靈堂內(nèi)的尸體忽然破棺而出施符,到底是詐尸還是另有隱情,我是刑警寧澤擂找,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布戳吝,位于F島的核電站,受9級特大地震影響贯涎,放射性物質(zhì)發(fā)生泄漏骨坑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一柬采、第九天 我趴在偏房一處隱蔽的房頂上張望欢唾。 院中可真熱鬧,春花似錦粉捻、人聲如沸礁遣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祟霍。三九已至,卻和暖如春盈包,著一層夾襖步出監(jiān)牢的瞬間沸呐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工呢燥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留崭添,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓叛氨,卻偏偏與公主長得像呼渣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子寞埠,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361