Reputation: 1512
I've done Java and then Kotlin for years.. but for some reason i just cant wrap my head around these JS promise chains...
I have for last 2 hours tried to figure how would i return just the encrypted string from this AES example code or anything else from such chain.
import { NativeModules, Platform } from 'react-native'
const Encrypt = (message) => {
const Aes = NativeModules.Aes
const options = {
password: "Password",
salt: "salt",
cost: 5000,
length: 256
}
const GenerateKey = (password, salt, cost, length) => {
Aes.pbkdf2(
password || options.password,
salt || options.salt,
cost || options.cost,
length || options.length
)
}
const DecryptData = (cipher, iv, key) => Aes.decrypt(cipher, key, iv)
const EncryptData = (text, key) => {
return Aes.randomKey(16).then(iv => {
return Aes.encrypt(text, key, iv).then(cipher => ({
cipher,
iv
}))
})
}
const example = () => {
generateKey('asd', 'salt', 2000, 256)
.then( key => {
console.log('Key:', key)
encryptData(message, key)
.then(({ cipher, iv }) => {
console.log('Encrypted:', cipher)
decryptData(cipher, iv, key)
.then(text => {
console.log('Decrypted:', text)
})
.catch(error => {
console.log(error)
})
Aes.hmac256(cipher, key).then(hash => {
console.log('HMAC', hash)
})
})
.catch(error => {
console.log(error)
})
})
}
}
export default Encrypt
All the console logs fire, if i take off the function declaration around example so the code should work.
Question 1: How would i return just the cipher from chain ?
Question 2: Can i somehow export just the EncryptData function, to be used alone?
Question 3: Does anyone have any resources, such as tutorial which made you understand this flow?
I have googled and read couple of tutorials but JS syntax seem to change every other day and none of the tutorials seem to be about this kind of chain..
Thanks
Upvotes: 1
Views: 105
Reputation: 1938
So from what I understand, your native component Aes has 5 functions: pbkdf2, decrypt, encrypt, randomKey and hmac256.
A more flexible and readable way to do what you want is using async await on each "promise" function.
So basically I would do this:
const Encrypt = (message) => {
const Aes = NativeModules.Aes
const options = {
password: "Password",
salt: "salt",
cost: 5000,
length: 256
}
const generateKey = (password, salt, cost, length) => {
return Aes.pbkdf2(
password || options.password,
salt || options.salt,
cost || options.cost,
length || options.length
)
}
const decryptData = (cipher, iv, key) => Aes.decrypt(cipher, key, iv)
const encryptData = async (text, key) => {
const iv = await Aes.randomKey(16);
const cipher = await Aes.encrypt(text, key, iv);
return { cipher, iv };
}
const example = async () => {
try {
const key = await generateKey('asd', 'salt', 2000, 256);
console.log('Key:', key);
const { cipher, iv } = await encryptData(message, key);
console.log('Encrypted:', cipher);
const text = await decryptData(cipher, iv, key);
console.log('Decrypted:', text);
const hash = await Aes.hmac256(cipher, key);
console.log('HMAC', hash);
} catch (err) {
console.log('Error:', err);
}
}
}
If what you need is a function to return the cipher you can either return the cipher in the example an use the asynchronous way, or you send a callback function.
Asynchronous way:
const EncryptData = async (message) => {
const Aes = NativeModules.Aes
const options = {
password: "Password",
salt: "salt",
cost: 5000,
length: 256
}
const generateKey = (password, salt, cost, length) => {
return Aes.pbkdf2(
password || options.password,
salt || options.salt,
cost || options.cost,
length || options.length
)
}
const decryptData = (cipher, iv, key) => Aes.decrypt(cipher, key, iv)
const encryptData = async (text, key) => {
const iv = await Aes.randomKey(16);
const cipher = await Aes.encrypt(text, key, iv);
return { cipher, iv };
}
const key = await generateKey('asd', 'salt', 2000, 256);
console.log('Key:', key);
const { cipher, iv } = await encryptData(message, key);
return cipher;
}
callback function
const EncryptData = async (message, onSuccess, onError) => {
const Aes = NativeModules.Aes
const options = {
password: "Password",
salt: "salt",
cost: 5000,
length: 256
}
const generateKey = (password, salt, cost, length) => {
return Aes.pbkdf2(
password || options.password,
salt || options.salt,
cost || options.cost,
length || options.length
)
}
const decryptData = (cipher, iv, key) => Aes.decrypt(cipher, key, iv)
try {
const encryptData = async (text, key) => {
const iv = await Aes.randomKey(16);
const cipher = await Aes.encrypt(text, key, iv);
return { cipher, iv };
}
const key = await generateKey('asd', 'salt', 2000, 256);
console.log('Key:', key);
const { cipher, iv } = await encryptData(message, key);
if (typeof onSuccess === 'function') onSuccess(cipher);
} catch (err) {
if (typeof onError === 'function') onError(err);
}
}
If you want to understand more about promises and async await, I suggest these 2 videos:
Upvotes: 2