cinely / mule-uploader

Stubborn HTML5 Amazon S3 uploader
http://mule-uploader.com/
MIT License
223 stars 43 forks source link

Ruby Backend #29

Closed robj closed 9 years ago

robj commented 10 years ago

The following ruby backend code will produce exactly the same signature as the python backend. (Verified by using Amazons test input at http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html )

I still get 'signature does not match' errors when mule POSTs to S3.

Bucket CORS

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

  AWS_ACCESS_KEY = Settings.s3.access_key_id
  AWS_SECRET = Settings.s3.secret_access_key
  BUCKET = 'uploads.stud.net'
  MIME_TYPE = 'application/octet-stream'
  AWS_REGION = 'us-east-1'

  def bin_to_hex(s)
    s.each_byte.map { |b| b.to_s(16) }.join
  end

  def signing_key

    key = AWS_SECRET
    regionName = AWS_REGION
    date = Time.now
    dateStamp = date.utc.strftime("%Y%m%d")
    serviceName = 's3'

    # http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html
    kDate    = OpenSSL::HMAC.digest('sha256', "AWS4" + key, dateStamp)
    kRegion  = OpenSSL::HMAC.digest('sha256', kDate, regionName)
    kService = OpenSSL::HMAC.digest('sha256', kRegion, serviceName)
    kSigning = OpenSSL::HMAC.digest('sha256', kService, "aws4_request")

    signature = bin_to_hex(kSigning)

    data = {

        date: date,
        signature: signature,
        access_key: AWS_ACCESS_KEY,
        region: AWS_REGION,
        bucket: BUCKET,
        backup_key: Random.rand(1000000).to_s,
        content_type: MIME_TYPE,
    }

    return json: data

  end

'/uploads/signing_key' returns:

{
   "date":"2014-05-13T01:35:05Z",
   "signature":"c72a95255cf4892acadf9b3fc24626b3f2a3cafb5bff12d313c21308f709e4b",
   "access_key":"AKIAJ242DT4M5QFWNLPA",
   "region":"us-east-1",
   "bucket":"uploads.stud.net",
   "content_type":"application/octet-stream"
}

server debug statements during request:

  date: 2014-05-13 01:35:05 UTC
  dateStamp: 20140513
  signature c72a95255cf4892acadf9b3fc24626b3f2a3cafb5bff12d313c21308f709e4b

S3:

successful OPTIONS method request headers (relevant)

Access-Control-Request-Method:POST
Access-Control-Request-Headers:x-amz-content-sha256, x-amz-acl, content-disposition, x-amz-date, authorization, content-type

unsuccessful POST method request headers (relevant)

Authorization:AWS4-HMAC-SHA256 Credential=AKIAJ242DT4M5QFWNLPA/20140513/us-east-1/s3/aws4_request, SignedHeaders=content-disposition;content-type;host;x-amz-acl;x-amz-content-sha256;x-amz-date, Signature=444705ce7fb6c571f68dfe0dbb6836b2f51bc0f51ecba228b8536421d11eff51
x-amz-acl:public-read
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:Tue, 13 May 2014 01:35:05 GMT

unsuccessful POST method response headers (all)

Access-Control-Allow-Methods:PUT, POST, DELETE, GET, HEAD
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Date, ETag, x-amz-server-side-encryption, x-amz-request-id, x-amz-id-2
Access-Control-Max-Age:999999
Content-Type:application/xml
Date:Tue, 13 May 2014 01:35:05 GMT
Server:AmazonS3
Transfer-Encoding:chunked
Vary:Origin, Access-Control-Request-Headers, Access-Control-Request-Method
x-amz-id-2:s0LgEOrG8qfjB4d8S1J7OK+oViENqPdsPVhxfFbnwOSF5Y7NdosFWFbHfdWj3fG4
x-amz-request-id:67D1BB98398B5D4D

