Reputation: 23
I have a promise like object in my own function that decrypts the given message using web crypto api. Problem is, in my decrypt function, I want to try couple of different values as an input and run this promise like object multiple times in a for loop and at the end function should return the object which ever of these promises resolve successfully.
public decryptMessage(latitude: [string, number], longitude: [string, number], ciphertext: string) {
//get salt
const salt = localStorage.getItem("salt")
const retrievedSaltArray = JSON.parse(salt)
const saltBytes = new Uint8Array(retrievedSaltArray)
//get iv
const iv = localStorage.getItem("iv")
const retrievedIvArray = JSON.parse(iv)
const ivBytes = new Uint8Array(retrievedIvArray)
//get tolerance distance
let toleranceDistance = parseInt(JSON.parse(localStorage.getItem("toleranceDistance")))
//get original keyHash
let originalHash = localStorage.getItem("keyhash")
//create location inputs(locations with adjacent quadrants)
let location = new Location(latitude, longitude)
let locationInputs = location.prepareReceiverLocationInputs()
let encryptionTool = new EncryptionHelper(saltBytes, ivBytes)
for (let i = 0; i <= locationInputs.length - 1; i++) {
let plaintText = encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash)
plaintText.then(function (plaintTextResult) {
return plaintTextResult
})
}
}
So here what I try to do is, this promise Like ojbect which is encryptionTool.decryp() should run in the for loop and then whichever of these promises resolves should be the return value of decryptMessage method. However, this encryptionTool.decrypt method uses webcrypto api so it doesnt have reject or catch methods because it is an promise like method.
Upvotes: 0
Views: 2066
Reputation: 30919
Since a promise represents a value that will be available in the future, you can't test "now" (synchronously) which one succeeds. Instead, you have to use the available functions for manipulating and combining promises. I'm assuming encryptionTool.decrypt
returns a PromiseLike<string>
; if it's a PromiseLike<T>
for some other T
, just replace string
with that T
in the following.
First, you can use Promise.resolve
to convert the PromiseLike<string>
to a Promise<string>
. Then, you want to use Promise.all
to take an array of promises and give you back a promise of the array of results, so you can write a then
callback to scan the array and take the result you want. A potential problem is that Promise.all
rejects if any of the provided promises rejects, in which case you don't get to see the other results. So before you use Promise.all
, you need to use catch
to map the rejection to a sentinel value, such as null
. The complete code would look something like this (I haven't tested it, so there may be mistakes):
// Assuming that encryptionTool.decrypt returns a PromiseLike<string>,
// promises will be a Promise<string | null>[].
let promises = [];
for (let i = 0; i <= locationInputs.length - 1; i++) {
promises.push(
Promise.resolve(encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash))
.catch((error) => null));
}
return Promise.all(promises).then((results) => {
// results is a (string | null)[].
// Look through it, find the non-null result and return it.
});
Note that the final then
call generates a promise for the final result, and you return this promise synchronously to the caller of decryptMessage
.
An alternative approach would be to make decryptMessage
an async function so you can program in a more familiar style. Replace public decryptMessage
with public async decryptMessage
and then use code like this:
for (let i = 0; i <= locationInputs.length - 1; i++) {
try {
return await encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash);
} catch (e) {
// Discard the exception and proceed to the next decryption attempt.
}
}
// TODO: Decide what to return here if all decryptions fail.
Note that this way, each decryption does not start until after the previous one fails, so the process may take longer to complete depending on how the web crypto API is implemented.
Upvotes: 1