1# Database Encryption (ArkTS) 2 3## When to Use 4 5OpenHarmony provides the database encryption capability to effectively protect the data stored in a database. Database encryption allows data to be stored and used in ciphertext, ensuring data confidentiality and integrity. 6 7The encrypted database can be accessed only using an API, and the database file cannot be opened in other ways. Whether a database is encrypted is set when the database is created, and the setting cannot be changed. 8 9Both KV stores and RDB stores support database encryption. For RDB stores, you can custom the encryption/decryption keys and other parameters. 10 11 12## Encrypting a KV Store 13 14When a KV store is created, the **encrypt** parameter in **options** specifies whether to encrypt it. The value **true** means to encrypt the KV store, and the value **false** (default) means the opposite. 15 16For details about the APIs, see [Distributed KV Store](../reference/apis-arkdata/js-apis-distributedKVStore.md). 17 18```ts 19import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; 20import { hilog } from '@kit.PerformanceAnalysisKit'; 21import { distributedKVStore } from '@kit.ArkData'; 22import { BusinessError } from '@kit.BasicServicesKit'; 23 24export default class EntryAbility extends UIAbility { 25 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { 26 this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); 27 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 28 let kvManager: distributedKVStore.KVManager | undefined = undefined; 29 let kvStore: distributedKVStore.SingleKVStore | undefined = undefined; 30 let context = this.context; 31 const kvManagerConfig: distributedKVStore.KVManagerConfig = { 32 context: context, 33 bundleName: 'com.example.datamanagertest', 34 } 35 try { 36 kvManager = distributedKVStore.createKVManager(kvManagerConfig); 37 console.info('Succeeded in creating KVManager.'); 38 } catch (e) { 39 let error = e as BusinessError; 40 console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`); 41 } 42 if (kvManager !== undefined) { 43 kvManager = kvManager as distributedKVStore.KVManager; 44 try { 45 const options: distributedKVStore.Options = { 46 createIfMissing: true, 47 // Whether to encrypt the KV store. 48 encrypt: true, 49 backup: false, 50 autoSync: false, 51 kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION, 52 securityLevel: distributedKVStore.SecurityLevel.S3 53 }; 54 kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => { 55 if (err) { 56 console.error(`Fail to get KVStore. Code:${err.code},message:${err.message}`); 57 return; 58 } 59 console.info('Succeeded in getting KVStore.'); 60 kvStore = store; 61 }); 62 } catch (e) { 63 let error = e as BusinessError; 64 console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`); 65 } 66 } 67 if (kvStore !== undefined) { 68 kvStore = kvStore as distributedKVStore.SingleKVStore; 69 // Perform subsequent operations. 70 //... 71 } 72 } 73} 74``` 75 76## Encrypting an RDB Store 77 78The **encrypt** property in [StoreConfig](../reference/apis-arkdata/arkts-apis-data-relationalStore-i.md#storeconfig) specifies whether to encrypt the RDB store. The value **true** means to encrypt the RDB store, and **false** means the opposite. 79 80If **encrypt** is **true**, you can set parameters such as the key and algorithm used for encryption/decryption in **cryptoParam** in ArkTS APIs. 81 82The **cryptoParam** setting involves the following scenarios: 83 84If **cryptoParam** is not set, the default configuration is used for database encryption and decryption. 85 86 87```ts 88import { UIAbility } from '@kit.AbilityKit'; 89import { relationalStore } from '@kit.ArkData'; 90import { BusinessError } from '@kit.BasicServicesKit'; 91 92export default class EntryAbility extends UIAbility { 93 async onCreate(): Promise<void> { 94 let store: relationalStore.RdbStore | undefined = undefined; 95 let context = this.context; 96 97 try { 98 const STORE_CONFIG: relationalStore.StoreConfig = { 99 name: 'RdbTest.db', 100 securityLevel: relationalStore.SecurityLevel.S3, 101 encrypt: true 102 }; 103 store = await relationalStore.getRdbStore(context, STORE_CONFIG); 104 console.info('Succeeded in getting RdbStore.'); 105 } catch (e) { 106 const err = e as BusinessError; 107 console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`); 108 } 109 } 110} 111``` 112 113If **cryptoParam** is set, the specified key and algorithm are used for database encryption and decryption. 114 115```ts 116import { UIAbility } from '@kit.AbilityKit'; 117import { relationalStore } from '@kit.ArkData'; 118import { BusinessError } from '@kit.BasicServicesKit'; 119 120export default class EntryAbility extends UIAbility { 121 async onCreate(): Promise<void> { 122 let store: relationalStore.RdbStore | undefined = undefined; 123 let context = this.context; 124 // Initialize the key to be used. 125 let key = new Uint8Array(32); 126 for (let i = 0; i < 32; i++) { 127 key[i] = i; 128 } 129 130 // Initialize the encryption algorithm. 131 const CRYPTO_PARAM: relationalStore.CryptoParam = { 132 encryptionKey: key, // (Mandatory) Key used to open the encrypted database. If this parameter is not specified, the database generates and saves the key and uses the generated key to open the database file. 133 iterationCount: 25000, // (Optional) Number of iterations. The value must be greater than or equal to 0. If this parameter is not specified or is set to 0, the default value 10000 and the default encryption algorithm are used. 134 encryptionAlgo: relationalStore.EncryptionAlgo.AES_256_CBC, // (Optional) Encryption/Decryption algorithm. If this parameter is not specified, the default algorithm AES_256_GCM is used. 135 hmacAlgo: relationalStore.HmacAlgo.SHA256, // (Optional) HMAC algorithm. If this parameter is not specified, the default value SHA256 is used. 136 kdfAlgo: relationalStore.KdfAlgo.KDF_SHA512, // (Optional) KDF algorithm. If this parameter is not specified, the default value (same as the HMAC algorithm) is used. 137 cryptoPageSize: 2048 // (Optional) Page size used for encryption/decryption. The value must be an integer within the range of 1024 to 65536 and a power of 2. The default value is 1024. 138 } 139 140 const STORE_CONFIG: relationalStore.StoreConfig = { 141 name: "encrypted.db", 142 securityLevel: relationalStore.SecurityLevel.S3, 143 encrypt: true, 144 cryptoParam: CRYPTO_PARAM 145 } 146 try { 147 let store = await relationalStore.getRdbStore(context, STORE_CONFIG); 148 if (store == null) { 149 console.error('Failed to get RdbStore.'); 150 } else { 151 console.info('Succeeded in getting RdbStore.'); 152 } 153 // Clear the key. 154 CRYPTO_PARAM.encryptionKey.fill(0); 155 } catch (e) { 156 const err = e as BusinessError; 157 console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`); 158 } 159 } 160} 161``` 162 163If you do not care about the algorithm and other parameters used for encryption, leave **cryptoParam** unspecified. In this case, the default encryption configuration is used. If you want to customize the encryption configuration or open an encrypted database that is not configured by default, set **cryptoParam**. 164