unsuccessful POST method body

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 54 75 65 2c 20 31 33 20 4d 61 79 20 32 30 31 34 20 30 31 3a 33 35 3a 30 35 20 47 4d 54 0a 32 30 31 34 30 35 31 33 2f 75 73 2d 65 61 73 74 2d 31 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 62 66 31 64 34 36 35 33 31 30 65 64 66 33 65 32 61 66 30 36 32 63 31 37 64 66 38 39 32 35 64 66 61 31 65 63 39 35 61 36 37 39 34 64 35 30 39 38 64 38 36 39 31 37 66 38 61 63 30 66 64 66 36 33</StringToSignBytes><RequestId>67D1BB98398B5D4D</RequestId><CanonicalRequestBytes>50 4f 53 54 0a 2f 72 2f 72 6f 62 2f 31 33 39 39 39 34 34 38 39 36 33 33 37 0a 75 70 6c 6f 61 64 73 3d 0a 63 6f 6e 74 65 6e 74 2d 64 69 73 70 6f 73 69 74 69 6f 6e 3a 61 74 74 61 63 68 6d 65 6e 74 3b 20 66 69 6c 65 6e 61 6d 65 3d 72 61 79 6e 65 6f 5f 31 30 73 65 63 2e 6d 70 34 0a 63 6f 6e 74 65 6e 74 2d 74 79 70 65 3a 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6f 63 74 65 74 2d 73 74 72 65 61 6d 0a 68 6f 73 74 3a 75 70 6c 6f 61 64 73 2e 73 74 75 64 2e 6e 65 74 2e 73 33 2e 61 6d 61 7a 6f 6e 61 77 73 2e 63 6f 6d 0a 78 2d 61 6d 7a 2d 61 63 6c 3a 70 75 62 6c 69 63 2d 72 65 61 64 0a 78 2d 61 6d 7a 2d 63 6f 6e 74 65 6e 74 2d 73 68 61 32 35 36 3a 65 33 62 30 63 34 34 32 39 38 66 63 31 63 31 34 39 61 66 62 66 34 63 38 39 39 36 66 62 39 32 34 32 37 61 65 34 31 65 34 36 34 39 62 39 33 34 63 61 34 39 35 39 39 31 62 37 38 35 32 62 38 35 35 0a 78 2d 61 6d 7a 2d 64 61 74 65 3a 54 75 65 2c 20 31 33 20 4d 61 79 20 32 30 31 34 20 30 31 3a 33 35 3a 30 35 20 47 4d 54 0a 0a 63 6f 6e 74 65 6e 74 2d 64 69 73 70 6f 73 69 74 69 6f 6e 3b 63 6f 6e 74 65 6e 74 2d 74 79 70 65 3b 68 6f 73 74 3b 78 2d 61 6d 7a 2d 61 63 6c 3b 78 2d 61 6d 7a 2d 63 6f 6e 74 65 6e 74 2d 73 68 61 32 35 36 3b 78 2d 61 6d 7a 2d 64 61 74 65 0a 65 33 62 30 63 34 34 32 39 38 66 63 31 63 31 34 39 61 66 62 66 34 63 38 39 39 36 66 62 39 32 34 32 37 61 65 34 31 65 34 36 34 39 62 39 33 34 63 61 34 39 35 39 39 31 62 37 38 35 32 62 38 35 35</CanonicalRequestBytes><CanonicalRequest>POST
robj commented 10 years ago

of note to any ruby developers, while not helpful in this case (where signing is done in JS), a gem does exist for server side URL signing

https://github.com/cmdrkeene/aws4

bordo commented 10 years ago

@robj any success on this issue? I have same results.

bordo commented 10 years ago

@robj Works for me now. One chage needs to be made in your code.

def bin_to_hex(s)
  s.unpack('H*')[0]
end
dereksweet commented 9 years ago

@bordo Thanks so much! That was exactly what I needed. Works for me now too..

gabipurcaru commented 9 years ago

I suppose this is fixed, so I'll close it.