Pude cifrar y cargar con éxito un archivo de imagen usando el siguiente fragmento:
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); }); });Para recuperar el objeto descifrado, utilicé el método getsignedurl, la consola genera una URL firmada pero no descifra la imagen, por lo que muestra el siguiente error en el navegador:
¿Qué podría estar haciendo mal aquí?
Lo tengo funcionando con getObject en lugar de getSignedUrl.
Creo que hay un punto válido en no devolver datos descifrados con el método getSignedUrl. Dado que se usa getSignedUrl, la clave se pasaría en texto sin formato en la URL en lugar de en el encabezado, lo que disminuiría el uso de cifrado si la clave se puede leer en la red.
Lo siguiente funciona con un objeto descifrado en una matriz de bytes:
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')); } });Según el documento en https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property :
Nota:
No todos los parámetros de operación son compatibles cuando se usan URL prefirmadas. Ciertos parámetros, como SSECustomerKey, ACL, Expires, ContentLength o Tagging, deben proporcionarse como encabezados al enviar una solicitud. Si usa URL prefirmadas para cargar desde un navegador y necesita usar estos campos, consulte createPresignedPost().
Necesitarías un código como estos:
En back-end:
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 })En el navegador:
//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); }); } } }