updateEncKey method
Update/change encryption key Need to re-encrypt all the encrypted files using the new key
Implementation
Future<String> updateEncKey(
String plainPrevEncKey, String plainNewEncKey) async {
/// Verify old encryption key before moving forward
if (await verifyEncKey(plainPrevEncKey)) {
/// Create hash values for old and new encrypted keys
String newKeyHash = sha224
.convert(utf8.encode(plainNewEncKey))
.toString()
.substring(0, 32);
String newEncKey = sha256
.convert(utf8.encode(plainNewEncKey))
.toString()
.substring(0, 32);
String prevEncKey = sha256
.convert(utf8.encode(plainPrevEncKey))
.toString()
.substring(0, 32);
/// Get the previous key and the list of locations of files that are encrypted
var keyInfo = await fetchFile(encKeyFileLoc);
EncProfile keyFile = EncProfile(keyInfo.toString());
String prevKeyHash = keyFile.getEncKeyHash();
String encFileHash = keyFile.getEncFileHash();
String encFileIv = keyFile.getEncIvVal();
String encFilePlaintext = decryptVal(prevEncKey, encFileHash, encFileIv);
List encFileList = jsonDecode(encFilePlaintext);
/// Loop over each encrypted file and re-encrypt the content using
/// new encryption key
for (var i = 0; i < encFileList.length; i++) {
String encFilePath = encFileList[i];
var fileInfo = await fetchFile(encFilePath);
EncProfile encFile = EncProfile(fileInfo.toString());
String encFileCont = encFile.getEncFileCont();
String encFileIv = encFile.getEncIvVal();
String plainFileCont = decryptVal(prevEncKey, encFileCont, encFileIv);
List newEncFileRes = encryptVal(newEncKey, plainFileCont);
String newEncFileCont = newEncFileRes[0];
String newEncIv = newEncFileRes[1];
String encFileUrl = webId.replaceAll('profile/card#me', encFilePath);
// Update encrypted value
String dPopToken =
genDpopToken(encFileUrl, rsaKeyPair, publicKeyJwk, 'PATCH');
String fileUpdateQuery = genSparqlQuery(
'UPDATE', '', encValPred, newEncFileCont,
prevObject: encFileCont);
String fileContupdate =
await runQuery(encFileUrl, dPopToken, fileUpdateQuery);
// Update IV value
String dPopTokenIv =
genDpopToken(encFileUrl, rsaKeyPair, publicKeyJwk, 'PATCH');
String fileUpdateQueryIv = genSparqlQuery(
'UPDATE', '', ivValPred, newEncIv,
prevObject: encFileIv);
String fileContupdateIv =
await runQuery(encFileUrl, dPopTokenIv, fileUpdateQueryIv);
if (fileContupdate == 'ok' && fileContupdateIv == 'ok') {
continue;
} else {
throw Exception('Failed to update encrypted file $encFilePath.');
}
}
/// Update the encryption key hash with new key
String encKeyUrl = webId.replaceAll('profile/card#me', encKeyFileLoc);
String dPopToken =
genDpopToken(encKeyUrl, rsaKeyPair, publicKeyJwk, 'PATCH');
String updateQuery = genSparqlQuery('UPDATE', '', encKeyPred, newKeyHash,
prevObject: prevKeyHash);
String updateResponse = await runQuery(encKeyUrl, dPopToken, updateQuery);
if (updateResponse == 'ok') {
/// Update the list of locations of the encrypted files
List encFileNewRes = encryptVal(newEncKey, encFilePlaintext);
String encFileHashNew = encFileNewRes[0];
String encFileIvNew = encFileNewRes[1];
// Update encrypted value
String dPopToken =
genDpopToken(encKeyUrl, rsaKeyPair, publicKeyJwk, 'PATCH');
String updateQuery = genSparqlQuery(
'UPDATE', '', encFilePred, encFileHashNew,
prevObject: encFileHash);
String updateResponse =
await runQuery(encKeyUrl, dPopToken, updateQuery);
// Update IV value
String dPopTokenIv =
genDpopToken(encKeyUrl, rsaKeyPair, publicKeyJwk, 'PATCH');
String updateQueryIv = genSparqlQuery(
'UPDATE', '', ivValPred, encFileIvNew,
prevObject: encFileIv);
String updateResponseIv =
await runQuery(encKeyUrl, dPopTokenIv, updateQueryIv);
if (updateResponse == 'ok' && updateResponseIv == 'ok') {
removeEncKeyStorage();
/// Remove previous key from local storage
setEncKeyStorage(newEncKey);
/// Set new key to local storage
return updateResponse;
} else {
throw Exception('Failed to update encrypted file locations.');
}
} else {
throw Exception('Failed to update new encryption key.');
}
} else {
throw Exception('Failed to verify the previous encryption key.');
}
}