aws-sdk-js: using pre-signed url for PUT returns SignatureDoesNotMatch using SSE-C

If I use ServerSideEncryption this entire workflow is perfect. I can upload a file using the pre-signed url and offer a link to my end users without having to send any header information (in the PUT or GET).

However, switching over to use SSECustomerKey causes the same workflow to error out.

It generates the proper signed url for a PUT request, but when I attempt to upload it fails with a SignatureDoesNotMatch error.

I have seen in some other tickets that you have to send the same headers across when using a signedurl. However, I’m not sending those headers across when I use ServerSideEencryption and it works fine.

I was hoping and assumed that because the signed url includes the header information in the query string that it would just work. Which it does for sse. The moment I switch it to sse-c it errors out.

If I do have to send the headers for sse-c… how am I supposed to offer a link for people to click on our site? And why does it work for sse, but not sse-c?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 35 (12 by maintainers)

Most upvoted comments

hey @Timer here is the OpenResty configuration we used for prototyping the solution. You need to use openresty, as it has functionality that isn’t available with nginx ootb.

error_log 			       logs/error.log;

events {
	worker_connections	   1024;
}

http {
    client_max_body_size            20M;
	proxy_headers_hash_bucket_size	1024;
	map $is_args $algorithm {
        default $arg_x-amz-server-side-encryption-customer-algorithm;
    }

    map $is_args $key {
        default $arg_x-amz-server-side-encryption-customer-key;
    }

    map $is_args $md5 {
        default $arg_x-amz-server-side-encryption-customer-key-md5;
    }

    map $is_args $ct {
        default $arg_content-type;
    }

    server {
	
        listen 8888;

	location /hc {
		return 200 'hello';		
	}

        location ~* ^/storage/(.*) {
            if ($request_method = OPTIONS ) {
			     add_header Access-Control-Allow-Origin "*";
			     add_header Access-Control-Allow-Methods "GET, OPTIONS, PUT";
			     add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With, Cache-Control, Accept, Origin, X-Session-ID,Access-Control-Allow-Origin";
			     return 200;
		    }
		
            resolver                 8.8.8.8 valid=300s;
            resolver_timeout         10s;

            set_unescape_uri	     $sig $arg_signature;
            set_unescape_uri	     $ak $arg_awsAccessKeyId;

            set $ct                 'Content-Type=$ct';
            set $s3_bucket          'your-bucket.s3.amazonaws.com';

            set $aws_access_key     'AWSAccessKeyId=$ak';
            set $url_expires        'Expires=$arg_expires';
            set $url_signature      'Signature=$arg_signature';
            set $url_full           '$1?$aws_access_key&$url_expires&$url_signature&ct';

            set_unescape_uri	     $a $algorithm;
            set_unescape_uri	     $k $key;
            set_unescape_uri	     $m $md5;

            proxy_http_version       1.1;
            proxy_set_header         Host $s3_bucket;
            proxy_set_header         Authorization '';
            proxy_hide_header        x-amz-id-2;
            proxy_hide_header        x-amz-request-id;
            proxy_hide_header        Set-Cookie;
            proxy_ignore_headers     "Set-Cookie";
            proxy_buffering          off;
            proxy_intercept_errors   on;

            proxy_set_header         x-amz-server-side-encryption-customer-algorithm 	$a;
            proxy_set_header         x-amz-server-side-encryption-customer-key 		$k;
            proxy_set_header         x-amz-server-side-encryption-customer-key-md5 		$m;

            proxy_pass               https://$s3_bucket/$url_full;
        }
    }
}