Skip to main content

What if my user lost their private key ?

One day, one of your user will lose their private key. In order for them to have access back to their data, you will have to put a few actions in place.

Pre-requisites

In this tutorial, we will only focus on the additional steps related to a lost key pair : We won't cover the User authentication and data sharing services.

Therefore, we assume that you're already familiar with :

At this stage, you should :

  • Have a patient user
  • Have a practitioner user
  • Have some data created by your patient and shared with your practitioner user

Login and create a new RSA Keypair

You can't find back Daenaerys's private key. Depending where you saved her private key, it could be because:

  • she lost her computer
  • she started the app on another browser
  • she reset her computer
  • she cleared her cache
  • ...

Anyway, if you want her to continue using your app, you need to create her a new RSA Keypair. For this, start a new authentication process as usual:

const loginAuthResult = await anonymousMedTechApi.authenticationApi.completeAuthentication(
loginProcess,
newValidationCode,
)

The completeAuthentication will create autonomously a new key pair for the User if an existing one is not found.
At this stage, Daenaerys will be able to create new data using her new RSA keypair :

const newlyCreatedObservation = await loginAuthResult.api.observationApi.createOrModifyFor(
foundUser.patientId,
new Observation({
tags: new Set([new CodingReference({ type: 'IC-TEST', code: 'TEST' })]),
localContent: mapOf({ en: new LocalComponent({ stringValue: 'Hello world' }) }),
openingDate: 20220929083400,
}),
)
newlyCreatedDataSample
{
"id": "9fbfe82a-dc0b-497b-8afc-84c32b75365f",
"identifiers": [],
"batchId": "5fa49c65-cdb1-4107-9516-7afb6424e8e7",
"healthcareElementIds": [],
"index": 0,
"valueDate": 20231115142959,
"openingDate": 20220929083400,
"created": 1700058599346,
"modified": 1700058599346,
"author": "*",
"performer": "*",
"localContent": {},
"qualifiedLinks": {},
"codes": {},
"tags": {},
"systemMetaData": {
"secretForeignKeys": [
"7905c201-1c48-478e-b82c-8ab2bf68e61a"
],
"cryptedForeignKeys": {},
"delegations": {},
"encryptionKeys": {},
"securityMetadata": {
"secureDelegations": {},
"keysEquivalences": {}
},
"encryptedSelf": "X83hHnFCXmDumz563PH/rFcDeErabBIbks56RYDGS/uYxLh7wg59m+3VRHeSgD0Bv7wskCG8Ex5n44hWOan2jHoC64ReO16RB7uLvsx2v9Q=",
"tags": {}
},
"notes": []
}

However, she still won't be able to access the data she created with her previous key. To get access back to it, Daenaerys will need the help of people with whom she shared those data.

Get access back to previous data

The previous key of Daenaerys is lost, meaning she shouldn't be able to access her data anymore. However, thanks to iCure advanced cryptography, she can still hope to find it back, by asking the data owners with whom she shared her data to give her access back.

danger

Of course, if Daenaerys didn't share her data with anyone, it is definitely lost. She won't be able to access it again.

When Daenarys created a new RSA Keypair, the MedTech SDK sent a notification to all data owners she shared data with in the past, to warn them she has a new keypair and needs them to re-share her data using the new keypair and not only the previous keypair anymore.

Once the data owners will treat this notification and decide or not to give access back to Daenaerys, she will be able to see her previous data again.

For the next steps of this tutorial, we'll consider that Daenaerys shared some of her medical data with her doctor, Jorah Mormont.

When Jorah will start your app, he will have to retrieve all recent notifications he needs to treat. The ones that are interesting us here are the notifications related to updated keypairs :

