1# 数据库加密
2
3
4## 场景介绍
5
6为了增强数据库的安全性,数据库提供了一个安全适用的数据库加密能力,从而对数据库存储的内容实施有效保护。通过数据库加密等安全方法实现了数据库数据存储的保密性和完整性要求,使得数据库以密文方式存储并在密态方式下工作,确保了数据安全。
7
8加密后的数据库只能通过接口进行访问,无法通过其它方式打开数据库文件。数据库的加密属性在创建数据库时确认,无法变更。
9
10键值型数据库和关系型数据库均支持数据库加密操作,其中关系型数据库支持自定义加密/解密的密钥和其他参数。
11
12
13## 键值型数据库加密
14
15键值型数据库,通过options中encrypt参数来设置是否加密,默认为false,表示不加密。encrypt参数为true时表示加密。
16
17具体接口及功能,可见[分布式键值数据库](../reference/apis-arkdata/js-apis-distributedKVStore.md)。
18
19```ts
20import { distributedKVStore } from '@kit.ArkData';
21import { BusinessError } from '@kit.BasicServicesKit';
22
23let kvManager: distributedKVStore.KVManager | undefined = undefined;
24let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
25let context = getContext(this);
26const kvManagerConfig: distributedKVStore.KVManagerConfig = {
27  context: context,
28  bundleName: 'com.example.datamanagertest',
29}
30try {
31  kvManager = distributedKVStore.createKVManager(kvManagerConfig);
32  console.info('Succeeded in creating KVManager.');
33} catch (e) {
34  let error = e as BusinessError;
35  console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);
36}
37if (kvManager !== undefined) {
38  kvManager = kvManager as distributedKVStore.KVManager;
39  try {
40    const options: distributedKVStore.Options = {
41      createIfMissing: true,
42      // 设置数据库加密
43      encrypt: true,
44      backup: false,
45      autoSync: false,
46      kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
47      securityLevel: distributedKVStore.SecurityLevel.S3
48    };
49    kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => {
50      if (err) {
51        console.error(`Fail to get KVStore. Code:${err.code},message:${err.message}`);
52        return;
53      }
54      console.info('Succeeded in getting KVStore.');
55      kvStore = store;
56    });
57  } catch (e) {
58    let error = e as BusinessError;
59    console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
60  }
61}
62if (kvStore !== undefined) {
63  kvStore = kvStore as distributedKVStore.SingleKVStore;
64    //进行后续操作
65    //...
66}
67```
68
69
70## 关系型数据库加密
71
72关系型数据库,通过[StoreConfig](../reference/apis-arkdata/js-apis-data-relationalStore.md#storeconfig)中encrypt属性来设置是否加密。encrypt参数为true时表示加密;为false时表示不加密;默认值为false。
73
74当encrypt为true时,支持开发者通过ArkTs API中的可选属性cryptoParam设置自定义的加密/解密密钥和算法等参数。Native侧暂不支持此配置项。
75
76针对cryptoParam的配置与否,有如下两种场景:
77
78场景1:不配置cryptoParam属性,此时会使用默认的加密配置进行数据库的加密/解密。
79
80
81```ts
82import { relationalStore } from '@kit.ArkData';
83
84let store: relationalStore.RdbStore;
85let context = getContext(this);
86const STORE_CONFIG: relationalStore.StoreConfig = {
87  name: 'RdbTest.db',
88  securityLevel: relationalStore.SecurityLevel.S3,
89  encrypt: true
90};
91relationalStore.getRdbStore(context, STORE_CONFIG, (err, rdbStore) => {
92  store = rdbStore;
93  if (err) {
94    console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`);
95    return;
96  }
97  console.info('Succeeded in getting RdbStore.');
98})
99```
100
101场景2:配置cryptoParam属性,此时会使用开发者自定义的密钥和算法参数进行数据库的加密/解密。
102
103```ts
104import { relationalStore } from '@kit.ArkData';
105
106let context = getContext(this);
107
108// 初始化需要使用的密钥
109let key = new Uint8Array(32);
110for (let i = 0; i < 32; i++) {
111    key[i] = i;
112}
113
114// 初始化加密算法
115const CRYPTO_PARAM : relationalStore.CryptoParam = {
116    encryptionKey: key, // 必选参数,使用指定的密钥打开加密数据库。为空则由数据库负责生成并保存密钥,并使用生成的密钥打开数据库文件。
117    iterationCount: 25000, // 可选参数,迭代次数。迭代次数必须大于零。不指定或等于零则使用默认值10000和默认加密算法。
118    encryptionAlgo: relationalStore.EncryptionAlgo.AES_256_CBC, // 可选参数,加密/解密算法。如不指定,默认算法为AES_256_GCM。
119    hmacAlgo: relationalStore.HmacAlgo.SHA256, // 可选参数,HMAC算法。如不指定,默认值为SHA256。
120    kdfAlgo: relationalStore.KdfAlgo.KDF_SHA512, // 可选参数,KDF算法。如不指定,默认值和HMAC算法相等。
121    cryptoPageSize: 2048 // 可选参数,加密/解密时使用的页大小。必须为1024到65536范围内的整数并且为2的幂。如不指定,默认值为1024。
122}
123
124const STORE_CONFIG : relationalStore.StoreConfig = {
125    name: "encrypted.db",
126    securityLevel: relationalStore.SecurityLevel.S3,
127    encrypt: true,
128    cryptoParam: CRYPTO_PARAM
129}
130
131async function run() {
132    let store = await relationalStore.getRdbStore(context, STORE_CONFIG);
133    if (store == null) {
134      console.error('Failed to get RdbStore.');
135    } else {
136      console.info('Succeeded in getting RdbStore.');
137    }
138    // 调用完后需要将密钥清零
139    CRYPTO_PARAM.encryptionKey.fill(0);
140}
141
142run();
143```
144
145如果开发者不关心加密使用的算法及参数,则无需配置cryptoParam属性,使用默认加密配置即可。当开发者需要自定义加密配置,或需要打开非默认配置的加密数据库时,则需要配置cryptoParam属性。
146