A criptografia no lado do cliente criptografa objetos localmente antes do upload para o Object Storage Service (OSS). Somente o detentor da chave mestra do cliente (CMK) pode descriptografar os objetos, o que aumenta a segurança dos dados durante a transmissão e o armazenamento.
Observações de uso
O código de exemplo neste tópico usa a região China (Hangzhou), cujo ID de região é
cn-hangzhou. Por padrão, o sistema usa um endpoint público. Para acessar o bucket a partir de outros serviços da Alibaba Cloud na mesma região, use um endpoint interno. Para obter mais informações sobre regiões e endpoints do OSS, consulte Regiões e endpoints.Ao usar a criptografia no lado do cliente, garanta a integridade e a validade da CMK.
Ao copiar ou migrar dados criptografados, você é responsável pela integridade e validade dos metadados do objeto.
Usar CMKs baseadas em RSA para criptografia no lado do cliente
Use RSA-based CMKs to encrypt objects in simple uploads and decrypt objects in simple downloads
O código de exemplo a seguir mostra como usar uma CMK baseada em RSA para criptografar objetos em uploads simples e descriptografar objetos em downloads simples:
<?php
// Introduce autoload files to load dependent libraries.
require_once __DIR__ . '/../vendor/autoload.php';
use AlibabaCloud\Oss\V2 as Oss;
// Specify the RSA public key for the data encryption operation.
const RSA_PUBLIC_KEY = <<<BBB
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW
6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC
5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR
1EKib1Id8hpooY5xaQIDAQAB
-----END PUBLIC KEY-----
BBB;
// Specify the RSA private key for the data decryption operation.
const RSA_PRIVATE_KEY = <<<BBB
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKiR+IBVdd/kiYXM
oPD5c79QHJbqax7ZCwiDPdnAG0w27n19HnO21LH7x8Hu9HgI3dtPO2s/0DpuOg3Q
UWeGVDe80kLkwU7U8HKsT8w13kAB9JVtr3cjqzHw1KTkzNQIDg0nMBSpg4RYa0YF
yibqQQXoyZHUQqJvUh3yGmihjnFpAgMBAAECgYA49RmCQ14QyKevDfVTdvYlLmx6
kbqgMbYIqk+7w611kxoCTMR9VMmJWgmk/Zic9mIAOEVbd7RkCdqT0E+xKzJJFpI2
ZHjrlwb21uqlcUqH1Gn+wI+jgmrafrnKih0kGucavr/GFi81rXixDrGON9KBE0FJ
cPVdc0XiQAvCBnIIAQJBANXu3htPH0VsSznfqcDE+w8zpoAJdo6S/p30tcjsDQnx
l/jYV4FXpErSrtAbmI013VYkdJcghNSLNUXppfk2e8UCQQDJt5c07BS9i2SDEXiz
byzqCfXVzkdnDj9ry9mba1dcr9B9NCslVelXDGZKvQUBqNYCVxg398aRfWlYDTjU
IoVVAkAbTyjPN6R4SkC4HJMg5oReBmvkwFCAFsemBk0GXwuzD0IlJAjXnAZ+/rIO
ItewfwXIL1Mqz53lO/gK+q6TR585AkB304KUIoWzjyF3JqLP3IQOxzns92u9EV6l
V2P+CkbMPXiZV6sls6I4XppJXX2i3bu7iidN3/dqJ9izQK94fMU9AkBZvgsIPCot
y1/POIbv9LtnviDKrmpkXgVQSU4BmTPvXwTJm8APC7P/horSh3SVf1zgmnsyjm9D
hO92gGc+4ajL
-----END PRIVATE KEY-----
BBB;
// Specify descriptions for command line parameters.
$optsdesc = [
"region" => ['help' => The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located.
"endpoint" => ['help' => The domain names that other services can use to access OSS', 'required' => False], // (Optional) Specify the endpoint that can be used by other services to access OSS.
"bucket" => ['help' => The name of the bucket, 'required' => True], // (Required) Specify the name of the bucket.
"key" => ['help' => The name of the object, 'required' => True], // (Required) Specify the name of the object.
];
// Generate a long options list to parse the command line parameters.
$longopts = \array_map(function ($key) {
return "$key:"; // Add a colon (:) to the end of each parameter to indicate that a value is required.
}, array_keys($optsdesc));
// Parse the command line parameters.
$options = getopt("", $longopts);
// Check whether the required parameters are configured.
foreach ($optsdesc as $key => $value) {
if ($value['required'] === True && empty($options[$key])) {
$help = $value['help'];
echo "Error: the following arguments are required: --$key, $help"; // Indicate that the required parameters are not configured.
exit(1);
}
}
// Obtain the values of the command line parameters.
$region = $options["region"]; // The region in which the bucket is located.
$bucket = $options["bucket"]; // The name of the bucket.
$key = $options["key"]; // The name of the object.
// Use environment variables to load the AccessKey ID and AccessKey secret.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
// Use the default configurations of the SDK.
$cfg = Oss\Config::loadDefault();
// Specify the credential provider.
$cfg->setCredentialsProvider($credentialsProvider);
// Specify the region.
$cfg->setRegion($region);
// Specify the endpoint if an endpoint is provided.
if (isset($options["endpoint"])) {
$cfg->setEndpoint($options["endpoint"]);
}
// Create an OSSClient instance.
$client = new Oss\Client($cfg);
// Create a CMK encrypter and use the RSA public key for data encryption and the RSA private key for data decryption.
$masterCipher = new Oss\Crypto\MasterRsaCipher(
publicKey: RSA_PUBLIC_KEY, // Specify the RSA public key.
privateKey: RSA_PRIVATE_KEY, // Specify the RSA private key.
matDesc: ['tag' => 'value'] // Encrypt additional tags.
);
// Create a client for client-side encryption.
$eclient = new Oss\EncryptionClient(client: $client, masterCipher: $masterCipher);
// Create a PutObjectRequest object for simple upload.
$putObjRequest = new Oss\Models\PutObjectRequest(bucket: $bucket, key: $key);
// Use the putObject method to upload the local file.
$putObjResult = $eclient->putObject(request: $putObjRequest);
// Display the returned result.
printf(
'put object status code:' . $putObjResult->statusCode . PHP_EOL . // The returned HTTP status code.
'request id:' . $putObjResult->requestId . PHP_EOL // The request ID, which is the unique identifier of the request.
);
Use RSA-based CMKs to encrypt objects in multipart upload
O código de exemplo a seguir mostra como usar uma CMK baseada em RSA para criptografar um objeto em upload multipart:
<?php
// Introduce autoload files to load dependent libraries.
require_once __DIR__ . '/../vendor/autoload.php';
use AlibabaCloud\Oss\V2 as Oss;
// Specify the RSA public key for the data encryption operation.
const RSA_PUBLIC_KEY = <<<BBB
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW
6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC
5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR
1EKib1Id8hpooY5xaQIDAQAB
-----END PUBLIC KEY-----
BBB;
// Specify the RSA private key for the data decryption operation.
const RSA_PRIVATE_KEY = <<<BBB
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKiR+IBVdd/kiYXM
oPD5c79QHJbqax7ZCwiDPdnAG0w27n19HnO21LH7x8Hu9HgI3dtPO2s/0DpuOg3Q
UWeGVDe80kLkwU7U8HKsT8w13kAB9JVtr3cjqzHw1KTkzNQIDg0nMBSpg4RYa0YF
yibqQQXoyZHUQqJvUh3yGmihjnFpAgMBAAECgYA49RmCQ14QyKevDfVTdvYlLmx6
kbqgMbYIqk+7w611kxoCTMR9VMmJWgmk/Zic9mIAOEVbd7RkCdqT0E+xKzJJFpI2
ZHjrlwb21uqlcUqH1Gn+wI+jgmrafrnKih0kGucavr/GFi81rXixDrGON9KBE0FJ
cPVdc0XiQAvCBnIIAQJBANXu3htPH0VsSznfqcDE+w8zpoAJdo6S/p30tcjsDQnx
l/jYV4FXpErSrtAbmI013VYkdJcghNSLNUXppfk2e8UCQQDJt5c07BS9i2SDEXiz
byzqCfXVzkdnDj9ry9mba1dcr9B9NCslVelXDGZKvQUBqNYCVxg398aRfWlYDTjU
IoVVAkAbTyjPN6R4SkC4HJMg5oReBmvkwFCAFsemBk0GXwuzD0IlJAjXnAZ+/rIO
ItewfwXIL1Mqz53lO/gK+q6TR585AkB304KUIoWzjyF3JqLP3IQOxzns92u9EV6l
V2P+CkbMPXiZV6sls6I4XppJXX2i3bu7iidN3/dqJ9izQK94fMU9AkBZvgsIPCot
y1/POIbv9LtnviDKrmpkXgVQSU4BmTPvXwTJm8APC7P/horSh3SVf1zgmnsyjm9D
hO92gGc+4ajL
-----END PRIVATE KEY-----
BBB;
// Specify descriptions for command line parameters.
$optsdesc = [
"region" => ['help' => The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located.
"endpoint" => ['help' => The domain names that other services can use to access OSS', 'required' => False], // (Optional) Specify the endpoint that can be used by other services to access OSS.
"bucket" => ['help' => The name of the bucket, 'required' => True], // (Required) Specify the name of the bucket.
"key" => ['help' => The name of the object, 'required' => True], // (Required) Specify the name of the object.
];
// Generate a long options list to parse the command line parameters.
$longopts = \array_map(function ($key) {
return "$key:"; // Add a colon (:) to the end of each parameter to indicate that a value is required.
}, array_keys($optsdesc));
// Parse the command line parameters.
$options = getopt("", $longopts);
// Check whether the required parameters are configured.
foreach ($optsdesc as $key => $value) {
if ($value['required'] === True && empty($options[$key])) {
$help = $value['help'];
echo "Error: the following arguments are required: --$key, $help"; // Indicate that the required parameters are not configured.
exit(1);
}
}
// Obtain the values of the command line parameters.
$region = $options["region"]; // The region in which the bucket is located.
$bucket = $options["bucket"]; // The name of the bucket.
$key = $options["key"]; // The name of the object.
// Use environment variables to load the AccessKey ID and AccessKey secret.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
// Use the default configurations of the SDK.
$cfg = Oss\Config::loadDefault();
// Specify the credential provider.
$cfg->setCredentialsProvider($credentialsProvider);
// Specify the region.
$cfg->setRegion($region);
// Specify the endpoint if an endpoint is provided.
if (isset($options["endpoint"])) {
$cfg->setEndpoint($options["endpoint"]);
}
// Create an OSSClient instance.
$client = new Oss\Client($cfg);
// Create a CMK encrypter and use the RSA public key for data encryption and the RSA private key for data decryption.
$masterCipher = new Oss\Crypto\MasterRsaCipher(
RSA_PUBLIC_KEY, // Specify the RSA public key.
RSA_PRIVATE_KEY, // Specify the RSA private key.
['tag' => 'value'] // Encrypt additional tags.
);
// Create a client for client-side encryption.
$eclient = new Oss\EncryptionClient($client, $masterCipher);
// Initiate a multipart upload request and specify the part size and the total object size.
$initRequest = new Oss\Models\InitiateMultipartUploadRequest(bucket: $bucket, key: $key);
$initRequest-> cseDataSize=500 * 1024; // Set the total size of the object to 500 KB.
$initRequest-> csePartSize=200 * 1024; // Set the size of each part to 200 KB.
// Use the initiateMultipartUpload method to initiate a multipart upload request.
$initResult = $eclient->initiateMultipartUpload(request: $initRequest);
// Create an UploadPartRequest object for the multipart upload task.
$uploadPartRequest = new Oss\Models\UploadPartRequest(bucket: $bucket, key: $key);
// Specify the name and part size of the temporary local file.
$bigFileName = "upload.tmp"; // Specify the name of the temporary local file.
$partSize=200 * 1024; // Set the size of each part to 200 KB.
// Generate a temporary local file whose size is 500 KB for testing.
generateFile($bigFileName, 500 * 1024);
// Open the temporary local file and read the content.
$file = fopen(filename: $bigFileName, mode: 'r');
// Specify the array used to store the part information.
$parts = array();
// If the temporary local file is successfully opened, read and upload the parts.
if ($file) {
$i = 1; // Specify the part number starting from 1.
while (!feof(stream: $file)) {
// Read the data of a part.
$chunk = fread(stream: $file, length: $partSize);
// Create an UploadPartRequest object for the multipart upload task and specify the part number and upload ID.
$uploadPartRequest = new Oss\Models\UploadPartRequest(
bucket: $bucket,
key: $key,
partNumber: $i,
uploadId: $initResult->uploadId,
contentLength: null,
contentMd5: null,
trafficLimit: null,
requestPayer: null,
body: Oss\Utils::streamFor(resource: $chunk) // Convert the part data to a stream.
);
// Encrypt the context.
$uploadPartRequest->encryptionMultipartContext = $initResult->encryptionMultipartContext;
// Use the uploadPart method to upload a part.
$partResult = $eclient->uploadPart($uploadPartRequest);
// Create an UploadPart object and add it to the part array.
$part = new Oss\Models\UploadPart(
partNumber: $i,
etag: $partResult->etag, // Obtain the ETag of the part.
);
array_push(array: $parts, values: $part);
$i++; // Specify the part number. The part number sequentially increases.
}
fclose(stream: $file); // Close the file.
}
// Use the completeMultipartUpload method to combine the parts into a complete object.
$comResult = $eclient->completeMultipartUpload(
request: new Oss\Models\CompleteMultipartUploadRequest(
bucket: $bucket,
key: $key,
uploadId: $initResult->uploadId,
acl: null,
completeMultipartUpload: new Oss\Models\CompleteMultipartUpload(
parts: $parts
),
)
);
// Delete the temporary local file.
unlink($bigFileName);
// Display the returned result.
printf(
'complete multipart upload status code:' . $comResult->statusCode . PHP_EOL . // The returned HTTP status code.
'complete multipart upload request id:' . $comResult->requestId . PHP_EOL . // The request ID, which is the unique identifier of the request.
complete multipart upload result:' . var_export($comResult, true) // The result of the multipart upload task.
);
// Create a local file of a specific size to test multipart upload.
function generateFile($filename, $size)
{
// If the file already exists and the size of the file meets the requirements, it is returned directly.
if (
file_exists($filename) &&
$size == sprintf('%u', filesize($filename))
) {
return;
}
$part_size=32; // Set the size of each data block that the client can write to OSS at a time to 32 bytes.
$fp = fopen($filename, "w"); // Open the file in write mode.
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; // Specify the character set.
$charactersLength = strlen($characters); // Specify the length of the character set.
// If the file is successfully opened, data is written in a loop until the specified size of data is uploaded.
if ($fp) {
while ($size > 0) {
// Calculate the size of data for the current write operation.
if ($size < $part_size) {
$write_size = $size;
} else {
$write_size = $part_size;
}
$size -= $write_size; // Update the remaining size to be written.
// Randomly select a character and repeatedly generate content.
$a = $characters[rand(0, $charactersLength - 1)];
$content = str_repeat($a, $write_size);
// Write the content to the local file.
$flag = fwrite($fp, $content);
if (!$flag) {
break; // Exit the loop if the write operation fails.
}
}
}
fclose($fp); // Close the local file.
}
Usar CMKs personalizadas
Use custom CMKs to encrypt objects in simple uploads and decrypt objects in simple downloads
O SDK fornece uma implementação RSA padrão. Se ela não atender às suas necessidades, implemente a criptografia e a descriptografia com base em CMKs personalizadas. O código de exemplo a seguir usa uma CMK personalizada no KMS 3.0 para criptografar um objeto em uploads simples e descriptografar o objeto em downloads simples:
<?php
// Introduce autoload files to load dependent libraries.
require_once 'vendor/autoload.php';
use AlibabaCloud\Dkms\Gcs\Sdk\Client as KmsClient;
use AlibabaCloud\Oss\V2 as Oss;
// Specify descriptions for command line parameters.
$optsdesc = [
"region" => ['help' => The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located.
"endpoint" => ['help' => The domain names that other services can use to access OSS.', 'required' => False], // (Optional) Specify the endpoint that can be used by other services to access OSS.
"bucket" => ['help' => The name of the bucket, 'required' => True], // (Required) Specify the name of the bucket.
"key" => ['help' => The name of the object, 'required' => True], // (Required) Specify the name of the object.
];
// Generate a long options list to parse the command line parameters.
$longopts = \array_map(function ($key) {
return "$key:"; // Add a colon (:) to the end of each parameter to indicate that a value is required.
}, array_keys($optsdesc));
// Parse the command line parameters.
$options = getopt("", $longopts);
// Check whether the required parameters are configured.
foreach ($optsdesc as $key => $value) {
if ($value['required'] === True && empty($options[$key])) {
$help = $value['help'];
echo "Error: the following arguments are required: --$key, $help"; // Indicate that the required parameters are not configured.
exit(1);
}
}
// Obtain the values of the command line parameters.
$region = $options["region"]; // The region in which the bucket is located.
$bucket = $options["bucket"]; // The name of the bucket.
$key = $options["key"]; // The name of the object.
// Use environment variables to load the AccessKey ID and AccessKey secret.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
// Specify the KMS encryption and decryption class to call the MasterCipherInterface operation.
class KmsCipher implements Oss\Crypto\MasterCipherInterface
{
private $matDesc;
private ?KmsClient $kmsClient;
private ?string $keyId;
private ?string $algorithm;
public function __construct(
$matDesc = null,
?string $keyId = null,
?KmsClient $kmsClient = null,
?string $algorithm = null
)
{
$this->keyId = $keyId;
$this->matDesc = null;
if (\is_array($matDesc)) {
$val = json_encode($matDesc);
if ($val !== false) {
$this->matDesc = $val;
}
} else if (is_string($matDesc)) {
$this->matDesc = $matDesc;
}
$this->kmsClient = $kmsClient;
$this->algorithm = $algorithm;
}
// Specify the encryption method.
public function encrypt(string $data): string
{
$encryptRequest = new \AlibabaCloud\Dkms\Gcs\Sdk\Models\AdvanceEncryptRequest();
$encryptRequest->algorithm = $this->algorithm;
$encryptRequest->keyId = $this->keyId;
$encryptRequest->plaintext = \AlibabaCloud\Tea\Utils\Utils::toBytes($data);
$runtimeOptions = new \AlibabaCloud\Dkms\Gcs\OpenApi\Util\Models\RuntimeOptions();
$encryptResponse = $this->kmsClient->advanceEncryptWithOptions($encryptRequest, $runtimeOptions);
return base64_decode((string)$encryptResponse->ciphertextBlob);
}
// Specify the decryption method.
public function decrypt(string $data): string
{
$decryptRequest = new \AlibabaCloud\Dkms\Gcs\Sdk\Models\AdvanceDecryptRequest();
$decryptRequest->keyId = $this->keyId;
$decryptRequest->ciphertextBlob = $data;
$decryptRequest->algorithm = $this->algorithm;
$runtimeOptions = new \AlibabaCloud\Dkms\Gcs\OpenApi\Util\Models\RuntimeOptions();
$decryptResponse = $this->kmsClient->advanceDecryptWithOptions($decryptRequest, $runtimeOptions);
return base64_decode((string)$decryptResponse->plaintext);
}
// Obtain the wrapping algorithm.
public function getWrapAlgorithm(): string
{
return "KMS/ALICLOUD";
}
public function getMatDesc(): string
{
return $this->matDesc;
}
}
/**
* Create a dedicated KMS SDK client.
* @return KmsClient
*/
function getDkmsGcsSdkClient()
{
global $clientKeyFile, $password, $endpoint;
// Create configurations for the dedicated KMS SDK client.
$config = new \AlibabaCloud\Dkms\Gcs\OpenApi\Models\Config();
$config->protocol = 'https';
$config->clientKeyFile = $clientKeyFile;
$config->password = $password;
$config->endpoint = $endpoint;
// Verify the certificate.
$config->caFilePath = 'path/to/caCert.pem';
// Create a KMS SDK client.
return new \AlibabaCloud\Dkms\Gcs\Sdk\Client($config);
}
// Specify the path of the file that stores the client key of the KMS instance.
$clientKeyFile = '<your client key file path>';
// Specify the password when you create the client key file.
$password = '<your dkms client passowrd>';
// Specify the endpoint of the KMS instance.
$endpoint = '<your dkms instance service address>';
// Specify the ID of the key that you created in KMS.
$kmsKeyId = '<your cmk id>';
// Specify the encryption and decryption algorithms.
$algorithm = '<your encrypt algorithm>';
// Specify the dedicated KMS SDK client.
$kmsClient = getDkmsGcsSdkClient();
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider);
$cfg->setRegion($region);
if (isset($options["endpoint"])) {
$cfg->setEndpoint($options["endpoint"]);
}
$client = new Oss\Client($cfg);
$materialDesc = ['desc' => 'your kms encrypt key material describe information'];
$masterKmsCipher = new KmsCipher($materialDesc, $kmsKeyId, $kmsClient, $algorithm);
$eClient = new \AlibabaCloud\Oss\V2\EncryptionClient($client, $masterKmsCipher);
$eClient->putObject(new Oss\Models\PutObjectRequest(
bucket: $bucket,
key: $key,
body: Oss\Utils::streamFor('hi kms')
));
$result = $eClient->getObject(new Oss\Models\GetObjectRequest(
bucket: $bucket,
key: $key,
));
$data = $result->body->getContents();
echo "get object data: " . $data;
Referências
Para obter mais informações sobre criptografia no lado do cliente, consulte Criptografia no lado do cliente.
Para obter o código de exemplo completo para uploads e downloads simples baseados em CMKs RSA, acesse o GitHub.