全部产品
Search
文档中心

Object Storage Service:Enkripsi Sisi Klien (Python SDK V2)

更新时间:Nov 09, 2025

Dengan enkripsi sisi klien, Anda dapat mengenkripsi data secara lokal sebelum mengunggahnya ke Object Storage Service (OSS). Hal ini memastikan bahwa hanya pemegang kunci yang berwenang yang dapat mendekripsi data, meningkatkan keamanan selama transmisi dan penyimpanan.

Peringatan

  • Contoh kode dalam topik ini menggunakan ID Wilayah China (Hangzhou) cn-hangzhou dan titik akhir publiknya sebagai referensi. Jika Anda ingin mengakses OSS dari produk Alibaba Cloud lain di wilayah yang sama, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang Wilayah dan titik akhir yang didukung oleh OSS, lihat Wilayah dan Titik Akhir.

  • Saat menggunakan fitur enkripsi sisi klien, Anda bertanggung jawab atas keamanan dan integritas kunci master.

  • Saat menyalin atau memigrasikan data terenkripsi, Anda bertanggung jawab atas integritas metadata enkripsi.

Definisi metode

Python SDK V2 mendukung dua jenis kunci master berikut:

  • Kunci Master RSA yang Dikelola Pengguna

    SDK menyediakan implementasi default Rivest-Shamir-Adleman (RSA). Untuk menggunakan metode ini, Anda harus memberikan kunci publik dan kunci privat dari kunci master sebagai parameter ke SDK.

  • Kunci Master Kustom

    Jika metode kunci master RSA tidak memenuhi kebutuhan Anda, Anda dapat mengimplementasikan perilaku enkripsi dan dekripsi sendiri untuk kunci master.

Kedua metode enkripsi ini secara efektif mencegah kebocoran data dan melindungi keamanan data sisi klien Anda. Bahkan jika data terenkripsi bocor, pihak yang tidak berwenang tidak akan dapat mendekripsi data mentah.

Penting

Untuk informasi lebih lanjut tentang prinsip enkripsi sisi klien di OSS, lihat Enkripsi Sisi Klien.

Untuk menggunakan enkripsi sisi klien, Anda harus terlebih dahulu membuat instance klien enkripsi dan kemudian memanggil antarmuka yang disediakannya. Objek Anda akan secara otomatis dienkripsi dan didekripsi selama operasi yang sesuai.

class EncryptionClient:
  ...

def __init__(self,client: Client, master_cipher: MasterCipher, decrypt_master_ciphers: Optional[List[MasterCipher]] = None)

Parameter permintaan

Parameter

Tipe

Deskripsi

client

*Client

Sebuah instance klien non-enkripsi.

master_cipher

MasterCipher

Instance kunci master yang digunakan untuk mengenkripsi dan mendekripsi kunci data.

decrypt_master_ciphers

List[MasterCipher]

Instance kunci master yang digunakan untuk mendekripsi kunci data.

Tabel berikut mencantumkan antarmuka yang disediakan oleh EncryptionClient.

Antarmuka

Deskripsi

get_object_meta

Mendapatkan metadata parsial dari sebuah objek.

head_object

Mendapatkan semua metadata dari sebuah objek.

get_object

Mengunduh dan secara otomatis mendekripsi sebuah objek.

put_object

Mengunggah dan secara otomatis mengenkripsi sebuah objek.

initiate_multipart_upload

Menginisialisasi peristiwa unggah multipart dan konteks enkripsi multipart (EncryptionMultiPartContext).

upload_part

Menginisialisasi peristiwa unggah multipart. Panggil antarmuka ini untuk mengunggah bagian data dan secara otomatis mengenkripsinya. Saat Anda memanggil antarmuka ini, Anda harus menetapkan konteks enkripsi multipart.

complete_multipart_upload

Setelah semua bagian diunggah, panggil antarmuka ini untuk menggabungkannya menjadi satu file.

abort_multipart_upload

Membatalkan peristiwa unggah multipart dan menghapus data bagian yang sesuai.

