Question

I'm having tremendous problems trying to upload a file to the Google Cloud Storage (GCS) using a form on a webpage hosted on a Google App Engine (GAE), GWT, using POST OBJECT and a policy document and signature.

The biggest problems of all; I don't get any feedback on what is wrong.

First of all. I am able to upload a file to the GCS if I use no Policy or Signature at all, so I'm assuming the error lies in the that part. See below for code.

//Is used to get the policy as base64 and the signature (and converted to base64)
public String[] getPolicyAndSignature(String policy)
{
    try
    {
       KeyStore keystore = KeyStore.getInstance("PKCS12");
       keystore.load(new FileInputStream(new File("my_test_app/mykey.p12")), "notasecret".toCharArray());
       PrivateKey privateKey = (PrivateKey)keystore.getKey("privatekey", "notasecret".toCharArray());

       Signature signature = Signature.getInstance("SHA256withRSA");
       signature.initSign(privateKey);

       //is this wrong, should it be just: (?)
       //signature.update(policy.getBytes())
       signature.update(Base64Utils.toBase64(policy.getBytes()).getBytes());

       byte[] signatureBytes = signature.sign();
       byte[] policyBytes = policy.getBytes();

       return new String[]{Base64Utils.toBase64(policyBytes), Base64Utils.toBase64(signatureBytes)};
    }
    catch(Exception e)
    {
       System.out.println("Error: " + e.getMessage());
    }
    return null;
}

This is the code that uses that function:

public TestUploader()
{
    VerticalPanel mainPanel = new VerticalPanel();
    final FormPanel formPanel = new FormPanel();
    formPanel.setWidget(mainPanel);

    FileUpload upload = new FileUpload();
    upload.setName("file");
    formPanel.setAction("http://sgacms.storage.googleapis.com");
    formPanel.setMethod(FormPanel.METHOD_POST);
    formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
    formPanel.getElement().setAttribute("accept-charset", "UTF-8");

    String keyString = "testing";
    String bucketString = "sgacms";
    Hidden key = new Hidden("key", keyString);
    Hidden bucket = new Hidden("bucket", bucketString);
    Hidden contentType = new Hidden("Content-Type", "image/jpeg");
    Hidden GoogleAccessID = new Hidden("GoogleAccessID", "517031602192-p8kn8m33vhmhg9horbif8mansmkilqle@developer.gserviceaccount.com");
    Hidden acl = new Hidden("acl", "bucket-owner-read");
    final Hidden policy = new Hidden("policy");
    final Hidden hiddenSignature = new Hidden("signature");

    String policyString =
        "{\"expiration\":\"2016-06-16T11:11:11Z\","+
            "\"conditions\":["+
                "[\"starts-with\",\"$key\",\"\"],"+
                "{\"acl\":\"bucket-owner-read\"},"+
                "{\"bucket\":\"sgacms\"},"+
                "[\"eq\",\"$Content-Type\",\"image/jpeg\"],"+
                "[\"content-length-range\",0,1000000]"+
            "]"+
        "}";

    String[] policyAndSignature = getPolicyAndSignature(policyString);
    policy.setValue(policyAndSignature[0]);
    hiddenSignature.setValue(policyAndSignature[1]);

    Button btn = new Button("Submit");

    mainPanel.add(btn); //submit
    mainPanel.add(key); //hidden
    mainPanel.add(bucket); //hidden
    mainPanel.add(contentType); //hidden
    mainPanel.add(GoogleAccessID); //hidden
    mainPanel.add(acl); //hidden
    mainPanel.add(policy);  //hidden
    mainPanel.add(hiddenSignature); //hidden
    mainPanel.add(upload); //file

    initWidget(formPanel);

    btn.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
            formPanel.submit();
        }
    });
    formPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
        @Override
        public void onSubmitComplete(SubmitCompleteEvent event) {
            log.severe("Submit results: " + event.getResults());
        }
    });
}

The submit results simply prints: null, when I fail. And since I never succeed it never prints anything else. If I on the other hand uses no policy and no signature (in other words making an anonymous upload) the submit results will be empty and the file will be uploaded successfully.

So I can't figure out what is wrong! Any help is appreciated! Thank you!

EDIT: So now I've finally been able to get an error response which says the following: "SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method"

Était-ce utile?

La solution

Okay so I've found the answer to my problem.

I'm a bit pissed that it was such an "easy" fix. As you can see in my question I'm using Base64Utils which is part of the "com.google.gwt.user.server.Base64Utils" package. I think it's faulty somehow, either I'm using it wrongly or it uses some default character-encoding and ignores the encoding of the data that it receives, I simply don't know. I switched it out to use the Base64 from the "org.apache.commons.codec.binary.Base64" package, and it seems to work.

(It's worth mentioning that i did try to use the Base64Utils in combination with using getBytes("UTF-8") - but that didn't work either.)

So the working method looks like this:

public String[] getPolicyAndSignature(String policy)
{
    try
    {
        String encodedPolicy = new String(Base64.encodeBase64(policy.getBytes()));

        KeyStore keystore = KeyStore.getInstance("PKCS12");
        keystore.load(new FileInputStream(new File("my_test_app/mykey.p12")), "notasecret".toCharArray());
        PrivateKey privateKey = (PrivateKey)keystore.getKey("privatekey", "notasecret".toCharArray());

        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(encodedPolicy.getBytes());

        String encodedSignature = new String(Base64.encodeBase64(signature.sign(), false));

        return new String[]{encodedPolicy, encodedSignature};
    }
    catch(Exception e)
    {
        System.out.println("Error: " + e.getMessage());
    }
    return null;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top