Skip to content

Commit a7fd50d

Browse files
add profile management and store copying to javascript wrappers
Signed-off-by: Andrew Whitehead <[email protected]>
1 parent d43a0bc commit a7fd50d

File tree

14 files changed

+388
-5
lines changed

14 files changed

+388
-5
lines changed

include/libaries_askar.h

+37
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ typedef struct FfiResultList_Entry FfiResultList_Entry;
3737

3838
typedef struct FfiResultList_KeyEntry FfiResultList_KeyEntry;
3939

40+
typedef struct FfiResultList_String FfiResultList_String;
41+
4042
/**
4143
* A stored key entry
4244
*/
@@ -221,6 +223,14 @@ typedef int64_t CallbackId;
221223

222224
typedef void (*LogCallback)(const void *context, int32_t level, const char *target, const char *message, const char *module_path, const char *file, int32_t line);
223225

226+
typedef struct FfiResultList_String FfiStringList;
227+
228+
typedef struct ArcHandle_FfiStringList {
229+
const FfiStringList *_0;
230+
} ArcHandle_FfiStringList;
231+
232+
typedef struct ArcHandle_FfiStringList StringListHandle;
233+
224234
#ifdef __cplusplus
225235
extern "C" {
226236
#endif // __cplusplus
@@ -524,17 +534,33 @@ ErrorCode askar_store_close(StoreHandle handle,
524534
void (*cb)(CallbackId cb_id, ErrorCode err),
525535
CallbackId cb_id);
526536

537+
ErrorCode askar_store_copy(StoreHandle handle,
538+
FfiStr target_uri,
539+
FfiStr key_method,
540+
FfiStr pass_key,
541+
int8_t recreate,
542+
void (*cb)(CallbackId cb_id, ErrorCode err, StoreHandle handle),
543+
CallbackId cb_id);
544+
527545
ErrorCode askar_store_create_profile(StoreHandle handle,
528546
FfiStr profile,
529547
void (*cb)(CallbackId cb_id, ErrorCode err, const char *result_p),
530548
CallbackId cb_id);
531549

532550
ErrorCode askar_store_generate_raw_key(struct ByteBuffer seed, const char **out);
533551

552+
ErrorCode askar_store_get_default_profile(StoreHandle handle,
553+
void (*cb)(CallbackId cb_id, ErrorCode err, const char *profile),
554+
CallbackId cb_id);
555+
534556
ErrorCode askar_store_get_profile_name(StoreHandle handle,
535557
void (*cb)(CallbackId cb_id, ErrorCode err, const char *name),
536558
CallbackId cb_id);
537559

560+
ErrorCode askar_store_list_profiles(StoreHandle handle,
561+
void (*cb)(CallbackId cb_id, ErrorCode err, StringListHandle results),
562+
CallbackId cb_id);
563+
538564
ErrorCode askar_store_open(FfiStr spec_uri,
539565
FfiStr key_method,
540566
FfiStr pass_key,
@@ -565,6 +591,17 @@ ErrorCode askar_store_remove_profile(StoreHandle handle,
565591
void (*cb)(CallbackId cb_id, ErrorCode err, int8_t removed),
566592
CallbackId cb_id);
567593

594+
ErrorCode askar_store_set_default_profile(StoreHandle handle,
595+
FfiStr profile,
596+
void (*cb)(CallbackId cb_id, ErrorCode err),
597+
CallbackId cb_id);
598+
599+
ErrorCode askar_string_list_count(StringListHandle handle, int32_t *count);
600+
601+
void askar_string_list_free(StringListHandle handle);
602+
603+
ErrorCode askar_string_list_get_item(StringListHandle handle, int32_t index, const char **item);
604+
568605
void askar_terminate(void);
569606

570607
char *askar_version(void);

wrappers/javascript/aries-askar-nodejs/src/NodeJSAriesAskar.ts

+54
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import type {
6868
SetCustomLoggerOptions,
6969
SetMaxLogLevelOptions,
7070
StoreCloseOptions,
71+
StoreCopyToOptions,
7172
StoreCreateProfileOptions,
7273
StoreGenerateRawKeyOptions,
7374
StoreGetProfileNameOptions,
@@ -80,6 +81,9 @@ import type {
8081
AriesAskarErrorObject,
8182
AeadParamsOptions,
8283
MigrateIndySdkOptions,
84+
StoreGetDefaultProfileOptions,
85+
StoreSetDefaultProfileOptions,
86+
StoreListProfilesOptions,
8387
} from '@hyperledger/aries-askar-shared'
8488

8589
import {
@@ -117,6 +121,7 @@ import {
117121
FFI_SESSION_HANDLE,
118122
FFI_STORE_HANDLE,
119123
FFI_INT8,
124+
FFI_STRING_LIST_HANDLE,
120125
} from './ffi'
121126
import { getNativeAriesAskar } from './library'
122127

@@ -902,6 +907,14 @@ export class NodeJSAriesAskar implements AriesAskar {
902907
return this.promisify((cb, cbId) => this.nativeAriesAskar.askar_store_close(storeHandle, cb, cbId))
903908
}
904909

910+
public storeCopyTo(options: StoreCopyToOptions): Promise<void> {
911+
const { storeHandle, targetUri, passKey, keyMethod, recreate } = serializeArguments(options)
912+
913+
return this.promisify((cb, cbId) =>
914+
this.nativeAriesAskar.askar_store_copy(storeHandle, targetUri, keyMethod, passKey, recreate, cb, cbId)
915+
)
916+
}
917+
905918
public async storeCreateProfile(options: StoreCreateProfileOptions): Promise<string> {
906919
const { storeHandle, profile } = serializeArguments(options)
907920
const response = await this.promisifyWithResponse<string>(
@@ -922,6 +935,15 @@ export class NodeJSAriesAskar implements AriesAskar {
922935
return ret.deref() as string
923936
}
924937

938+
public async storeGetDefaultProfile(options: StoreGetDefaultProfileOptions): Promise<string> {
939+
const { storeHandle } = serializeArguments(options)
940+
const response = await this.promisifyWithResponse<string>((cb, cbId) =>
941+
this.nativeAriesAskar.askar_store_get_default_profile(storeHandle, cb, cbId)
942+
)
943+
944+
return handleInvalidNullResponse(response)
945+
}
946+
925947
public async storeGetProfileName(options: StoreGetProfileNameOptions): Promise<string> {
926948
const { storeHandle } = serializeArguments(options)
927949
const response = await this.promisifyWithResponse<string>((cb, cbId) =>
@@ -931,6 +953,30 @@ export class NodeJSAriesAskar implements AriesAskar {
931953
return handleInvalidNullResponse(response)
932954
}
933955

956+
public async storeListProfiles(options: StoreListProfilesOptions): Promise<string[]> {
957+
const { storeHandle } = serializeArguments(options)
958+
const listHandle = await this.promisifyWithResponse<Buffer>(
959+
(cb, cbId) => this.nativeAriesAskar.askar_store_list_profiles(storeHandle, cb, cbId),
960+
FFI_STRING_LIST_HANDLE
961+
)
962+
if (listHandle === null) {
963+
throw AriesAskarError.customError({ message: 'Invalid handle' })
964+
}
965+
const counti32 = allocateInt32Buffer()
966+
this.nativeAriesAskar.askar_string_list_count(listHandle, counti32)
967+
this.handleError()
968+
const count = counti32.deref() as number
969+
const ret = []
970+
const strval = allocateStringBuffer()
971+
for (let i = 0; i < count; i++) {
972+
this.nativeAriesAskar.askar_string_list_get_item(listHandle, i, strval)
973+
this.handleError()
974+
ret.push(strval.deref())
975+
}
976+
this.nativeAriesAskar.askar_string_list_free(listHandle)
977+
return ret
978+
}
979+
934980
public async storeOpen(options: StoreOpenOptions): Promise<StoreHandle> {
935981
const { profile, keyMethod, passKey, specUri } = serializeArguments(options)
936982

@@ -983,6 +1029,14 @@ export class NodeJSAriesAskar implements AriesAskar {
9831029
return handleInvalidNullResponse(response)
9841030
}
9851031

1032+
public async storeSetDefaultProfile(options: StoreSetDefaultProfileOptions): Promise<void> {
1033+
const { storeHandle, profile } = serializeArguments(options)
1034+
1035+
return this.promisify((cb, cbId) =>
1036+
this.nativeAriesAskar.askar_store_set_default_profile(storeHandle, profile, cb, cbId)
1037+
)
1038+
}
1039+
9861040
public async migrateIndySdk(options: MigrateIndySdkOptions): Promise<void> {
9871041
const { specUri, kdfLevel, walletKey, walletName } = serializeArguments(options)
9881042
await this.promisify((cb, cbId) =>

wrappers/javascript/aries-askar-nodejs/src/ffi/primitives.ts

+1
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ export const FFI_LOCAL_KEY_HANDLE = FFI_ARC_HANDLE
3333
export const FFI_SESSION_HANDLE = FFI_USIZE
3434
export const FFI_SCAN_HANDLE = FFI_USIZE
3535
export const FFI_STORE_HANDLE = FFI_USIZE
36+
export const FFI_STRING_LIST_HANDLE = FFI_ARC_HANDLE

wrappers/javascript/aries-askar-nodejs/src/library/bindings.ts

+12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
FFI_STORE_HANDLE,
1919
FFI_STRING,
2020
FFI_STRING_PTR,
21+
FFI_STRING_LIST_HANDLE,
2122
SecretBufferStruct,
2223
SecretBufferStructPtr,
2324
ByteBufferStruct,
@@ -42,6 +43,10 @@ export const nativeBindings = {
4243
askar_entry_list_get_tags: [FFI_ERROR_CODE, [FFI_ENTRY_LIST_HANDLE, FFI_INT32, FFI_STRING_PTR]],
4344
askar_entry_list_get_value: [FFI_ERROR_CODE, [FFI_ENTRY_LIST_HANDLE, FFI_INT32, SecretBufferStructPtr]],
4445

46+
askar_string_list_count: [FFI_ERROR_CODE, [FFI_STRING_LIST_HANDLE, FFI_INT32_PTR]],
47+
askar_string_list_free: [FFI_ERROR_CODE, [FFI_STRING_LIST_HANDLE]],
48+
askar_string_list_get_item: [FFI_ERROR_CODE, [FFI_STRING_LIST_HANDLE, FFI_INT32, FFI_STRING_PTR]],
49+
4550
askar_key_aead_decrypt: [
4651
FFI_ERROR_CODE,
4752
[FFI_POINTER, ByteBufferStruct, ByteBufferStruct, ByteBufferStruct, ByteBufferStruct, SecretBufferStructPtr],
@@ -183,9 +188,15 @@ export const nativeBindings = {
183188
],
184189

185190
askar_store_close: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
191+
askar_store_copy: [
192+
FFI_ERROR_CODE,
193+
[FFI_STORE_HANDLE, FFI_STRING, FFI_STRING, FFI_STRING, FFI_INT8, FFI_CALLBACK_PTR, FFI_CALLBACK_ID],
194+
],
186195
askar_store_create_profile: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
187196
askar_store_generate_raw_key: [FFI_ERROR_CODE, [ByteBufferStruct, FFI_STRING_PTR]],
188197
askar_store_get_profile_name: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
198+
askar_store_get_default_profile: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
199+
askar_store_list_profiles: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
189200
askar_store_open: [
190201
FFI_ERROR_CODE,
191202
[FFI_STRING, FFI_STRING, FFI_STRING, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID],
@@ -197,6 +208,7 @@ export const nativeBindings = {
197208
askar_store_rekey: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_STRING, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
198209
askar_store_remove: [FFI_ERROR_CODE, [FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
199210
askar_store_remove_profile: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
211+
askar_store_set_default_profile: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
200212

201213
askar_migrate_indy_sdk: [
202214
FFI_ERROR_CODE,

wrappers/javascript/aries-askar-nodejs/tests/keys.test.ts

+18
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,21 @@ describe('keys', () => {
7777
})
7878
})
7979
})
80+
81+
test('p384', () => {
82+
const key = Key.generate(KeyAlgs.EcSecp384r1)
83+
expect(key.algorithm).toStrictEqual(KeyAlgs.EcSecp384r1)
84+
const message = Uint8Array.from(Buffer.from('test message'))
85+
const signature = key.signMessage({ message })
86+
expect(key.verifySignature({ message, signature })).toStrictEqual(true)
87+
88+
expect(key.jwkPublic).toMatchObject({
89+
kty: 'EC',
90+
crv: 'P-384',
91+
})
92+
93+
expect(key.jwkSecret).toMatchObject({
94+
kty: 'EC',
95+
crv: 'P-384',
96+
})
97+
})

wrappers/javascript/aries-askar-nodejs/tests/store.test.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ describe('Store and Session', () => {
226226
found.forEach((entry) => entry.key.handle.free())
227227
})
228228

229-
test('profile', async () => {
229+
test('Profile', async () => {
230230
const session = await store.openSession()
231231
await session.insert(firstEntry)
232232
await session.close()
@@ -258,6 +258,11 @@ describe('Store and Session', () => {
258258
await expect(session4.count(firstEntry)).resolves.toStrictEqual(1)
259259
await session4.close()
260260

261+
await store.setDefaultProfile(profile)
262+
await expect(store.getDefaultProfile()).resolves.toStrictEqual(profile)
263+
264+
await expect(store.listProfiles()).resolves.toContain(profile)
265+
261266
await store.removeProfile(profile)
262267

263268
// Profile key is cached
@@ -274,4 +279,15 @@ describe('Store and Session', () => {
274279
await expect(session7.count(firstEntry)).resolves.toStrictEqual(0)
275280
await session7.close()
276281
})
282+
283+
test('Copy', async () => {
284+
const key = getRawKey()
285+
286+
await store.copyTo({
287+
uri: 'sqlite://:memory:',
288+
keyMethod: new StoreKeyMethod(KdfMethod.Raw),
289+
passKey: key,
290+
recreate: true,
291+
})
292+
})
277293
})

wrappers/javascript/aries-askar-react-native/cpp/HostObject.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ FunctionMap AriesAskarTurboModuleHostObject::functionMapping(jsi::Runtime &rt) {
1414
fMap.insert(
1515
std::make_tuple("setDefaultLogger", &ariesAskar::setDefaultLogger));
1616

17+
fMap.insert(std::make_tuple("storeCopyTo", &ariesAskar::storeCopyTo));
1718
fMap.insert(std::make_tuple("storeOpen", &ariesAskar::storeOpen));
1819
fMap.insert(
1920
std::make_tuple("storeGenerateRawKey", &ariesAskar::storeGenerateRawKey));
@@ -26,11 +27,17 @@ FunctionMap AriesAskarTurboModuleHostObject::functionMapping(jsi::Runtime &rt) {
2627
std::make_tuple("storeGenerateRawKey", &ariesAskar::storeGenerateRawKey));
2728
fMap.insert(
2829
std::make_tuple("storeGetProfileName", &ariesAskar::storeGetProfileName));
30+
fMap.insert(
31+
std::make_tuple("storeGetDefaultProfile",
32+
&ariesAskar::storeGetDefaultProfile));
2933
fMap.insert(std::make_tuple("storeProvision", &ariesAskar::storeProvision));
3034
fMap.insert(std::make_tuple("storeRekey", &ariesAskar::storeRekey));
3135
fMap.insert(std::make_tuple("storeRemove", &ariesAskar::storeRemove));
3236
fMap.insert(
3337
std::make_tuple("storeRemoveProfile", &ariesAskar::storeRemoveProfile));
38+
fMap.insert(
39+
std::make_tuple("storeSetDefaultProfile",
40+
&ariesAskar::storeSetDefaultProfile));
3441

3542
fMap.insert(std::make_tuple("sessionClose", &ariesAskar::sessionClose));
3643
fMap.insert(std::make_tuple("sessionCount", &ariesAskar::sessionCount));

0 commit comments

Comments
 (0)