从 s3 签名 url 以使用 SSE-C 解密上传的对象
Getting signed url from s3 to decrypt uploaded object using SSE-C
我使用以下代码段成功加密并上传了图像文件:
var ssecKey = '12345678901234567890123456789012'
var data = {
Key: 'testfolder/abc.png',
Body: buffer,
ContentEncoding: 'base64',
ContentType: 'image/png',
SSECustomerAlgorithm: 'AES256',
SSECustomerKey: ssecKey
};
s3.putObject(data, (err) => {
if (err) return console.error(err.stack)
s3.getSignedUrl('getObject', {
Key: 'testfolder/abc.png',
Expires: 160,
SSECustomerAlgorithm: 'AES256',
SSECustomerKey: ssecKey
}, (err, data) => {
if (err) return console.error(err.stack)
console.log(data);
});
});
为了取回解密后的对象,我使用了getsignedurl方法,控制台输出了一个签名的url但是没有解密图片,因此在浏览器上显示如下错误:
我这里可能做错了什么。
使用 getObject 而不是 getSignedUrl。
我认为不使用 getSignedUrl 方法返回解密数据是有道理的。由于使用 getSignedUrl,密钥将在 url 中以纯文本形式传递,而不是在 header 中传递,如果密钥可通过网络读取,这将减少加密的使用。
以下使用字节数组中解密的 object:
s3.getObject({
Key: 'testfolder/abc.png',
SSECustomerAlgorithm: 'AES256',
SSECustomerKey: ssecKey
}, function (err, data) {
if (err) {
console.error(err);
}
else {
console.log('BYTE ARRAY: ' + data.Body);
console.log('BASE64: ' + data.Body.toString('base64'));
}
});
根据 https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property 上的文档:
Note:
Not all operation parameters are supported when using pre-signed URLs.
Certain parameters, such as SSECustomerKey, ACL, Expires,
ContentLength, or Tagging must be provided as headers when sending a
request. If you are using pre-signed URLs to upload from a browser and
need to use these fields, see createPresignedPost().
您需要这样的代码:
在后端:
AWS.config.update({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION,
signatureVersion: 'v4' // NB! this seems needed to avoid some bugs
})
s3.getSignedUrl('getObject', {
Bucket: process.env.S3_BUCKET_NAME,
Key: key,
SSECustomerAlgorithm: 'AES256', // NB! this must be added
})
在浏览器中:
//encryption key can be generated in nodejs:
//var password = "some easy to remember password";
//var encryption_key = crypto.createHash('sha256').update(password, 'utf8').digest('base64');
//var encryption_key_md5 = crypto.createHash('md5').update(encryption_key, 'base64').digest('base64');
function presigned_get(url) {
console.log("presigned_get", url);
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.open("get", url);
xhr.setRequestHeader("x-amz-server-side-encryption-customer-algorithm", "AES256");
xhr.setRequestHeader("x-amz-server-side-encryption-customer-key", ENCRYPTION_KEY);
//xhr.setRequestHeader("x-amz-server-side-encryption-customer-key-MD5", ENCRYPTION_KEY_MD5);
xhr.send();
xhr.onload = function() {
if (xhr.status == 200) {
console.log(`Downloaded ${url}`);
var filename = url.substring(0, url.indexOf('?'));
filename = filename.substring(filename.lastIndexOf('/')+1);
window.saveAs(xhr.response, filename);
} else {
var reader = new FileReader();
reader.readAsText(xhr.response);
reader.addEventListener('loadend', (e) => {
console.error(`Downloading ${url} failed:`, xhr.statusText, e.srcElement.result);
});
}
}
}
我使用以下代码段成功加密并上传了图像文件:
var ssecKey = '12345678901234567890123456789012'
var data = {
Key: 'testfolder/abc.png',
Body: buffer,
ContentEncoding: 'base64',
ContentType: 'image/png',
SSECustomerAlgorithm: 'AES256',
SSECustomerKey: ssecKey
};
s3.putObject(data, (err) => {
if (err) return console.error(err.stack)
s3.getSignedUrl('getObject', {
Key: 'testfolder/abc.png',
Expires: 160,
SSECustomerAlgorithm: 'AES256',
SSECustomerKey: ssecKey
}, (err, data) => {
if (err) return console.error(err.stack)
console.log(data);
});
});
为了取回解密后的对象,我使用了getsignedurl方法,控制台输出了一个签名的url但是没有解密图片,因此在浏览器上显示如下错误:
我这里可能做错了什么。
使用 getObject 而不是 getSignedUrl。
我认为不使用 getSignedUrl 方法返回解密数据是有道理的。由于使用 getSignedUrl,密钥将在 url 中以纯文本形式传递,而不是在 header 中传递,如果密钥可通过网络读取,这将减少加密的使用。
以下使用字节数组中解密的 object:
s3.getObject({
Key: 'testfolder/abc.png',
SSECustomerAlgorithm: 'AES256',
SSECustomerKey: ssecKey
}, function (err, data) {
if (err) {
console.error(err);
}
else {
console.log('BYTE ARRAY: ' + data.Body);
console.log('BASE64: ' + data.Body.toString('base64'));
}
});
根据 https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property 上的文档:
Note:
Not all operation parameters are supported when using pre-signed URLs. Certain parameters, such as SSECustomerKey, ACL, Expires, ContentLength, or Tagging must be provided as headers when sending a request. If you are using pre-signed URLs to upload from a browser and need to use these fields, see createPresignedPost().
您需要这样的代码:
在后端:
AWS.config.update({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION,
signatureVersion: 'v4' // NB! this seems needed to avoid some bugs
})
s3.getSignedUrl('getObject', {
Bucket: process.env.S3_BUCKET_NAME,
Key: key,
SSECustomerAlgorithm: 'AES256', // NB! this must be added
})
在浏览器中:
//encryption key can be generated in nodejs:
//var password = "some easy to remember password";
//var encryption_key = crypto.createHash('sha256').update(password, 'utf8').digest('base64');
//var encryption_key_md5 = crypto.createHash('md5').update(encryption_key, 'base64').digest('base64');
function presigned_get(url) {
console.log("presigned_get", url);
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.open("get", url);
xhr.setRequestHeader("x-amz-server-side-encryption-customer-algorithm", "AES256");
xhr.setRequestHeader("x-amz-server-side-encryption-customer-key", ENCRYPTION_KEY);
//xhr.setRequestHeader("x-amz-server-side-encryption-customer-key-MD5", ENCRYPTION_KEY_MD5);
xhr.send();
xhr.onload = function() {
if (xhr.status == 200) {
console.log(`Downloaded ${url}`);
var filename = url.substring(0, url.indexOf('?'));
filename = filename.substring(filename.lastIndexOf('/')+1);
window.saveAs(xhr.response, filename);
} else {
var reader = new FileReader();
reader.readAsText(xhr.response);
reader.addEventListener('loadend', (e) => {
console.error(`Downloading ${url} failed:`, xhr.statusText, e.srcElement.result);
});
}
}
}