Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload files from Android to Amazon S3 WITHOUT using the SDK

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.

like image 479
kevin.w.johnson Avatar asked Oct 09 '13 19:10

kevin.w.johnson


People also ask

How do I upload files to Amazon S3?

In the Amazon S3 console, choose the bucket where you want to upload an object, choose Upload, and then choose Add Files. In the file selection dialog box, find the file that you want to upload, choose it, choose Open, and then choose Start Upload. You can watch the progress of the upload in the Transfer pane.

How many ways you can upload data to S3?

There are three ways in which you can upload a file to amazon S3.


2 Answers

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", "");

[Ref: https://aws.amazon.com/articles/1434]

The link above also describes the input parameteres in the HTTP request.

like image 68
thepace Avatar answered Oct 16 '22 15:10

thepace


I would double check that the date matches what is expected and sent in the http headers (are you setting the "x-amz-date" header?), it gave me some headache when signing requests "manually".

Also, adding the error message from S3 might help us to understand what is wrong and help you.

like image 37
Julio Faerman Avatar answered Oct 16 '22 15:10

Julio Faerman