Подтвердить что ты не робот

Как загрузить файлы с Android на Amazon S3 БЕЗ использования SDK

Я работал над использованием REST API Amazon S3 для загрузки файла с моего устройства Android в ведро, которое у меня есть. У меня есть KEY и SECRET_KEY, но я не уверен, как правильно генерировать подпись, которую они ищут в своих запросах. Я использую HttpPut на своих серверах, но не знаю, как правильно генерировать signatureValue. Пока что у меня есть:

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()));

Затем вот методы, которые я использую для генерации значения подписи:

    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;
    }

Я использовал тестер Signature Amazon S3, и моя строка была правильной, но я никогда не получал правильное кодированное значение. Спасибо за любую помощь или толчок в правильном направлении.

4b9b3361

Ответ 1

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

[Ссылка: https://aws.amazon.com/articles/1434]

В приведенной выше ссылке также описаны входные параметры в HTTP-запросе.

Ответ 2

Я бы дважды заметил, что дата соответствует ожидаемым и отправляется в заголовках http (вы устанавливаете заголовок "x-amz-date"?), это дало мне некоторую головную боль при подписании запросов "вручную".

Кроме того, добавление сообщения об ошибке из S3 может помочь нам понять, что не так, и помочь вам.