Skip to content

Instantly share code, notes, and snippets.

@themarcelor
Created August 21, 2017 11:39
Show Gist options
  • Save themarcelor/e09a25c722c390c41a456173c93d9125 to your computer and use it in GitHub Desktop.
Save themarcelor/e09a25c722c390c41a456173c93d9125 to your computer and use it in GitHub Desktop.
############ User input for AWS Access key and AWS Secret key
echo "Please provide your S3 Access Key: "
read -s AWSID
echo "Please provide your S3 Secret key:"
read -s AWSSEC
calculate_signature () {
AWSSEC=$1
x_amz_date_short=$2
region=$3
service=$4
string_to_sign=$5
hex_secret=$(printf "AWS4$AWSSEC" | xxd -p -c 256)
digest=$(printf "$x_amz_date_short" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$hex_secret)
digest="${digest#* }"
digest=$(printf "$region" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$digest)
digest="${digest#* }"
digest=$(printf "$service" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$digest)
digest="${digest#* }"
digest=$(printf "aws4_request" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$digest)
signing_key="${digest#* }"
signature=$(printf "$string_to_sign" | openssl dgst -binary -hex -sha256 -mac HMAC -macopt hexkey:$signing_key)
}
create_string_to_sign () {
x_amz_date_long=$1
x_amz_date_short=$2
region=$3
service=$4
hashed_canonical_request=$5
string_to_sign="AWS4-HMAC-SHA256
$x_amz_date_long
$x_amz_date_short/$region/$service/aws4_request
$hashed_canonical_request"
}
create_canonical_request () {
method=$1
uri=$2
query_string=$3
service=$4
payload=$5
host=$6
x_amz_date_long=$7
the_kms_key=$8
http_request_method="$method"
canonical_uri="$uri"
canonical_query_string="$query_string"
################################################
# KMS HEADERS
################################################
if [ "$service" == "kms" ]; then
hashed_payload=$(echo -n "$payload" | openssl dgst -sha256 | awk -F ' ' '{print $2}')
# Identation looks a bit funny here but the aws v4 signature doesnt' like additional white spaces
canonical_headers="content-type:application/x-amz-json-1.1
host:$host
x-amz-date:$x_amz_date_long
x-amz-target:TrentService.ListAliases"
signed_headers="content-type;host;x-amz-date;x-amz-target"
################################################
# S3 HEADERS
################################################
elif [ "$service" == "s3" ]; then
################################################
# FILE UPLOAD
################################################
if [ -z "$query_string" ]; then
# just a normal file upload ( file size < 5GB )
hashed_payload=$(openssl dgst -sha256 $payload | awk -F ' ' '{print $2}')
canonical_headers="host:$host
x-amz-content-sha256:$hashed_payload
x-amz-date:$x_amz_date_long
x-amz-server-side-encryption:aws:kms
x-amz-server-side-encryption-aws-kms-key-id:$the_kms_key"
signed_headers="host;x-amz-content-sha256;x-amz-date;x-amz-server-side-encryption;x-amz-server-side-encryption-aws-kms-key-id"
else
if [ -z "$payload" ]; then
################################################
# MULTIPART UPLOAD - INITIATE
################################################
# empty payload means that this request is either initiating or completing a multipart upload
# hardcode hash from empty string and provide md5 from the original file
hashed_payload="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
amz_meta_md5=$(openssl dgst -binary -md5 "$FILE" | openssl enc -base64)
canonical_headers="host:$host
x-amz-content-sha256:$hashed_payload
x-amz-date:$x_amz_date_long
x-amz-meta-md5:$amz_meta_md5
x-amz-server-side-encryption:aws:kms
x-amz-server-side-encryption-aws-kms-key-id:$the_kms_key"
signed_headers="host;x-amz-content-sha256;x-amz-date;x-amz-meta-md5;x-amz-server-side-encryption;x-amz-server-side-encryption-aws-kms-key-id"
else
################################################
# MULTIPART UPLOAD - FILE PART
################################################
echo "##### FILE PART: $payload"
# the presence of a payload means this request is uploading a file part
# take sha256 and md5 hashes from the payload (file part)
hashed_payload=$(openssl dgst -sha256 $payload | awk -F ' ' '{print $2}')
canonical_headers="host:$host
x-amz-content-sha256:$hashed_payload
x-amz-date:$x_amz_date_long"
signed_headers="host;x-amz-content-sha256;x-amz-date"
fi
fi
else
echo "S3 file upload failed. This service { $service } is not supported."
exit 1
fi
canonical_request="$http_request_method
$canonical_uri
$canonical_query_string
$canonical_headers
$signed_headers
$hashed_payload"
hashed_canonical_request=$(echo -n "$canonical_request" | openssl dgst -sha256 | awk -F ' ' '{print $2}')
}
assemble_aws_v4_signature () {
method=$1
service=$2
region=$3
host=$4
uri=$5
query_string=$6
payload=$7
the_kms_key=$8
x_amz_date_long=$(date -u '+%Y%m%dT%H%M%SZ')
x_amz_date_short="${x_amz_date_long/T*}"
create_canonical_request "${method}" "${uri}" "${query_string}" "${service}" "${payload}" "${host}" "${x_amz_date_long}" "${the_kms_key}"
create_string_to_sign "${x_amz_date_long}" "${x_amz_date_short}" "${region}" "${service}" "${hashed_canonical_request}"
calculate_signature "${AWSSEC}" "${x_amz_date_short}" "${region}" "${service}" "${string_to_sign}"
signature="${signature#* }"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment