2012-01-05 29 views
6

Vì một số lý do, tôi đang đấu tranh với việc tạo chữ ký cho chính sách tải lên Amazon S3 của tôi. Tôi thề rằng tôi đã làm việc này tại một thời điểm nhưng không còn nữa. Bất kì sự trợ giúp nào đều được đánh giá cao. Tôi cần một bộ mắt mới.Chính sách Amazon S3 Đăng nhập bằng Java

Khi so sánh với đầu ra từ Amazon S3 Signature Tester, tôi là không phải là có chữ ký giống nhau. Tuy nhiên, khi tôi trực tiếp sử dụng chữ ký sắp ra của công cụ đó, mọi thứ đều hoạt động tốt. Vì vậy, vấn đề là chắc chắn trong quá trình ký kết của tôi. Ngoài ra, giải mã thập lục phân "Chuỗi được ký" sắp ra khỏi công cụ đó giống hệt với chính sách nhập của tôi được ký.

Các tài liệu AWS nói the process for constructing a policy signature nên đi như thế này:

  1. Mã hóa các chính sách sử dụng UTF-8.
  2. Mã hóa các byte UTF-8 đó bằng Base64.
  3. Ký chính sách bằng Khóa truy cập bí mật của bạn bằng HMAC SHA-1.
  4. Mã hóa chữ ký SHA-1 bằng Base64.

Dường như đủ về phía trước. Nơi duy nhất cho sự mơ hồ có thể ở vị trí thứ 3. Tài liệu AWS hiển thị a sample snippet for generating HMAC-SHA1 và điều này phù hợp với other Java cryptography examples Tôi đã xem.

Tôi đang sử dụng v1.6 triển khai Apache Commons của Base64. mã ký của tôi về cơ bản trông như thế này:

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

Và sau đó sử dụng của tôi ký này trông giống như:

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

Trả lời

5

Được rồi, tôi tìm thấy nó. Rõ ràng hôm nay tôi đã bỏ qua bướC# 2 một cách hiệu quả. Tôi đã mã hóa chính sách JSON thành Base64 nhưng sau đó tôi trực tiếp ký chuỗi JSON chứ không phải chuỗi Base64.

BướC# 3 có thể được viết lại thành "Đăng ký chính sách Base64 bằng Khóa truy cập bí mật của bạn bằng HMAC SHA-1".

Tôi đoán tôi sẽ bỏ qua điều này trong trường hợp bất kỳ ai khác gặp phải vấn đề tương tự.

-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

Bây giờ, quy trình này được hỗ trợ chính thức. 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", ""); 

* Cẩn thận thực hiện cửa sổ cho ví dụ này như một số vấn đề tìm thấy từ những ý kiến ​​của bưu chính, giải pháp cho vấn đề này cũng đã được cung cấp ở đó.

Kết quả có thể được xác nhận của thành viên này http://s3.amazonaws.com/doc/s3-example-code/post/post_sample.html

Tuy nhiên, một số nói điều này "org.apache.commons.codec.binary.Base64" là tốt hơn vì điều này. http://www.asgarli.net/2011/03/replacing-sunmiscbase64encoder-and.html