list_parts

Mendaftar semua bagian yang berhasil diunggah untuk peristiwa unggah tertentu.

Menggunakan kunci master RSA

Menggunakan kunci master RSA untuk unggah dan unduh objek sederhana

Contoh kode berikut menunjukkan cara menggunakan kunci master RSA untuk mengunggah dan mengunduh objek sederhana:

import argparse
import alibabacloud_oss_v2 as oss
import alibabacloud_oss_v2.crypto
from alibabacloud_oss_v2.encryption_client import EncryptionClient, EncryptionMultiPartContext

# Buat parser argumen baris perintah untuk menerima input pengguna.
parser = argparse.ArgumentParser(description="contoh enkripsi put object")

# Tambahkan argumen baris perintah --region, yang menentukan wilayah tempat bucket berada. Argumen ini wajib.
parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True)

# Tambahkan argumen baris perintah --bucket, yang menentukan nama bucket. Argumen ini wajib.
parser.add_argument('--bucket', help='Nama bucket.', required=True)

# Tambahkan argumen baris perintah --endpoint, yang menentukan nama domain yang layanan lain gunakan untuk mengakses OSS. Argumen ini opsional.
parser.add_argument('--endpoint', help='Nama domain yang layanan lain bisa gunakan untuk mengakses OSS')

# Tambahkan argumen baris perintah --key, yang menentukan nama objek. Argumen ini wajib.
parser.add_argument('--key', help='Nama objek.', required=True)

