He estado usando AWS SDK V3 para PHP para colocar objetos en S3 con cifrado del lado del servidor utilizando la clave proporcionada por el cliente. La documentación es bastante incompleta (o al menos no la he encontrado).
Para cargar el objeto usando S3client, uso putobject con
$params['SSECustomerAlgorithm'] = 'AES256'; $params['SSECustomerKey'] = $this->encryptioncustkey; $params['SSECustomerKeyMD5'] = $this->encryptioncustkeymd5;
$this->encryptioncustkey es una clave de cliente simple (no codificada en base64 porque el SDK parece estar haciendo eso) y this->encryptioncustkeymd5 = md5($this->encryptioncustkey,true);
El objeto puesto funciona bien. Sin embargo, el problema está en generar un createSignedURL.
$cmd = $client->getCommand('GetObject', array( 'Bucket' => $bucket, 'Key' => $storedPath, 'ResponseContentDisposition' => 'attachment;charset=utf-8;filename="'.utf8_encode($fileName).'"', 'ResponseContentType' => $ctype, 'SSECustomerAlgorithm' => 'AES256', 'SSECustomerKey' => $this->encryptioncustkey, 'SSECustomerKeyMD5' => $this->encryptioncustkey64md5 ));
pero recibo una respuesta extraña que indica que falta "x-amz-server-side-encryption" (ServerSideEncryption) que, según la documentación, no es necesario para SSE-C. Incluso si lo configuro en ServerSideEncryption='AES256', no tiene ningún efecto.
<Error> <Code>InvalidArgument</Code> <Message> Requests specifying Server Side Encryption with Customer provided keys must provide an appropriate secret key. </Message> <ArgumentName>x-amz-server-side-encryption</ArgumentName> <ArgumentValue>null</ArgumentValue> <RequestId>A3368F6CE5DD310D</RequestId> <HostId> nHavXXz/gFOoJT0tnh+wgFTbTgGdpggRkyb0sDh07H7SomcX7HrcKU1dDzgZimrQwyaVQEqAjdk= </HostId> </Error>
Me encontré con el mismo problema e intenté todas las permutaciones posibles para intentar que funcionara. Finalmente llegué a la conclusión de que este caso de uso no es compatible . Al leer la documentación dispersa y arcana sobre el tema, parece que la única forma de acceder al contenido de SSE-C en S3 es especificando el x-amz-server-side-encryption-customer-algorithm
/ x-amz-server-side-encryption-customer-key
/ x-amz-server-side-encryption-customer-key-MD5
en el encabezado de la solicitud HTTP , no en la URL.
Lo que terminé haciendo es almacenar el contenido en cuestión en S3 sin cifrar y con la ACL configurada como private
(puede cargarlo como tal desde el principio o usar copyObject()
para hacer una copia con esa configuración). Luego, cuando quería obtener la URL prefirmada ["time-bombed"] para la solicitud GET, simplemente usé un comando similar al de su pregunta, pero omití los parámetros SSE. Eso funcionó para mí.