Skip to content

Instantly share code, notes, and snippets.

@trevorrowe
Created March 28, 2015 03:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trevorrowe/49bfb9d59f83ad450a9e to your computer and use it in GitHub Desktop.
Save trevorrowe/49bfb9d59f83ad450a9e to your computer and use it in GitHub Desktop.
Demonstration of using pre-signed GET url to download a server-side-encrypted with customer key from Amazon S3
require 'aws-sdk'
require 'openssl'
bucket_name = 'bucket-name'
object_key = 'object-key'
# patch for `aws-sdk` v2 gem (needed for versions <= v2.0.33, patch will be applied shortly to master)
class Aws::Signers::V4
def presigned_url(request, options = {})
now = Time.now.utc.strftime("%Y%m%dT%H%M%SZ")
body_digest = options[:body_digest] || hexdigest(request.body)
request.headers.delete('User-Agent')
request.headers['Host'] = request.endpoint.host
params = Aws::Query::ParamList.new
params.set("X-Amz-Algorithm", "AWS4-HMAC-SHA256")
params.set("X-Amz-Credential", credential(now))
params.set("X-Amz-Date", now)
params.set("X-Amz-Expires", options[:expires_in].to_s)
params.set("X-Amz-SignedHeaders", signed_headers(request))
params.set('X-Amz-Security-Token', credentials.session_token) if
credentials.session_token
endpoint = request.endpoint
if endpoint.query
endpoint.query += '&' + params.to_s
else
endpoint.query = params.to_s
end
endpoint.to_s + '&X-Amz-Signature=' + signature(request, now, body_digest)
end
end
# my "customer-provided-key"
cpk = OpenSSL::Cipher::AES.new(256, :CBC).random_key
# upload an object using Server-Side-Encryption with customer provided key
obj = Aws::S3::Object.new(bucket_name, object_key)
obj.put(
body: 'Hello World!',
sse_customer_algorithm: 'AES256',
sse_customer_key: cpk)
# download the object using the `aws-sdk`
obj.get(sse_customer_algorithm: 'AES256', sse_customer_key: cpk).body.read
#=> 'Hello World!'
# generate a presigned url
url = obj.presigned_url(:get,
sse_customer_algorithm: 'AES256',
sse_customer_key: cpk)
# use Ruby Net::HTTP to GET the encrypted object
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri.request_uri, {
"x-amz-server-side-encryption-customer-algorithm" => 'AES256',
"x-amz-server-side-encryption-customer-key" => Base64.encode64(cpk),
"x-amz-server-side-encryption-customer-key-MD5" => Base64.encode64(OpenSSL::Digest::MD5.digest(cpk))
})
resp = http.request(request)
puts resp.body
#=> Hello World!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment