David Harper
David Harper

Reputation: 43

Google Cloud Storage Appears to Ignore Customer Supplied Encryption Key Headers

I am working on a project that stores images in Google Cloud Storage (GCS). I'm running a NodeJS server with the code below. Files are sent to the server with a signed URL for a resumable upload in GCS. After buffing the entire file, the server directs a request to that address.

That part works. But, when I add headers to the request that specify a customer-supplied encryption key, GCS ignores them. The upload completes, returns a 200, and the default encryption key is applied.

When I tried an invalid value for x-goog-encryption-algorithm, where I should have gotten a 400, it uploaded fine.

I should be very close, but what header or configuration am I missing to be allowed to specify a customer-supplied encryption key?

var crypto = require("crypto");
var fs = require("fs");
var Request = require("request");

var hashKey = function(key) {
  var hash = crypto.createHash("sha256");
  key = new Buffer(key);
  hash.update(key);
  return hash.digest("base64");
};

var GCS = module.exports = function GCS(env) {
  // config contains the encryption key I'd like to specify.
  this.config = env.config
};

GCS.prototype.upload = function (url, buffer) {
  var self = this;
  return new Promise(function(resolve, reject) {
    var headers = { 
      "Content-Length": buffer.size,
      "x-goog-encryption-algorithm": "AES256",
      "x-goog-encryption-key": self.config.encryption.key, 
      "x-goog-encryption-key-sha256": hashKey(self.config.encryption.key)
    };

    var options = {
      url: url,
      method: "PUT",
      headers: headers
    };

    fs.createReadStream(buffer.path)
    .pipe(Request(options))
    .on("error", function(e) {
      self.logger.error("Failed to upload asset to slot.", e);
      reject(e);
    })
    .on("response", function(res){
      if (res.statusCode != 200) {
        reject(new Error("Unexpected response code" + res));
      }
      resolve(res);
     });
  });
};

Upvotes: 4

Views: 185

Answers (1)

Travis Hobrla
Travis Hobrla

Reputation: 5511

For a resumable upload, you need to send the same encryption headers with the initial POST that creates the upload URL.

Upvotes: 2

Related Questions