# Tentukan kunci publik dan privat RSA untuk enkripsi dan dekripsi.
RSA_PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
MIGfMA0G6mse2QsIgz3******GBcom6kEF6MmR1EKixaQIDAQAB
-----END PUBLIC KEY-----"""

RSA_PRIVATE_KEY = """-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgk******ItewfwXIL1Mqz53lO/gK+q6TR92gGc+4ajL
-----END PRIVATE KEY-----"""

def main():
    # Parsing argumen baris perintah.
    args = parser.parse_args()

    # Muat kredensial (AccessKey ID dan AccessKey secret) dari variabel lingkungan.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Muat konfigurasi default dari SDK.
    cfg = oss.config.load_default()

    # Tetapkan penyedia kredensial.
    cfg.credentials_provider = credentials_provider

    # Tetapkan wilayah tempat bucket berada.
    cfg.region = args.region

    # Jika titik akhir kustom disediakan, tetapkan dalam konfigurasi.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Inisialisasi klien OSS dengan objek konfigurasi.
    client = oss.Client(cfg)

    # Inisialisasi objek MasterRsaCipher untuk enkripsi dan dekripsi.
    mc = oss.crypto.MasterRsaCipher(
        mat_desc={"tag": "value"},
        public_key=RSA_PUBLIC_KEY,  # Kunci publik RSA untuk enkripsi.
        private_key=RSA_PRIVATE_KEY  # Kunci privat RSA untuk dekripsi.
    )

    # Inisialisasi klien enkripsi.
    encryption_client = oss.EncryptionClient(client, mc)

    # Tentukan data untuk diunggah.
    data = b'hello world'

    # Panggil metode put_object dari klien enkripsi untuk mengunggah objek terenkripsi.
    result = encryption_client.put_object(
        oss.PutObjectRequest(
            bucket=args.bucket,  # Nama bucket tujuan.
            key=args.key,        # Nama objek.
            body=data,           # Data untuk diunggah.
        )
    )

    # Cetak kode status dan informasi lainnya tentang operasi.
    print(f'kode status: {result.status_code}, '  # Kode status HTTP, yang menunjukkan apakah permintaan berhasil.
          f'id permintaan: {result.request_id}, '    # ID permintaan, digunakan untuk melacak log dan debugging.
          f'md5 konten: {result.content_md5}, '  # Checksum MD5 dari konten objek yang dikembalikan.
          f'etag: {result.etag}, '               # ETag dari objek yang dikembalikan.
          f'hash crc64: {result.hash_crc64}, '   # Checksum CRC-64 dari objek yang dikembalikan.
          f'id versi: {result.version_id}')    # ID versi objek jika pengendalian versi diaktifkan.


    # Panggil metode get_object dari klien enkripsi untuk mendapatkan konten objek terenkripsi.
    result = encryption_client.get_object(
        oss.GetObjectRequest(
            bucket=args.bucket,  # Nama bucket tujuan.
            key=args.key,        # Nama objek tujuan (jalur file).
        )
    )

    # Cetak informasi tentang operasi.
    print(f'kode status: {result.status_code}, '  # Kode status HTTP, yang menunjukkan apakah permintaan berhasil.
          f'id permintaan: {result.request_id}, '   # ID permintaan, digunakan untuk melacak log dan debugging.
          f'md5 konten: {result.content_md5}, '  # Checksum MD5 dari konten objek.
          f'etag: {result.etag}, '               # ETag dari objek.
          f'hash crc64: {result.hash_crc64}, '   # Checksum CRC-64 dari objek.
          f'id versi: {result.version_id}')    # ID versi objek jika pengendalian versi diaktifkan.


if __name__ == "__main__":
    # Titik masuk program. Panggil fungsi utama untuk menjalankan logika.
    main()

Menggunakan kunci master RSA untuk unggah objek multipart

Contoh kode berikut menunjukkan cara menggunakan kunci master RSA untuk mengunggah objek multipart:

import argparse
import alibabacloud_oss_v2 as oss
import os
import alibabacloud_oss_v2.crypto
from alibabacloud_oss_v2.encryption_client import EncryptionClient, EncryptionMultiPartContext

# Buat parser argumen baris perintah untuk menerima input pengguna.
parser = argparse.ArgumentParser(description="contoh enkripsi put object")

# Tambahkan argumen baris perintah --region, yang menentukan wilayah tempat bucket berada. Argumen ini wajib.
parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True)

# Tambahkan argumen baris perintah --bucket, yang menentukan nama bucket. Argumen ini wajib.
parser.add_argument('--bucket', help='Nama bucket.', required=True)

# Tambahkan argumen baris perintah --endpoint, yang menentukan nama domain yang layanan lain gunakan untuk mengakses OSS. Argumen ini opsional.
parser.add_argument('--endpoint', help='Nama domain yang layanan lain bisa gunakan untuk mengakses OSS')

# Tambahkan argumen baris perintah --key, yang menentukan nama objek (jalur file). Argumen ini wajib.
parser.add_argument('--key', help='Nama objek.', required=True)

# Tentukan kunci publik dan privat RSA untuk enkripsi dan dekripsi.
RSA_PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
MIGfMA0G6mse2QsIgz3******GBcom6kEF6MmR1EKixaQIDAQAB
-----END PUBLIC KEY-----"""

RSA_PRIVATE_KEY = """-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgk******ItewfwXIL1Mqz53lO/gK+q6TR92gGc+4ajL
-----END PRIVATE KEY-----"""

