2

edit 2: i deleted the filed awskeyid - so now s3 accepts the x-amz-signature field, but now i get back an error that : The request signature we calculated does not match the signature you provided. Check your key and signing method

so u guess im calculating the signature wrong , any ideas?

edit: I have edited the code according to the documnation i found, i think im calculating the signature right, but it still doesnt work, when I put it in the form in a field named "signature" i get an error back that this mechanism isnt supoorted and i should use the new one, but if i change the name of signature field to x-amz-signature i get back an error that there is no field named "signature"

i have a working form to upload a file directly from browser to amazon s3, i have switched my bucket to frankfurt region which dosnt support the old policy signing.

so i triued to edit my form and the policy created , but with nu luck any help will be appreciated

this is my policy:

    $policy = json_encode(array(
            'expiration' => date('Y-m-d\TG:i:s\Z', strtotime('+6 hours')),
            'conditions' => array(
                    array(
                            'bucket' => $data['bucket']
                    ),
                    array(
                            'acl' => 'private'
                    ),
                    array(
                            'starts-with',
                            '$key',
                            'Zips/Uploads'
                    ),
                    array(
                            'content-length-range', 0, 500000000
                    ),
                    array(
                            "x-amz-algorithm"=> "AWS4-HMAC-SHA256"
                    ),
                    array (
                            "x-amz-credential"=> AMAZON_KEY."/20160111/eu-central-1/s3/aws4_request"
                    ),
                    array(
                            "x-amz-date"=> "20151101T000000Z"
                    ),

                )

    ));

    $data['base64Policy'] = base64_encode($policy);
    $signing_key1 = hash_hmac('sha256', "AWS4" .AMAZON_SECRET_KEY , "20151101", true);
    $signing_key2 = hash_hmac('sha256', $signing_key1, AMAZON_REGION,true); 
    $signing_key3 = hash_hmac('sha256', $signing_key2, "s3",true);
    $signing_key4 = hash_hmac('sha256', $signing_key3, "aws4_request",true);x
    $data['signature'] = base64_encode(hash_hmac('sha256',$signing_key4, $data['base64Policy'],true));

and this is the form I'm using

<form class="startfileupload" action="//s3.eu-central-1.amazonaws.com/<?php echo $bucket; ?>/" method="post" enctype="multipart/form-data">
<input type="hidden" name="key" value="${filename}" /><br />
<input type="hidden" name="acl" value="private" />
<input type="hidden" name="X-amz-Algorithm" value="AWS4-HMAC-SHA256" />
<input type="hidden" name="X-Amz-Credential" value="<?php echo $accesskey; ?>/20160111/eu-central-1/s3/aws4_request" />
<input type="hidden" name="X-Amz-Date" value="20151101T000000Z" />
<input type="hidden" name="policy" value="<?php echo $base64Policy; ?>">
<input type="hidden" name="X-Amz-Signature" value="<?php echo $signature; ?>">
<input type="file" name="file" /> <br />

using this form im getting back an error from amazon:

InvalidRequestThe authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.

what am i doing wrong? I tried reding the documantion and examples, but didnt really got me far.

thx!

Daniel Katzan
  • 526
  • 1
  • 7
  • 29
  • S3 moved from Signature v2 to Signature v4 a little while back, so the code that signs the request needs to be updated. Are you using the official SDK? They handle all of this for you. – Ryan Parman Jan 11 '15 at 00:21
  • This question appears to be off-topic because it is about a code snippet written for V2, which will require a substantial rewrite in order to match the documented requirements for V4 authentication of `POST` uploads: http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html – Michael - sqlbot Jan 11 '15 at 01:24
  • I got both the official and the laravel sdk for aws, i read the documantion but still find it very hard to understand how to create my policy – Daniel Katzan Jan 11 '15 at 14:57
  • @RyanParman i cant find how does the official sdk handles that for me? – Daniel Katzan Jan 11 '15 at 16:04
  • Look at https://github.com/aws/aws-sdk-php/blob/master/src/Aws/S3/Model/PostObject.php – Jeremy Lindblom Jan 12 '15 at 19:47
  • If you use the official SDK, you don't have to calculate the signature yourself. The SDK will calculate it for you. – Ryan Parman Jan 13 '15 at 06:23
  • Yes, what Jeremy posted. That solves all of your problems right there. – Ryan Parman Jan 13 '15 at 06:24
  • I just wrote an article on it (sorry for self-promotion, but it's relevant): http://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/ – Edd Turtle Mar 07 '15 at 11:07

1 Answers1

2

According to this answer (Java version):

Using some help I've found the answer, which was a combination of 2 missing pieces (one of which was referred to in the comments):

1) Need to set this:

System.setProperty(SDKGlobalConfiguration.ENABLE_S3_SIGV4_SYSTEM_PROPERTY, "true");

2) Must set the "endPoint" (which was not required for upload or download):

s3Client.setEndpoint(endpoint);

Optionally it might be useful to also add this:

s3Client.setS3ClientOptions(new S3ClientOptions().withPathStyleAccess(true));
Bahadir Tasdemir
  • 10,325
  • 4
  • 49
  • 61