If you enable the always-confidential database feature for your ApsaraDB RDS for PostgreSQL instance, the ciphertext data of different users on the RDS instance is automatically isolated. This topic describes how to manage permissions to implement integrated computing of multi-user data and how to authorize database administrators (DBAs) to perform high-risk data operations.
Feature description
In an always-confidential database, user data is encrypted by using the data encryption keys (DEKs) of the users. The ciphertext data of different users is automatically isolated. If a joint query involves data from multiple users, the data owner must grant the permissions to the subject that wants to query data to access the ciphertext data of the data owner. This process is called multi-user authorization management.
In an always-confidential database, you can use a behavior control list (BCL) to grant access permissions on multi-user data. After a BCL is issued, the subject can perform joint queries without the need to understand the data content of the issuer that owns the data. The issuer does not need to worry about data leaks and can issue or revoke the BCL to limit the behavior of the subject. This promptly and effectively prevents the data from being used unexpectedly.
If you want to authorize a DBA to perform high-risk operations on an always-confidential database, such as creating a custom key or converting data between plaintext and ciphertext, you can issue a BCL. This way, the DBA can perform relevant operations by using an account. In this case, the subject and the issuer use the same account.
Prerequisites
The always-confidential database feature is enabled. For more information, see Enable the always-confidential database feature.
NoteThe minor engine version of the RDS instance is 20230830 or later. For more information about how to update the minor engine version of an RDS instance, see Update the minor engine version.
Accounts are separately created for the subject and the issuer. For more information, see Create an account.
Sensitive data is defined. For more information, see Define sensitive data.
The EncDB SDK is used by the subject and the issuer to separately log on to the required database and construct test data in the database. For more information, see Use the always-confidential database feature from a client.
Step 1: Initialize the public and private keys
Install OpenSSL.
In this topic, OpenSSL, an open source cryptographic toolkit, is used to obtain the public and private keys. Linux operating systems are provided with OpenSSL. If you use a Linux operating system, you do not need to install OpenSSL. If you use a Windows operating system, you must download the OpenSSL software package and install OpenSSL. For more information, see Win32/Win64 OpenSSL.
NoteIf you use an RDS instance for which the always-confidential database (basic edition) feature is enable, you must use the SM2 algorithm to generate public and private keys. You can run the
openssl ecparam -list_curves
command to check whether the SM2 algorithm is supported by the current OpenSSL version. RDS instances for which the always-confidential database (basic edition) feature is enabled are the RDS instances that use non-Intel SGX-based security-enhanced instance types. If SM2 is included in the command output, the SM2 algorithm is supported. If SM2 is not included in the command output, you must upgrade OpenSSL to a version that supports the SM2 algorithm. You can upgrade OpenSSL to V1.1.1 or later.Obtain the public and private keys of the subject and the issuer based on the instance type of the RDS instance for which the always-confidential database feature is enabled.
Two key files are generated. The
pub_key.pem
file is the public key file. Thepri_key_pkcs8.pem
file is the private key file.Hardware-enhanced edition of the always-confidential database feature (Intel SGX-based)
RDS instances for which the always-confidential database (hardware-enhanced edition) feature is enabled are the RDS instances that use Intel SGX-based security-enhanced instance types. For more information, see Instance types for primary ApsaraDB RDS for PostgreSQL instances.
You can perform the following operations to obtain the public and private keys:
Use OpenSSL to generate a Rivest-Shamir-Adleman (RSA) private key.
openssl genpkey -algorithm RSA -out pri_key_pkcs8.pem -pkeyopt rsa_keygen_bits:3072
Note3072: the key length. You can change the key length to a different value that complies with the security standards based on your business requirements.
Use OpenSSL to generate an RSA public key.
openssl rsa -in pri_key_pkcs8.pem -pubout -out pub_key.pem
Basic edition of the always-confidential database feature
RDS instances for which the always-confidential database (basic edition) feature is enabled are the RDS instances that use non-Intel SGX-based security-enhanced instance types. For more information, see Instance types for primary ApsaraDB RDS for PostgreSQL instances.
You can perform the following operations to obtain the public and private keys:
Use OpenSSL to generate an SM2 private key.
# Generate a private key in the Public-Key Cryptography Standards (PKCS)#1 format. openssl ecparam -out ec_param.pem -name SM2 -param_enc explicit -genkey # Convert the private key into the PKCS#8 format. openssl pkcs8 -topk8 -inform PEM -in ec_param.pem -outform pem -nocrypt -out pri_key_pkcs8.pem
Use OpenSSL to generate an SM2 public key.
openssl ec -in ec_param.pem -pubout -out pub_key.pem
Separately initialize the public and private keys of the subject and the issuer.
Initialize the public and private keys of the subject and the issuer in their business code.
NoteNewlines are automatically added in PEM files that are generated by using OpenSSL. In specific editors, the display of the newlines may be optimized. As a result, when you manually copy the content of a PEM file, newlines are omitted. We recommend that you use program code to read the content of the PEM file to ensure data accuracy.
//The private keys of the subject and the issuer. String userPrkPemString = readPemFile("path/to/pri_key_pkcs8.pem"); //The public keys of the subject and the issuer. String userPukPemString = readPemFile("path/to/pub_key.pem"); //Key initialization. The keys need to be initialized only once. KeyManager km = sdk.getKeyManager(); km.registerCertificate(userPrkPemString, userPukPemString);
Step 2: Grant access permissions on multi-user data
Define the authorization content.
String bclBodyJsonString = """{ "version": 1, "serial_num": "a121bac0-5cb3-4463-a2b2-1155ff29f4c8", "issuer_pukid": "p81x+WqYb7BR0yP0LK0qiEaxgLDqwuIjfJhgC0mMJcE=", "subject_pukid": "qIPPfgTJEEG/9WkjP0E5LLAijZ14h/Qgb2EfmBZCWSo=", "validity": { "not_after": "20250820111111+0800", "not_before": "20240820111111+0800" }, "policies": { "issuer_dek_group": [ { "min": 1, "max": 100000, "groupid": "5bc60759-5b05-45ec-afc1-ffca1229e554" } ], "result_dek": "SUBJECT", "subject_dek_group": [ { "min": 1, "max": 100000, "groupid": "53413af9-f90a-48a9-93b6-49847861b823" } ], "operation": [ "*" ], "postproc": "NULL", "preproc": "NULL" } } """;
Parameter description
Parameter
Example value
Description
version
1
The version number. Set the value to 1.
serial_num
"a121bac0-5cb3-4463-a2b2-1155ff29f4c8"
A unique, random serial number in the UUID format.
NoteYou can use the UUID generation tool to generate serial numbers.
issuer_pukid
"p81x+WqYb7BR0yP0LK0qiEaxgLDqwuIjfJhgC0mMJcE="
The public key digest of the issuer. You can run the following code to obtain the public key digest based on the edition of the always-confidential database feature and the generated public key file pub_key.pem:
Hardware-enhanced edition (Intel SGX-based)
openssl sha256 -binary pub_key.pem | openssl base64
Basic edition
openssl sm3 -binary pub_key.pem | openssl base64
subject_pukid
"qIPPfgTJEEG/9WkjP0E5LLAijZ14h/Qgb2EfmBZCWSo="
The public key digest of the subject. You can configure this parameter the same way you configure the issuer_pukid parameter.
validity
{ "not_before": "20240820111111+0800", "not_after": "20250820111111+0800"}
The validity period of the authorization. The value must be in the GeneralizedTime time format.
"not_before": the beginning of the validity period.
"not_after": the end of the validity period.
policies
issuer_dek_group
[ { "min": 1, "max": 100000, "groupid": "5bc60759-5b05-45ec-afc1-ffca1229e554" }]
The group of DEKs that are allowed by the issuer.
"groupid": the ID of the DEK group
"min": the smallest DEK ID in the DEK group
"max": the largest DEK ID in the DEK group
NoteIn a DEK group, the values of the DEK IDs must monotonically increase.
You can run the following code to obtain the value of the groupid parameter:
SELECT encdb_get_cc_entry_by_name(encdb.keyname_generate('<user_name>', '<database_name>', '<schema_name>', '<table_name>', '<column_name>'));
Note<user_name>
: the username of the issuer<table_name>
: the name of the table that the issuer allows the subject to access<column_name>
: the name of the column that the issuer allows the subject to access
subject_dek_group
[ { "min": 1, "max": 100000, "groupid": "53413af9-f90a-48a9-93b6-49847861b823" }]
The DEK group that the subject is allowed to access.
"groupid": the ID of the DEK group
"min": the smallest DEK ID in the DEK group
"max": the largest DEK ID in the DEK group
NoteIn a DEK group, the values of the DEK IDs must monotonically increase.
You can run the following code to obtain the value of the groupid parameter:
SELECT encdb_get_cc_entry_by_name(encdb.keyname_generate('<user_name>', '<database_name>', '<schema_name>', '<table_name>', '<column_name>'));
Note<user_name>
: the username of the subject<table_name>
: the name of the table that the subject is allowed to access.<column_name>
: the name of the column that the subject is allowed to access.
result_dek
"SUBJECT"
The DEK that is used to encrypt the computation result.
"SUBJECT": uses the DEK of the subject in the current computation.
"ISSUER": uses the DEK of the issuer in the current computation.
DEK ID: uses the DEK with the specified DEK ID.
ImportantIf you want to use a specific DEK, set this parameter to
the ID of the DEK
. You can directly specify the DEK ID without the need to enclose the DEK ID in double quotation marks ("").
operation
[ "*"]
The allowed computation operations.
"encrypt": encryption
"decrypt": decryption
"cmp": comparison
"*": all operations
postproc
"NULL"
The pre-processing operation before the computation. Set the value to NULL, which specifies that no pre-processing operations are required.
preproc
"NULL"
The post-processing operation after the computation. Set the value to NULL, which specifies that no post-processing operations are required.
Grant access permissions on multi-user data
The issuer uses its public and private keys to issue a BCL to authorize the subject to access the data in the permitted column.
boolean isIssuer = true; bclBodyJsonString = km.issueBCL(bclBodyJsonString, userPukPemString, userPrkPemString, isIssuer);
The subject uses its public and private keys to issue a BCL and access the permitted data.
boolean isIssuer = false; bclBodyJsonString = km.issueBCL(bclBodyJsonString, userPukPemString, userPrkPemString, isIssuer);
(Optional) Step 3: Revoke the authorization
If the issuer wants to revoke the authorization, perform the following operations:
Define the authorization that is to be revoked.
String brlBodyJsonString = """{ "version": 1, "pukid": "dYJ3Wfj/n0eZbuqgQjv8bnBdPXGyWGOlxE/uMy16NXo=", "this_update": "20220819111128+0800", "next_update": "20220919111128+0800", "revoked": [ { "revocation_date": "20220819111128+0800", "serial_num": "a121bac0-5cb3-4463-a2b2-1155ff29f4c8" } ] } """;
Parameter description
Parameter
Example value
Description
version
1
The version number. Set the value to 1.
pukid
"dYJ3Wfj/n0eZbuqgQjv8bnBdPXGyWGOlxE/uMy16NXo="
The public key digest of the issuer. Set the value to the public key digest of the issuer in the BCL authorization application. You can configure this parameter the same way you configure the parameter described in Define the authorization content.
this_update
"20220819111128+0800"
The point in time at which the revocation list is updated. The value must be in the GeneralizedTime time format.
next_update
"20220919111128+0800"
The next update time of the revocation list. The value must be in the GeneralizedTime time format.
revoked
revocation_date
"20220819111128+0800"
The point in time at which the authorization is revoked. The value must be in the GeneralizedTime time format.
serial_num
"a121bac0-5cb3-4463-a2b2-1155ff29f4c8"
The serial number in the UUID format. You must set this parameter to the serial number that is specified in the BCL authorization application.
The issuer approves and issues the revocation.
brlBodyJsonString = km.revokeBCL(brlBodyJsonString, userPukPemString, userPrkPemString);
Scenarios
Scenario 1: High-risk operations: data conversion between plaintext and ciphertext
If you want to enable the always-confidential database feature for an existing plaintext database without the need to migrate data, you can directly convert the plaintext data on the database to ciphertext data. For more information, see Convert data between plaintext and ciphertext. By default, users including DBAs cannot perform data conversion between plaintext and ciphertext on always-confidential databases because this operation is considered as a high-risk operation.
If you understand and acknowledge data security risks, you can issue a BCL to authorize the required user to directly convert data between plaintext and ciphertext on an always-confidential database. In this case, the subject and the issuer use the same account.
When you define the content of a BCL, you must set the
issuer_pukid
parameter to the same value as thesubject_pukid
parameter and theissuer_dek_group
parameter to the same value as thesubject_dek_group
parameter. For more information, see Define the authorization content.When you initialize the public and private keys, the subject and the issuer use the same public and private keys. The public key is specified by the
userPukPemString
parameter, and the private key is specified by theuserPrkPemString
parameter. The values of the userPukPemString and userPrkPemString parameters for the issuer are the same as the values of those for the subject. For more information, see Initialize the public and private keys.
After you issue a BCL, you can perform the required operations by using the authorized account. Sample code:
Scenario 2: Joint queries of multi-user data
For example, a data platform company obtains the required permissions to use the data platform to collect user data and generate user profiles. Then, the data platform company authorizes a third party, such as an insurance company, to use the data for multi-party data integration and computing. This helps implement joint marketing. For more information, see Multi-party data integration and computing.
The following code provides an example on how to perform joint queries.