Todos os produtos
Search
Central de documentação

Object Storage Service:Criptografia no lado do cliente com o OSS SDK for PHP 2.0

Última atualização: Jul 03, 2026

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.