Back

Explore Courses Blog Tutorials Interview Questions
0 votes
2 views
in AWS by (19.1k points)

I've been working on using the REST API of Amazon's S3 to upload a file from my Android device to a bucket I have. I have the KEY and SECRET_KEY but am not sure how to properly generate the signatureValue they are looking for in their requests. I'm using a HttpPut to their servers, but am not sure how to properly generate the signatureValue. So far here's what I have:

HttpPut put = new HttpPut(URL);

            String fmt = "EEE, dd MMM yyyy HH:mm:ss ";

            SimpleDateFormat format = new SimpleDateFormat(fmt, Locale.US);

            format.setTimeZone(TimeZone.getTimeZone("GMT"));

            String method = "PUT";

            String contentType = "application/octet-stream";

            String date = format.format(new Date()) + "GMT";

            String bucket = "/test-bucket52809/";

            StringBuffer buf = new StringBuffer();

            buf.append(method).append("\n\n");

            buf.append(contentType).append("\n");

            buf.append(date).append("\n");

            buf.append(bucket);

            String signature = percentEncodeRfc3986(hmac(buf.toString()));

Then here are the methods I use to generate the signature value:

    private void setupMac() throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException

    {

        byte[] secretyKeyBytes = KEY_SECRET.getBytes("UTF-8");

        signingKey = new SecretKeySpec(secretyKeyBytes, "HmacSHA256");

        mac = Mac.getInstance("HmacSHA256");

        mac.init(signingKey);

    }

    private String hmac(String stringToSign) {

        String signature = null;

        byte[] data;

        byte[] rawHmac;

        try {

            data = stringToSign.getBytes("UTF-8");

            rawHmac = mac.doFinal(data);

            signature = new String(Base64.encode(rawHmac, Base64.DEFAULT));

        } catch (UnsupportedEncodingException e) {

            throw new RuntimeException("UTF-8" + " is unsupported!", e);

        }

        return signature;

    }

    private String percentEncodeRfc3986(String s) {

        String out;

        try {

            out = URLEncoder.encode(s, "UTF-8").replace("+", "%20")

                    .replace("*", "%2A").replace("%7E", "~");

        } catch (UnsupportedEncodingException e) {

            out = s;

        }

        return out;

    }

I used the Amazon S3 Signature tester, and my string was correct, but I never got the right encoded value. Thanks for any help or a push in the right direction.

1 Answer

0 votes
by (44.4k points)

Use this:

import sun.misc.BASE64Encoder;

import javax.crypto.Mac;

import javax.crypto.spec.SecretKeySpec;

String policy = (new BASE64Encoder()).encode(

    policy_document.getBytes("UTF-8")).replaceAll("\n","").replaceAll("\r","");

Mac hmac = Mac.getInstance("HmacSHA1");

hmac.init(new SecretKeySpec(

    aws_secret_key.getBytes("UTF-8"), "HmacSHA1"));

String signature = (new BASE64Encoder()).encode(

    hmac.doFinal(policy.getBytes("UTF-8")))

    .replaceAll("\n", "");

Related questions

Want to get 50% Hike on your Salary?

Learn how we helped 50,000+ professionals like you !

0 votes
1 answer
0 votes
1 answer

Browse Categories

...