Proses penandatanganan V4 dengan program Anda sendiri
Tetap teratur dengan koleksi
Simpan dan kategorikan konten berdasarkan preferensi Anda.
Halaman ini berisi penjelasan mengenai algoritma untuk mengimplementasikan proses penandatanganan V4 agar Anda dapat membuat URL bertanda tangan kunci RSA Cloud Storage dalam alur kerja Anda sendiri, menggunakan bahasa pemrograman pilihan Anda.
Sebelum memulai
Sebelum membuat program yang mengimplementasikan proses penandatanganan V4, Anda harus
menyelesaikan langkah-langkah berikut:
Membuat akun layanan Jika sudah memiliki akun layanan,
Anda dapat melewati langkah ini. Untuk mengetahui informasi selengkapnya tentang akun layanan, lihat
Ringkasan akun layanan.
Misalnya, jika URL yang ditandatangani akan mengizinkan pengguna membaca data objek, akun layanan itu sendiri harus memiliki izin untuk membaca data objek.
Jika algoritma penandatanganan yang ingin Anda gunakan tidak terintegrasi dalam
Google Cloud, buat kunci pribadi baru, atau miliki kunci pribadi untuk akun layanan tersebut. Kunci dapat menggunakan format JSON atau PKCS12.
Algoritma untuk menandatangani URL
Program Anda harus mencakup langkah-langkah berikut:
Buat permintaan kanonis sebagai string. Permintaan kanonis menentukan elemen yang harus disertakan pengguna dalam permintaan mereka saat menggunakan URL yang ditandatangani.
Lihat Permintaan Kanonis untuk mengetahui detail tentang bagian dan format yang diperlukan.
Buat string-to-sign. String-to-sign adalah dasar pembuatan
tanda tangan dan menyertakan di dalamnya nilai hash berenkode hex
dari permintaan kanonis.
Lihat Tanda tangan untuk detail tentang format string-to-sign.
Tanda tangani string-to-sign menggunakan tanda tangan RSA dengan SHA-256. Hasil
penandatanganan ini adalah tanda tangan permintaan Anda. Ada beberapa opsi untuk
penandatanganan:
Anda dapat menggunakan library klien Cloud Storage untuk membuat URL bertanda tangan
untuk banyak bahasa pemrograman umum. Lihat proses penandatanganan V4 dengan alat Cloud Storage untuk mengetahui contohnya.
Contoh berikut menunjukkan implementasi algoritma untuk menandatangani URL yang tidak menggunakan library klien Cloud Storage. Contoh ini menggunakan bahasa pemrograman Python, tetapi dapat disesuaikan dengan bahasa pilihan Anda.
importbinasciiimportcollectionsimportdatetimeimporthashlibimportsysfromurllib.parseimportquote# pip install google-authfromgoogle.oauth2importservice_account# pip install siximportsixdefgenerate_signed_url(service_account_file,bucket_name,object_name,subresource=None,expiration=604800,http_method="GET",query_parameters=None,headers=None,):ifexpiration > 604800:print("Expiration Time can't be longer than 604800 seconds (7 days).")sys.exit(1)escaped_object_name=quote(six.ensure_binary(object_name),safe=b"/~")canonical_uri=f"/{escaped_object_name}"datetime_now=datetime.datetime.now(tz=datetime.timezone.utc)request_timestamp=datetime_now.strftime("%Y%m%dT%H%M%SZ")datestamp=datetime_now.strftime("%Y%m%d")google_credentials=service_account.Credentials.from_service_account_file(service_account_file)client_email=google_credentials.service_account_emailcredential_scope=f"{datestamp}/auto/storage/goog4_request"credential=f"{client_email}/{credential_scope}"ifheadersisNone:headers=dict()host=f"{bucket_name}.storage.googleapis.com"headers["host"]=hostcanonical_headers=""ordered_headers=collections.OrderedDict(sorted(headers.items()))fork,vinordered_headers.items():lower_k=str(k).lower()strip_v=str(v).lower()canonical_headers+=f"{lower_k}:{strip_v}\n"signed_headers=""fork,_inordered_headers.items():lower_k=str(k).lower()signed_headers+=f"{lower_k};"signed_headers=signed_headers[:-1]# remove trailing ';'ifquery_parametersisNone:query_parameters=dict()query_parameters["X-Goog-Algorithm"]="GOOG4-RSA-SHA256"query_parameters["X-Goog-Credential"]=credentialquery_parameters["X-Goog-Date"]=request_timestampquery_parameters["X-Goog-Expires"]=expirationquery_parameters["X-Goog-SignedHeaders"]=signed_headersifsubresource:query_parameters[subresource]=""canonical_query_string=""ordered_query_parameters=collections.OrderedDict(sorted(query_parameters.items()))fork,vinordered_query_parameters.items():encoded_k=quote(str(k),safe="")encoded_v=quote(str(v),safe="")canonical_query_string+=f"{encoded_k}={encoded_v}&"canonical_query_string=canonical_query_string[:-1]# remove trailing '&'canonical_request="\n".join([http_method,canonical_uri,canonical_query_string,canonical_headers,signed_headers,"UNSIGNED-PAYLOAD",])canonical_request_hash=hashlib.sha256(canonical_request.encode()).hexdigest()string_to_sign="\n".join(["GOOG4-RSA-SHA256",request_timestamp,credential_scope,canonical_request_hash,])# signer.sign() signs using RSA-SHA256 with PKCS1v15 paddingsignature=binascii.hexlify(google_credentials.signer.sign(string_to_sign)).decode()scheme_and_host="{}://{}".format("https",host)signed_url="{}{}?{}&x-goog-signature={}".format(scheme_and_host,canonical_uri,canonical_query_string,signature)returnsigned_url
[[["Mudah dipahami","easyToUnderstand","thumb-up"],["Memecahkan masalah saya","solvedMyProblem","thumb-up"],["Lainnya","otherUp","thumb-up"]],[["Sulit dipahami","hardToUnderstand","thumb-down"],["Informasi atau kode contoh salah","incorrectInformationOrSampleCode","thumb-down"],["Informasi/contoh yang saya butuhkan tidak ada","missingTheInformationSamplesINeed","thumb-down"],["Masalah terjemahan","translationIssue","thumb-down"],["Lainnya","otherDown","thumb-down"]],["Terakhir diperbarui pada 2025-08-18 UTC."],[],[],null,["# V4 signing process with your own program\n\nThis page describes an algorithm for implementing the V4 signing process so that\nyou can create Cloud Storage RSA key [signed URLs](/storage/docs/access-control/signed-urls) in your own\nworkflow, using a programming language of your choice.\n| **Note:** In most cases, it's faster and easier to create signed URLs by using the [V4 signing process with Cloud Storage tools](/storage/docs/access-control/signing-urls-with-helpers).\n\nBefore you begin\n----------------\n\nBefore creating a program that implements the V4 signing process, you must\ncomplete the following steps:\n\n1. [Create a service account](/iam/docs/creating-managing-service-accounts#creating_a_service_account). If you already have a service account,\n you can skip this step. For more information about service accounts, see\n [Service accounts overview](/iam/docs/service-account-overview).\n\n2. [Give the service account sufficient permission](/storage/docs/access-control/using-iam-permissions) such that it could\n perform the request that the signed URL will make.\n\n For example, if your signed URL will allow a user to read object data, the\n service account must itself have permission to read the object data.\n3. If the [signing algorithm](/storage/docs/authentication/signatures#signing-process) you intend to use is not built into\n Google Cloud, [generate a new private key](/iam/docs/creating-managing-service-account-keys#creating_service_account_keys), or have an existing\n private key for the service account. The key can be in either JSON or\n PKCS12 format.\n\nAlgorithm for signing URLs\n--------------------------\n\nYour program should include the following steps:\n\n1. Construct the *canonical request* as a string. The canonical request defines\n elements that users must include in their request when they use your\n signed URL.\n\n See [Canonical Requests](/storage/docs/authentication/canonical-requests) for details about the parts and format required.\n2. Construct the *string-to-sign*. The string-to-sign is the basis for creating\n a signature and includes within it the hex-encoded hash value of the\n canonical request.\n\n See [Signatures](/storage/docs/authentication/signatures) for details about the format of the string-to-sign.\n3. Sign the string-to-sign using an RSA signature with SHA-256. The result\n of this signing is your *request signature*. There are several options for\n signing:\n\n - You can [use the IAM `signBlob` method](/storage/docs/authentication/creating-signatures) provided by\n Google Cloud.\n\n - You can use a programming language that has a library for performing RSA\n signatures.\n\n | **Note:** You can also [sign the string-to-sign using HMAC](/storage/docs/authentication/signatures#signing-process) if you are using the XML API for interoperable access.\n4. Construct the *signed URL* by using the following concatenation:\n\n ```html\n HOSTNAME + PATH_TO_RESOURCE + \"?\" + CANONICAL_QUERY_STRING + \"&X-Goog-Signature=\" + REQUEST_SIGNATURE\n ```\n\n The signed URL has the following components:\n - \u003cvar translate=\"no\"\u003eHOSTNAME\u003c/var\u003e: This should be `https://storage.googleapis.com`.\n\n - \u003cvar translate=\"no\"\u003ePATH_TO_RESOURCE\u003c/var\u003e: This should match the value you used in\n constructing the canonical request.\n\n - \u003cvar translate=\"no\"\u003eCANONICAL_QUERY_STRING\u003c/var\u003e: This should match the values you used\n in constructing the canonical request.\n\n - \u003cvar translate=\"no\"\u003eREQUEST_SIGNATURE\u003c/var\u003e: This is the output from using an RSA\n signature in the previous step, hex-encoded.\n\n Here is a sample completed URL: \n\n ```\n https://storage.googleapis.com/example-bucket/cat.jpeg?X-Goog-Algorithm=GOOG4-\n RSA-SHA256&X-Goog-Credential=example%40example-project.iam.gserviceaccount.com\n %2F20181026%2Fus%2Fstorage%2Fgoog4_request&X-Goog-Date=20181026T211942Z&X-Goog\n -expires=3600&X-Goog-Signedheaders=host&X-Goog-Signature=2d2a6f5055eb004b8690b\n 9479883292ae7450cdc15f17d7f99bc49b916f9e7429106ed7e5858ae6b4ab0bbbdb1a8ccc364d\n ad3a0da2caebd30887a70c5b2569d089ceb8afbde3eed4dff5086f0db5483998c175980991fe89\n 9fbd2cd8cb813b00165e8d56e0a8aa7b3d7a12ee1baa8400611040f05b50a1a8eab5ba223fe137\n 5747748de950ec7a4dc50f8382a6ffd4994ac42498d7daa703d9a414d4475154d0e7edaa92d4f2\n 507d92c1f7e8efa7cab64df68b5df48575b9259d8d0bdb5dc752bdf07bd162d98ff2924f2e4a26\n fa6b3cede73ad5333c47d146a21c2ab2d97115986a12c68ff37346d6c2ca83e56b8ec8ad956327\n 10b489b75c35697d781c38e\n ```\n\nPython sample program\n---------------------\n\nYou can use the Cloud Storage client libraries to create signed URLs\nfor many common programming languages. See [V4 signing process with\nCloud Storage tools](/storage/docs/access-control/signing-urls-with-helpers) for examples.\n\nThe following sample shows an implementation of the algorithm for signing URLs\nthat does not use the Cloud Storage client libraries. The sample uses\nthe Python programming language but can be adapted to the language of your\nchoice. \n\n import binascii\n import collections\n import datetime\n import hashlib\n import sys\n from urllib.parse import quote\n\n # pip install google-auth\n from google.oauth2 import service_account\n\n # pip install six\n import six\n\n\n def generate_signed_url(\n service_account_file,\n bucket_name,\n object_name,\n subresource=None,\n expiration=604800,\n http_method=\"GET\",\n query_parameters=None,\n headers=None,\n ):\n if expiration \u003e 604800:\n print(\"Expiration Time can't be longer than 604800 seconds (7 days).\")\n sys.exit(1)\n\n escaped_object_name = quote(six.ensure_binary(object_name), safe=b\"/~\")\n canonical_uri = f\"/{escaped_object_name}\"\n\n datetime_now = datetime.datetime.now(tz=datetime.timezone.utc)\n request_timestamp = datetime_now.strftime(\"%Y%m%dT%H%M%SZ\")\n datestamp = datetime_now.strftime(\"%Y%m%d\")\n\n google_credentials = service_account.Credentials.from_service_account_file(\n service_account_file\n )\n client_email = google_credentials.service_account_email\n credential_scope = f\"{datestamp}/auto/storage/goog4_request\"\n credential = f\"{client_email}/{credential_scope}\"\n\n if headers is None:\n headers = dict()\n host = f\"{bucket_name}.storage.googleapis.com\"\n headers[\"host\"] = host\n\n canonical_headers = \"\"\n ordered_headers = collections.OrderedDict(sorted(headers.items()))\n for k, v in ordered_headers.items():\n lower_k = str(k).lower()\n strip_v = str(v).lower()\n canonical_headers += f\"{lower_k}:{strip_v}\\n\"\n\n signed_headers = \"\"\n for k, _ in ordered_headers.items():\n lower_k = str(k).lower()\n signed_headers += f\"{lower_k};\"\n signed_headers = signed_headers[:-1] # remove trailing ';'\n\n if query_parameters is None:\n query_parameters = dict()\n query_parameters[\"X-Goog-Algorithm\"] = \"GOOG4-RSA-SHA256\"\n query_parameters[\"X-Goog-Credential\"] = credential\n query_parameters[\"X-Goog-Date\"] = request_timestamp\n query_parameters[\"X-Goog-Expires\"] = expiration\n query_parameters[\"X-Goog-SignedHeaders\"] = signed_headers\n if subresource:\n query_parameters[subresource] = \"\"\n\n canonical_query_string = \"\"\n ordered_query_parameters = collections.OrderedDict(sorted(query_parameters.items()))\n for k, v in ordered_query_parameters.items():\n encoded_k = quote(str(k), safe=\"\")\n encoded_v = quote(str(v), safe=\"\")\n canonical_query_string += f\"{encoded_k}={encoded_v}&\"\n canonical_query_string = canonical_query_string[:-1] # remove trailing '&'\n\n canonical_request = \"\\n\".join(\n [\n http_method,\n canonical_uri,\n canonical_query_string,\n canonical_headers,\n signed_headers,\n \"UNSIGNED-PAYLOAD\",\n ]\n )\n\n canonical_request_hash = hashlib.sha256(canonical_request.encode()).hexdigest()\n\n string_to_sign = \"\\n\".join(\n [\n \"GOOG4-RSA-SHA256\",\n request_timestamp,\n credential_scope,\n canonical_request_hash,\n ]\n )\n\n # signer.sign() signs using RSA-SHA256 with PKCS1v15 padding\n signature = binascii.hexlify(\n google_credentials.signer.sign(string_to_sign)\n ).decode()\n\n scheme_and_host = \"{}://{}\".format(\"https\", host)\n signed_url = \"{}{}?{}&x-goog-signature={}\".format(\n scheme_and_host, canonical_uri, canonical_query_string, signature\n )\n\n return signed_url\n\nWhat's next\n-----------\n\n- [Learn how to sign URLs with Cloud Storage tools](/storage/docs/access-control/signing-urls-with-helpers) such as client libraries or the Google Cloud CLI.\n- [Learn more about signed URLs](/storage/docs/access-control/signed-urls).\n- [Learn about canonical requests](/storage/docs/authentication/canonical-requests), which underpin signed URLs."]]