Generate Google Cloud Storage Policy Document and Signature

Go To StackoverFlow.com

1

I'm trying to upload files to Google Cloud Storage via a HTML Form via the POST method. Google states in their documentation that to assign a non-standard ACL you need both a policy and a signature field.

Reading through their descriptions on how to generate these values, it seems pretty simple. Unfortunately, after many attempts, I still cannot generate values that will pass Google's filters. I continuously get errors saying that my signature does not match the policy document.

Could someone instruct me where I'm going wrong? This is my process:

  1. Build my policy document

This is the easy part. My policy document is:

{"expiration": "2015-06-16T11:11:11Z", 
"conditions": [ 
    ["starts-with", "$key", ""], 
    {"acl": "public-read" }, 
    {"bucket": "publicjs"}, 
    {"success_action_redirect": "http://localhost/gcs.php" } 
] }
  1. I then went to this website and encoded the above value in base64. This is what I'm using as my policy document.

  2. Now for the signature. I need to encrypt my policy document using my secret key as the encryption key, so I went to this website to do the encryption. I entered my base64 encoded policy document (from step 2) into the main text area, and my interoperability "Secret" key into the key box.

  3. Hit enter, and the value next to base64 should be the signature value.

  4. Put values in form, send POST request, receive error.

Where am I going wrong?

2012-04-05 16:41
by jwegner


4

The encoding sequence should be as follows:

  • base64 encode the policy document (let's call that the encoded policy)

  • generate a SHA1 hash (for interop keys only, use SHA256 if you want to use an RSA key) of the encoded policy and base64 encode that (let's call that the signature)

  • send the encoded policy and the signature in the form post request (along with rest of the form)

Here's an idealized implementation of the sequence in Python:

  POLICY = '''{
                "expiration": "2015-06-16T11:11:11Z", 
                "conditions": [
                  ["starts-with", "$key", "test"],
                  {"acl" : "public-read"}
                ]
              }'''

  GEN_FORM = '''
    <form action="%s" method="post" enctype="multipart/form-data">
      <input type="hidden" name="acl" value="public-read">
      <input type="hidden" name="bucket" value="YOUR_BUCKET">
      <input type="hidden" name="key" value="YOUR_OBJECT_NAME">
      <input type="hidden" name="GoogleAccessId" value="YOUR_ACCESS_ID">
      <input type="hidden" name="policy" value="%s">
      <input type="hidden" name="signature" value="%s">
      <input name="file" type="file">
      <input type="submit" value="Upload">
    </form>
  '''

  encoded_policy = base64.b64encode(POLICY).strip()
  h = hmac.new(YOUR_SECRET_KEY, digestmod=sha.sha)
  h.update(encoded_policy)
  signature = base64.b64encode(h.digest())
  gen_html = GEN_FORM % (url, encoded_policy, signature)
2012-04-06 03:34
by Marc Cohen
Actually got this figured out. I was accidentally doing a SHA256 (as mentioned in Google's documentation), but a SHA1 is really what is required. Also, if I use "key" instead of "$key" I get invalid policy errors - jwegner 2012-04-06 12:03
A SHA1 hash is required when using the interoperability key but SHA256 is required when using an RSA key. I think the doc you are referring to assumes RSA but it could be more clear about this point (I've written a request to fix that). You're right about the dollar signs, they don't belong when using field names but they are needed when using conditionals, which you are using here. I've updated my code to reflect that correction, lest I mislead any visitors to this thread. Thanks Joseph - Marc Cohen 2012-04-06 15:45
@MarcCohen I'm having an impossible time trying to get the signatures to work (NOTE: I'm trying to use the interoperability keys and SHA1, just like your example). All I ever get is "SignatureDoesNotMatch". It seems that if my POLICY string has any difference in whitespace than the one Google puts together, then that will totally change the final signature, and they wont match up. How do I know that my policy string has the exact expected format of the one Google puts together before encoding/signing - Nick Franceschina 2013-12-21 01:46
HI @MarcCohen can you tell me the process to prepare signature and policy in java. Can you please elaborate what is $key and text in startswith in the policy. what is YOURSECRET_KEY in the hmac.new statement. I am looking for this for the last two days. Thanks in advanc - Sreekanth 2014-05-28 08:03
Ads