I'm working with Google Cloud Storage in AppEngine and I'm attempting to use a POST form to upload a file to GCS. The problem I'm having is with the steps needed to sign the policy document. I can easily fetch the client_secret, which is a String from the client_secrets.json
that the API Console gave me. however, in order to create a signature, I need to convert that string into a PrivateKey
object. Here's what my code looks like:
//create the policy document and encode it
String policyDocument = ... //omitted for brevity
String encodedPolicy = Base64.encodeString(policyDocument);
//sign using SHA256 with RSA
String secretKey = ... //I fetch this from client_secrets.json
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(secretKey); //THIS IS THE PROBLEM!
sig.update(encodedPolicy.getBytes("UTF-8"));
String signature = new String(Base64.encode(sig.sign()));
//put the values in the request attributes so we can fetch them from a JSP
req.setAttribute("policy", encodedPolicy);
req.setAttribute("signature", signature);
As noted above, my problem is in the line
sig.initSign(secretKey); //THIS IS THE PROBLEM!
secretKey
is a String. Signature.initSign()
expects a PrivateKey
, or one of its descendant objects. How do I convert the string in the client_secrets.json
into a PrivateKey (or derived) object that I can pass Signature.initSign
?
Any help would be greatly appreciated. Thanks
OK, here's where I am right now. I tried the suggestions below, and all of the documentation is urging me to use the client_secret in the client_secrets.json file downloaded from the Google API console, not the service account. And besides, I'm trying to construct an example of a user's upload, not a service account.
I found the following code on another page:
public static String signPolicyDocument(String policyDocument, String secret) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
byte[] secretBytes = secret.getBytes();
SecretKeySpec signingKey = new SecretKeySpec(secretBytes, "HmacSHA256");
mac.init(signingKey);
byte[] signedSecretBytes = mac.doFinal(policyDocument.getBytes());
return new String(Base64.encode(signedSecretBytes));
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
And it gets me all the way through the process...until I submit the resulting form. Then I get the following response:
The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.
What signing method is it looking for?