def main():
    # Parsing argumen baris perintah.
    args = parser.parse_args()

    # Muat kredensial (AccessKey ID dan AccessKey secret) dari variabel lingkungan.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Muat konfigurasi default dari SDK.
    cfg = oss.config.load_default()

    # Tetapkan penyedia kredensial.
    cfg.credentials_provider = credentials_provider

    # Tetapkan wilayah tempat bucket berada.
    cfg.region = args.region

    # Jika titik akhir kustom disediakan, tetapkan dalam konfigurasi.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Inisialisasi klien OSS dengan objek konfigurasi.
    client = oss.Client(cfg)

    # Inisialisasi cipher kunci master (MasterRsaCipher) untuk enkripsi dan dekripsi.
    mc = oss.crypto.MasterRsaCipher(
        mat_desc={"tag": "value"},# Buat deskripsi untuk kunci master. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master berkorespondensi satu-satu dengan kunci master.
        public_key=RSA_PUBLIC_KEY,  # Kunci publik RSA untuk enkripsi.
        private_key=RSA_PRIVATE_KEY  # Kunci privat RSA untuk dekripsi.
    )

    # Buat klien enkripsi.
    encryption_client = oss.EncryptionClient(client, mc)

    # Tentukan ukuran setiap bagian untuk unggah multipart dalam byte. Di sini, diatur ke 100 KB.
    part_size = 100 * 1024

    # Dapatkan ukuran file lokal dalam byte.
    data_size = os.path.getsize("/local/dir/example")  # Ganti dengan jalur aktual file lokal.

    # Inisialisasi tugas unggah multipart dan kembalikan informasi awal tugas unggah.
    result = encryption_client.initiate_multipart_upload(
        oss.InitiateMultipartUploadRequest(
            bucket="example_bucket",  # Nama bucket tujuan.
            key="example_key",        # Nama objek tujuan (jalur file).
            cse_part_size=part_size,  # Ukuran setiap bagian.
            cse_data_size=data_size   # Ukuran total file.
        )
    )

    # Cetak hasil inisialisasi tugas unggah multipart.
    print(vars(result))

    # Inisialisasi nomor bagian dan daftar bagian.
    part_number = 1
    upload_parts = []

    # Buka file lokal dan baca isinya bagian demi bagian berdasarkan ukuran bagian.
    with open("/local/dir/example", 'rb') as f:  # Ganti dengan jalur aktual file lokal.
        for start in range(0, data_size, part_size):  # Iterasi melalui isi file berdasarkan ukuran bagian.
            n = part_size  # Ukuran bagian saat ini.
            if start + n > data_size:  # Jika bagian terakhir lebih kecil dari ukuran bagian, sesuaikan ukurannya.
                n = data_size - start

            # Gunakan SectionReader untuk membaca isi bagian saat ini dari file.
            reader = oss.io_utils.SectionReader(
                oss.io_utils.ReadAtReader(f),  # Bungkus file sebagai objek yang mendukung pembacaan acak.
                start,  # Posisi awal bagian saat ini.
                n       # Ukuran bagian saat ini.
            )

            # Unggah bagian saat ini.
            up_result = encryption_client.upload_part(
                oss.UploadPartRequest(
                    bucket="example_bucket",  # Nama bucket tujuan.
                    key="example_key",        # Nama objek tujuan (jalur file).
                    upload_id=result.upload_id,  # Pengenal unik tugas unggah multipart.
                    part_number=part_number,  # Nomor bagian saat ini.
                    cse_multipart_context=result.cse_multipart_context,  # Informasi konteks enkripsi.
                    body=reader  # Isi data bagian saat ini.
                )
            )

            # Cetak hasil unggah bagian.
            print(vars(result))

            # Tambahkan nomor dan ETag bagian saat ini ke daftar bagian.
            upload_parts.append(
                oss.UploadPart(
                    part_number=part_number,  # Nomor bagian saat ini.
                    etag=up_result.etag       # Nilai ETag setelah bagian saat ini diunggah.
                )
            )

            # Perbarui nomor bagian.
            part_number += 1

    # Urutkan daftar bagian berdasarkan nomor bagian.
    parts = sorted(upload_parts, key=lambda p: p.part_number)

    # Selesaikan tugas unggah multipart, yang menggabungkan semua bagian untuk menghasilkan objek akhir.
    result = encryption_client.complete_multipart_upload(
        oss.CompleteMultipartUploadRequest(
            bucket="example_bucket",  # Nama bucket tujuan.
            key="example_key",        # Nama objek tujuan (jalur file).
            upload_id=result.upload_id,  # Pengenal unik tugas unggah multipart.
            complete_multipart_upload=oss.CompleteMultipartUpload(
                parts=parts  # Daftar bagian yang diurutkan.
            )
        )
    )

    # Cetak hasil penyelesaian tugas unggah multipart.
    print(vars(result))


if __name__ == "__main__":
    # Titik masuk program. Panggil fungsi utama untuk menjalankan logika.
    main()