const hcpNotifications = await hcpApi.notificationApi
.getPendingAfter(startTimestamp)
.then((notifs) => notifs.filter((notif) => notif.type === NotificationTypeEnum.KeyPairUpdate))
hcpNotifications
[
{
"id": "93695877-5aed-489f-8752-bb12701fa494",
"rev": "1-c6ed0e6b3a47ca2ec0b47b307a2efdfc",
"status": "pending",
"created": 1700058599261,
"identifiers": [],
"modified": 1700058599261,
"author": "*",
"responsible": "*",
"properties": {},
"type": "KEY_PAIR_UPDATE",
"systemMetaData": {
"secretForeignKeys": [],
"cryptedForeignKeys": {},
"delegations": {},
"encryptionKeys": {},
"securityMetadata": {
"secureDelegations": {},
"keysEquivalences": {}
},
"encryptedSelf": "ujjYdFpdUBZ6o0LdGwLGRvXGKpBtfSsQ8S18pfBKYeFRfFljjeqlMnGmB0cxPKH8EuXaR48DgAXYm9B4eIR4mUAh0tyIa1ApORojqw2mIHhf1wIqSVYGkhNLFS4I5kd9z/ekQAtZvID6etagcECNf5UCu2cFa1pi0hrs10hgpgPrxzfQR9Z6v+ZlMQW7MmechtGKLZLLUhsl6kf8FA1Ctgkv5ob9X70xBZpGLKhRoBCbVYfA/uvt4rGgCClvMY6e/riLQydnyOVBg0AwQmu4FHvnvxbT9YnO1urskpUTXJwYQgWJBZ1x9VHA/E71hzeY//SRQoX0KXy8W3kRTa5IX9CsbNs89YpWo8+CZfYSgJljwWR32k6Egva7P9MpmtfoaCYav8LCYD5PvNMsonE6L0ZO2qESYXuc+I/6Mf8EMVBD6UV6E4wqN5Ku2B1cKOB6yMgorpfLB4dpDECAUtAXV7HEf1qUPSwtJMWqKkLDQIuUy1q5SQbSnX0rdPNwHbhZS9Y3M2krVxf6JR5nUkbyVQxL0k55LxfuTIZqB/Hg48/wVgZd7AcylXxrLJujLbDCsXPE23FNFuHFvtzK3cjxVUQp0FFctaCDKtWzov7+qt+88hKr8hmz64V46M68FwOVGNu+2LeoANLLuXub5vjUsCpUhSOryjmiwG28NG4Ec+BA/BBT7g9pV0nCau0nFyr6hjJycq/q83vLHSvjdmrZT8iUO/fcOfBD3EV4yPigx/ipjBwKy14ESAlQndSmKjAXJIMP6BjvNzJIBJ8wcMn1zSeoHkU77iNC6ndKwM2AlZZqzGhHWIIyO2SO+HYl6CaPDP97FVtTtveUmiCTIE3XCOfMqXDWin2x4vz1evIrsCNkT2zaiDfcCmgOAen9Aj0/Tc0MBIe2xTTIcJ2XJV3dbNb0bw4ynT9YFjRbyVt0PK4jWYiepSXLgenWrkVY7N1pp43FbE8FUincqxHWlFouyl76eU/zznQmvoNUDBQmTv9zur75PFYKpOXFevlxwBfB4pU/8jJ1fWI9cXcgY02jY94E058r9FGOGk0QsDPSZR27gQb+AjhLyalO2dBY/UpwkVCu4vesyGHuH1T1LnEAbAk8pOaHk524GOuxgpRVbPGfGOVmhucP9CFzrldhdtIUFFVHTQhqTWvbp+5j89LwLA==",
"tags": {}
}
}
]

Once Jorah has the list of notifications, he will treat them one by one, deciding to give access back to the provided user or not.

Give access back to another data owner

danger

Before giving access back to a user, the data owner must ensure that the user is really who they meant to be.

Let's say Jorah decides to give Daenaerys access back to her previous data using her new keypair :

const daenaerysPatientId = Array.from(daenaerysNotification.properties ?? []).find(
(prop) => prop.id == 'dataOwnerConcernedId',
)
const daenaerysPatientPubKey = Array.from(daenaerysNotification.properties ?? []).find(
(prop) => prop.id == 'dataOwnerConcernedPubKey',
)

await hcpApi.dataOwnerApi.giveAccessBackTo(
daenaerysPatientId.typedValue.stringValue,
daenaerysPatientPubKey.typedValue.stringValue,
)
daenaerysPatientId
{
"id": "dataOwnerConcernedId",
"type": {
"type": "STRING"
},
"typedValue": {
"type": "STRING",
"stringValue": "04af2f55-a076-40d1-af78-96bbdda10d61"
}
}
daenaerysPatientPubKey
{
"id": "dataOwnerConcernedPubKey",
"type": {
"type": "STRING"
},
"typedValue": {
"type": "STRING",
"stringValue": "30820122300d06092a864886f70d01010105000382010f003082010a0282010100a0f7b606876c219650204ee85b62f41467637a018c7a6a3430beaeea2cf7c81b3dc9f4542dc49bda2f6361f2d74e4e0ed44358668056ffc3479eca5e1988aa599855bdc1dc527657ad13269eccd4d06c90b565c6bdb1cc64a21225ddaacd9bdb100aaa8e5faf384f2193e5db3a6e28aac6c3d64cf303cdfea343293f8327ed56ae2f295830a5976172d6b44f8e71f8d32c1286140e699f01a1a097c8a12224bd86d483bdd67659a99f5fa4050b1ebf77a3a601847755e757d82ea4d74c1efcab9ed3ef47b8653f7e89aaf9a73fcdc925cf61cd7e4d14028538173de91b57117882a133d84df2d800acac969b3faef401b6130512094b66150e68d5c0a7b06b4b0203010001"
}
}

After restarting her app, Daenaerys will be able to access her previous data back.

tip

Once a notification is treated, do not forget to update its status. (See more in How to manage notifications)

What if the user wants to authenticate on another device but didn't lose their previous key ?

When a new RSA keypair is generated for Daenaerys, a notification is sent to all data owners she shared data with, but not only: she receives a notification as well.

Therefore, the procedure stays the same, except that instead of waiting all data owners to give access back to her data, Daenaerys can get all her pending notifications, and give access back to all her data using her "previous" key.