2012-01-05 3 views
6

Amazon S3 업로드 정책의 서명 생성에 어려움을 겪고 있습니다. 나는이 일을 한 순간에했지만 더 이상 맹세하지 않았다. 어떤 도움이라도 대단히 감사 할 것입니다. 신선한 눈이 필요해. Amazon S3 Policy Java 로그인

Amazon S3 Signature Tester의 출력에 비해

, 나는 동일한 서명을 받고 하지은입니다. 그러나, 그 도구에서 나오는 서명을 직접 사용하면 모든 것이 잘 동작합니다. 문제는 확실히 서명 과정에 있습니다. 또한 해당 도구에서 나오는 16 진수로 디코딩 된 "서명 할 문자열"은 입력 정책과 동일합니다.

AWS의 문서는 the process for constructing a policy signature이 같이 가야 말 :

  1. 인코딩 UTF-8을 사용하여 정책.
  2. Base64를 사용하여 UTF-8 바이트를 인코딩합니다.
  3. HMAC SHA-1을 사용하여 비밀 키로 정책에 서명하십시오.
  4. Base64를 사용하여 SHA-1 서명을 인코딩합니다.

충분히 똑바로 보인다. 모호성을위한 유일한 장소는 # 3에있을 수 있습니다. AWS 문서는 a sample snippet for generating HMAC-SHA1이며 이는 other Java cryptography examples과 일치합니다.

저는 Apache Commons v2.6의 Base64 구현을 사용하고 있습니다.

import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 
import org.apache.commons.codec.binary.Base64; 

/* ... */ 

private static final String UTF8 = "UTF-8"; 
private static final String HMACSHA1 = "HmacSHA1"; 

public static String sign(String secret, String data) { 
    byte[] dataBytes = data.getBytes(UTF8); 
    byte[] secretBytes = secret.getBytes(UTF8); 

    SecretKeySpec signingKey = new SecretKeySpec(secretBytes, HMACSHA1); 

    Mac mac = Mac.getInstance(HMACSHA1); 
    mac.init(signingKey); 
    byte[] signature = mac.doFinal(dataBytes); 

    return Base64.encodeBase64String(signature); 
} 

을 그리고처럼 다음이 서명 내 사용은 같습니다 : 내 서명 코드는 기본적으로 다음과 같습니다

String signature = sign(
    /* AWS Secret Access Key copied directly out of the AWS Console */, 
    /* policy properly serialized as JSON */); 

답변

5

좋아, 나는 그것을 발견했다. 명백하게 오늘 나는 효과적으로 단계 # 2를 뛰어 넘었다. JSON을 Base64로 인코딩했지만 Base64 문자열이 아닌 JSON 문자열에 직접 서명합니다.

3 단계는 HMAC SHA-1을 사용하여 비밀 번호로 Base64 방침에 서명하도록 수정해야합니다.

다른 사람들도 비슷한 문제를 겪을 경우를 대비하여이 내용을 남겨 둘 것입니다.

-1
String policy_document = 
     "{\"expiration\": \"2009-01-01T00:00:00Z\"," + 
     "\"conditions\": [" + 
      "{\"bucket\": \"s3-bucket\"}," + 
      "[\"starts-with\", \"$key\", \"uploads/\"]," + 
      "{\"acl\": \"private\"}," + 
      "{\"success_action_redirect\": \"http://localhost/\"}," + 
      "[\"starts-with\", \"$Content-Type\", \"\"]," + 
      "[\"content-length-range\", 0, 1048576]" + 
     "]" + 
     "}"; 

    // Calculate policy and signature values from the given policy document and AWS credentials. 
    String policy = new String(
     Base64.encodeBase64(policy_document.getBytes("UTF-8")), "ASCII"); 

    Mac hmac = Mac.getInstance("HmacSHA1"); 
    hmac.init(new SecretKeySpec(
     aws_secret_key.getBytes("UTF-8"), "HmacSHA1")); 
    String signature = new String(
     Base64.encodeBase64(hmac.doFinal(policy.getBytes("UTF-8"))), "ASCII"); 
3

이제이 절차가 공식적으로 지원됩니다. http://aws.amazon.com/articles/1434

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

* 또한이 제공 한 문제에 대한 포스트 및 솔루션의 의견에서 일부 발견 문제로이 예를 들어 윈도우 구현을 조심하십시오.

결과

그러나이 http://s3.amazonaws.com/doc/s3-example-code/post/post_sample.html

하여 확인할 수 있습니다, 일부는이 "org.apache.commons.codec.binary.Base64는"이 때문에 더 나은 말했다. http://www.asgarli.net/2011/03/replacing-sunmiscbase64encoder-and.html