Menggunakan kunci master kustom

Menggunakan kunci master kustom untuk unggah dan unduh objek sederhana

Jika implementasi RSA default yang disediakan oleh SDK tidak memenuhi kebutuhan Anda, Anda dapat mengimplementasikan perilaku enkripsi dan dekripsi sendiri untuk kunci master. Contoh kode berikut menggunakan Alibaba Cloud KMS sebagai contoh untuk menunjukkan cara menggunakan kunci master kustom untuk mengunggah dan mengunduh objek sederhana.

import argparse
import base64
import json
from aliyunsdkkms.request.v20160120.DecryptRequest import DecryptRequest
from aliyunsdkkms.request.v20160120.EncryptRequest import EncryptRequest
from aliyunsdkcore.client import AcsClient
from typing import Optional, Dict
import alibabacloud_oss_v2 as oss

# Buat parser argumen baris perintah untuk menerima input pengguna.
parser = argparse.ArgumentParser(description="contoh enkripsi kms")

# Tambahkan argumen baris perintah --region, yang menentukan wilayah tempat bucket berada. Argumen ini wajib.
parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True)

# Tambahkan argumen baris perintah --bucket, yang menentukan nama bucket. Argumen ini wajib.
parser.add_argument('--bucket', help='Nama bucket.', required=True)

# Tambahkan argumen baris perintah --endpoint, yang menentukan nama domain yang layanan lain gunakan untuk mengakses OSS. Argumen ini opsional.
parser.add_argument('--endpoint', help='Nama domain yang layanan lain bisa gunakan untuk mengakses OSS')

# Tambahkan argumen baris perintah --key, yang menentukan nama objek (jalur file). Argumen ini wajib.
parser.add_argument('--key', help='Nama objek.', required=True)

# Tambahkan argumen baris perintah --kms_id, yang menentukan ID kunci master pelanggan (CMK) pengguna. Argumen ini wajib.
parser.add_argument('--kms_id', help='ID CMK Anda.', required=True)


# Kelas cipher kunci master kustom yang mewarisi dari oss.crypto.MasterCipher.
class MasterKmsCipher(oss.crypto.MasterCipher):

    def __init__(
        self,
        mat_desc: Optional[Dict] = None,
        kms_client: Optional[AcsClient] = None,
        kms_id: Optional[str] = None,
    ):
        self.kms_client = kms_client
        self.kms_id = kms_id
        self._mat_desc = None

        # Jika deskripsi untuk kunci master disediakan, serialisasikan ke dalam string JSON.
        if mat_desc is not None and len(mat_desc.items()) > 0:
            self._mat_desc = json.dumps(mat_desc)

    def get_wrap_algorithm(self) -> str:
        # Mengembalikan nama algoritma wrap, yang tetap sebagai 'KMS/ALICLOUD'.
        return 'KMS/ALICLOUD'

    def get_mat_desc(self) -> str:
        return self._mat_desc or ''

    def encrypt(self, data: bytes) -> bytes:
        """
        Mengenkripsi data menggunakan layanan KMS.
        :param data: Data mentah yang akan dienkripsi, dalam byte.
        :return: Data terenkripsi, dalam byte.
        """
        # Enkode data mentah dalam format Base64.
        base64_crypto = base64.b64encode(data)

        # Membuat objek permintaan enkripsi.
        request = EncryptRequest()
        request.set_KeyId(self.kms_id)  # Menetapkan ID CMK.
        request.set_Plaintext(base64_crypto)  # Menetapkan data yang dienkripsi dalam format Base64.

        # Memanggil klien KMS untuk melakukan operasi enkripsi dan mendapatkan respons.
        response = self.kms_client.do_action_with_exception(request)

        # Mengurai bidang data terenkripsi dari respons dan mendekode menjadi byte.
        return base64.b64decode(json.loads(response).get('CiphertextBlob'))

    def decrypt(self, data: bytes) -> bytes:
        """
        Mendekripsi data menggunakan layanan KMS.
        :param data: Data terenkripsi, dalam byte.
        :return: Data mentah yang didekripsi, dalam byte.
        """
        # Enkode data terenkripsi dalam format Base64.
        base64_crypto = base64.b64encode(data)

        # Membuat objek permintaan dekripsi.
        request = DecryptRequest()
        request.set_CiphertextBlob(base64_crypto)  # Menetapkan data terenkripsi.

        # Memanggil klien KMS untuk melakukan operasi dekripsi dan mendapatkan respons.
        response = self.kms_client.do_action_with_exception(request)

        # Mengurai bidang teks biasa dari respons dan mendekode menjadi byte.
        return base64.b64decode(json.loads(response).get('Plaintext'))


