Why i have the message Transfer Encoding is not implementing by AWS (Use with CURL)

  amazon-s3, amazon-web-services, api, c++

I try to create an application for use the AWS API. For this, i programme in c++ with the library CURL. I test my application with "GET" request and it’s work. After, i test with the "PUT" request but, i have an error :

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NotImplemented</Code>
<Message>A header you provided implies functionality that is not implemented</Message>
<Header>Transfer-Encoding</Header>
<RequestId> *** </RequestId>
<HostId> ***</HostId>
</Error>

my code :


   

    #include <stdio.h>
       #include <curl/curl.h>
    
    #include <iostream>
    #include "sha256_calc.h"
    #include <ctime>
    #include <hmac_sha256/hmac_sha256.h>
    #include <vector>
    
    using std::string;
    using std::cout;
    using std::endl;
    
    
    #define BUCKET_NAME "<my bucket>"
    #define REGION "eu-west-3"
    #define METHODE_PUT "PUT"
    #define SERVICE_S3 "s3"
    #define ALGORITHM "AWS4-HMAC-SHA256"
    
    #define ACCESS_KEY "<My access Key>"
    #define SECRET_KEY "<My secret access Key>"
    
    #define SHA256_HASH_SIZE 32
    
    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
        size_t written = fwrite(ptr, size, nmemb, stream);
        return written;
    }
    
    
    string vector_to_string (std::vector<uint8_t> val)
    {
        string retour = "";
    
        char res[2048];
        char intermedaire[2];
    
        for (int i = 0; i < SHA256_HASH_SIZE; i++)
        {
            //sprintf(intermedaire,"%x",val[i]);
            retour += val[i];
        }
        return retour;
    }
    
    std::vector<uint8_t> sign(string key,string msg)
    {
         std::vector<uint8_t> out(SHA256_HASH_SIZE);
         hmac_sha256(key.data(), key.size(), msg.data(), msg.size(),out.data(), out.size());
         return out;
    }
    
    
    std::vector<uint8_t> getSignatureKey(string key,string dateStamp,string regionName,string 
    serviceName)
    {
        printf("key : %s n" , key.c_str());
    
        std::vector<uint8_t> kDate = sign("AWS4" + key, dateStamp);
        for (int i = 0; i < SHA256_HASH_SIZE; i++)
        {
            printf("%dn",kDate[i]);
        }
        printf("n");
    
        string buff = vector_to_string (kDate);
        std::vector<uint8_t> kRegion = sign(buff, regionName);
        for (int i = 0; i < SHA256_HASH_SIZE; i++)
        {
            printf("%dn",kRegion[i]);
        }
        printf("n");
    
        buff = vector_to_string (kRegion);
        std::vector<uint8_t> kService = sign(buff, serviceName);
        for (int i = 0; i < SHA256_HASH_SIZE; i++)
        {
            printf("%dn",kService[i]);
        }
        printf("n");
    
        buff = vector_to_string (kService);
    
    
        std::vector<uint8_t> kSigning = sign(buff, "aws4_request");
        for (int i = 0; i < SHA256_HASH_SIZE; i++)
        {
            printf("%dn",kSigning[i]);
        }
        printf("n");
    
         return kSigning;
    }
    
    
    int main(void)
    {
      CURL *curl;
      CURLcode res;
      curl_slist *chunk=NULL;
    
      char *file = (char*)"fichier/CR1-12_11.pdf";
      char end_point[2048];
      char host[1024];
      sprintf(host,"%s.s3.%s.amazonaws.com",BUCKET_NAME,REGION);
      sprintf(end_point,"https://%s/fichier/CR1-12_11.pdf",host);
    
    
      time_t now = time(0);
      tm *gmtm = gmtime(&now);
    
      char amzdate[32];
      char datestamp[32];
      sprintf(amzdate,"%04d%02d%02dT%02d%02d%02dZ",gmtm->tm_year+1900,gmtm->tm_mon+1,gmtm- 
      >tm_mday,gmtm->tm_hour,gmtm->tm_min,gmtm->tm_sec);
      //sprintf(amzdate,"%04d%02d%02dT%02d%02d%02dZ",1900+gmtm->tm_year,gmtm->tm_mon+1,gmtm- 
      >tm_mday,8,45,25);
      sprintf(datestamp,"%04d%02d%02d",1900+gmtm->tm_year,gmtm->tm_mon+1,gmtm->tm_mday);
    
      cout << gmtm->tm_hour << endl;
    
    
      string canonical_uri;
      canonical_uri = (string)"/" + file;
    
      string test = "";
      string payload_hash = sha256(test);
    
      string canonical_headers;
      canonical_headers = (string)"host:" + host + "nx-amz-content-sha256:" + payload_hash + 
      "nx-amz-date:" + amzdate + "n";
    
      string signed_header = "host;x-amz-content-sha256;x-amz-date";
    
      string canonicale_request;
      canonicale_request = (string) METHODE_PUT + "n" + canonical_uri + "nn" + 
      canonical_headers + "n" + signed_header + "n" + payload_hash;
    
      printf ("%sn",canonicale_request.c_str());
    
      string credential_scope;
      credential_scope = (string) datestamp + "/" + REGION + "/" + SERVICE_S3 + "/aws4_request";
    
    
      string string_to_sign;
      string_to_sign = (string) ALGORITHM +  "n" + amzdate + "n" + credential_scope + "n" + 
      sha256(canonicale_request);
    
      char *pCACertFile = (char*)"<file>";
    
      std::vector<uint8_t> signing_key ;
      signing_key  = getSignatureKey(SECRET_KEY,datestamp,REGION,SERVICE_S3);
      string buff = vector_to_string(signing_key);
    
      std::vector<uint8_t> signature(SHA256_HASH_SIZE);
      string string_to_sign_buff = string_to_sign;
    
      hmac_sha256(buff.data(), buff.size(), string_to_sign_buff.data(), 
      string_to_sign_buff.size(),signature.data(), signature.size());
    
      printf("n");
      for (int i = 0; i < SHA256_HASH_SIZE; i++)
      {
          printf("%dn",signing_key[i]);
      }
      printf("n");
    
    
      printf("n %s n",string_to_sign_buff.c_str());
    
      for (int i = 0; i < SHA256_HASH_SIZE; i++)
      {
          printf("%dn",signature[i]);
      }
    
    
      FILE *fileOpen = fopen("<file>","rb");
      FILE *fileOpenWrite = fopen("<file>","wb");
      if (fileOpen)
      {
          printf("fichier ok n");
      }
      else
      {
          printf("erreurn");
      }
    
      FILE *f = fopen(pCACertFile,"r");
    
    
      if (f)
      {
          fclose(f);
      }
      else
      {
          printf("certificat abscent");
      }
    
      string buffUser="";
      curl=curl_easy_init();
      //curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
    
      curl_easy_setopt(curl, CURLOPT_URL, end_point);
      curl_easy_setopt(curl, CURLOPT_PUT, 1);
    
      buff = credential_scope;
      buff = ACCESS_KEY + string("/") + buff;
      printf("%sn",buff.c_str());
    
    
      string test_val = "";
      char tampon[8];
      for (int i = 0; i < SHA256_HASH_SIZE; i++)
      {
          sprintf(tampon,"%02x",signature[i]);
          test_val += tampon;
      }
    
      buffUser = (string) "Authorization:"+ ALGORITHM +" Credential="+ ACCESS_KEY + "/" + 
      credential_scope + ",SignedHeaders=" + signed_header + ",Signature=" + test_val;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buffUser = "x-amz-content-sha256:" + payload_hash;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buff = amzdate;
      buffUser = "x-amz-date:" + buff;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buffUser = "x-amz-decoded-content-length: 1024";
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      curl_easy_setopt(curl,CURLOPT_HTTPHEADER,chunk);
    
      curl_easy_setopt(curl,CURLOPT_READDATA,fileOpen);
    
        res = curl_easy_perform(curl);
    
    
        if(res != CURLE_OK)
          fprintf(stderr, "curl_easy_perform() failed: %sn",
                  curl_easy_strerror(res));
    
        curl_easy_cleanup(curl);
     // }
        fclose (fileOpen);
      printf("Fin programme n");
      return 0;
    }

The signature fonction, i can verify this with an other programme and, the GET methode use this.

Source: Windows Questions C++

LEAVE A COMMENT