def main():
    # Parsing argumen baris perintah.
    args = parser.parse_args()

    # Muat kredensial (AccessKey ID dan AccessKey secret) dari variabel lingkungan.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Muat konfigurasi default dari SDK.
    cfg = oss.config.load_default()

    # Tetapkan penyedia kredensial.
    cfg.credentials_provider = credentials_provider

    # Tetapkan wilayah tempat bucket berada.
    cfg.region = args.region

    # Jika titik akhir kustom disediakan, tetapkan dalam konfigurasi.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Inisialisasi klien OSS dengan objek konfigurasi.
    client = oss.Client(cfg)

    # Menginisialisasi klien KMS untuk berinteraksi dengan layanan KMS.
    kms_client = AcsClient(
        ak=credentials_provider._credentials.access_key_id,  # Memperoleh AccessKey ID dari penyedia kredensial.
        secret=credentials_provider._credentials.access_key_secret,  # Memperoleh AccessKey secret dari penyedia kredensial.
        region_id=args.region  # Menentukan wilayah.
    )

    # Menginisialisasi cipher kunci master (MasterKmsCipher) untuk operasi enkripsi dan dekripsi.
    mc = MasterKmsCipher(
        mat_desc={"desc": "informasi deskripsi materi kunci enkripsi master Anda"},  # Deskripsi kunci master.
        kms_client=kms_client,  # Instance klien KMS.
        kms_id=args.kms_id  # ID CMK pengguna.
    )

    # Buat klien enkripsi.
    encryption_client = oss.EncryptionClient(client, mc)

    # Tentukan data untuk diunggah.
    data = b'hello world'

    # Panggil metode put_object dari klien enkripsi untuk mengunggah objek terenkripsi.
    result = encryption_client.put_object(
        oss.PutObjectRequest(
            bucket=args.bucket,  # Nama bucket tujuan.
            key=args.key,        # Nama objek (jalur file).
            body=data,           # Data untuk diunggah.
        )
    )

    # Cetak hasil unggah objek terenkripsi.
    print(vars(result))

    # Panggil metode get_object dari klien enkripsi untuk mendapatkan konten objek terenkripsi.
    result = encryption_client.get_object(
        oss.GetObjectRequest(
            bucket=args.bucket,  # Nama bucket tujuan.
            key=args.key,        # Nama objek (jalur file).
        )
    )

    # Cetak hasil mendapatkan objek terenkripsi.
    print(vars(result))

    # Cetak konten objek yang didekripsi.
    print(result.body.read())


if __name__ == "__main__":
    # Titik masuk program. Panggil fungsi utama untuk menjalankan logika.
    main()
    

Referensi

  • Untuk informasi lebih lanjut tentang prinsip enkripsi sisi klien di OSS, lihat Enkripsi Sisi Klien.

  • Untuk informasi lebih lanjut tentang operasi enkripsi sisi klien di Python SDK V2, lihat Panduan Pengguna.

  • Untuk kode sampel lengkap menggunakan kunci master RSA untuk unggah dan unduh objek sederhana, lihat Contoh GitHub.

  • Untuk kode sampel lengkap menggunakan kunci master berbasis KMS untuk unggah dan unduh objek sederhana, lihat Contoh GitHub.