I updated my code to use getAppPubEncKey
instead of getAppPubSignKey
.
This is working nicely.
I ran this code, then reloaded page and reauthenticated my application, retrieved the same private MD, and was able to successfully decrypt using the app’s public encryption key.
let appInfo = {
id: 'net.maidsafe.api_playground.webclient.10',
name: 'SAFE web API playground',
vendor: 'MaidSafe Ltd.',
scope: null
};
let encryptedEntries = {};
function decryptQueue(mdHandle, i) {
let entries = Object.keys(encryptedEntries);
if ( i === entries.length ) {
console.log('Decrypted entry: ', encryptedEntries);
return;
}
window.safeMutableData.decrypt(mdHandle, encryptedEntries[entries[i]].buf).then(decryptedValue => {
encryptedEntries[entries[i]] = String.fromCharCode.apply(null, new Uint8Array(decryptedValue));
decryptQueue(mdHandle, i + 1);
})
}
window.safeApp.initialise(appInfo).then(appHandle => window.safeApp.authorise(appHandle, {
_public: ['Read', 'Insert', 'Update', 'Delete'],
_publicNames: ['Read', 'Insert', 'Update', 'Delete']
}, { own_container: true })
.then(authUri => window.safeApp.connectAuthorised(appHandle, authUri)))
.then(appHandle => window.safeCrypto.sha3Hash(appHandle, 'explicitly_named_md')
.then(hashedString => ({hashedString, appHandle})))
.then(({hashedString, appHandle}) => window.safeCrypto.getAppPubEncKey(appHandle)
.then(encKeyHandle => window.safeCryptoPubEncKey.getRaw(encKeyHandle).then(rawPubEncKey => ({rawPubEncKey, hashedString, appHandle}))))
.then(({rawPubEncKey, hashedString, appHandle}) => window.safeCrypto.generateNonce(appHandle).then(nonce => ({rawPubEncKey, hashedString, appHandle, nonce})))
.then(({rawPubEncKey, hashedString, appHandle, nonce}) => window.safeMutableData.newPrivate(appHandle, hashedString, 15001, rawPubEncKey.buffer, nonce.buffer)
.then(mdHandle => window.safeMutableData.encryptKey(mdHandle, 'key1').then(encryptedKey => ({encryptedKey}))
.then(({encryptedKey}) => window.safeMutableData.encryptValue(mdHandle, 'encrypted value').then(encryptedValue => ({encryptedKey, encryptedValue}))
.then(({encryptedKey, encryptedValue}) => window.safeMutableData.quickSetup(mdHandle)
.then(() => window.safeMutableData.newMutation(appHandle)
.then(mutationHandle => window.safeMutableDataMutation.insert(mutationHandle, encryptedKey, encryptedValue)
.then(() => window.safeMutableData.applyEntriesMutation(mdHandle, mutationHandle).then(() => ({mdHandle, appHandle, hashedString})))
)
)
)
)
)
)
.then(({mdHandle, appHandle, hashedString}) => window.safeMutableData.getEntries(mdHandle)
.then(entriesHandle => window.safeMutableDataEntries.forEach(entriesHandle, (k, v) => {
let key = String.fromCharCode.apply(null, k);
let value = String.fromCharCode.apply(null, new Uint8Array(v.buf));
console.log('Key: ', key,',', 'Value: ', value);
}).then(() => ({appHandle, hashedString}))
))
.then(({appHandle, hashedString}) => window.safeCrypto.getAppPubEncKey(appHandle)
.then(encKeyHandle => window.safeCryptoPubEncKey.getRaw(encKeyHandle).then(rawPubEncKey => ({rawPubEncKey, hashedString, appHandle})))
.then(({rawPubEncKey, hashedString, appHandle}) => window.safeCrypto.generateNonce(appHandle).then(nonce => ({rawPubEncKey, hashedString, appHandle, nonce})))
.then(({rawPubEncKey, hashedString, appHandle, nonce}) => window.safeMutableData.newPrivate(appHandle, hashedString, 15001, rawPubEncKey.buffer, nonce.buffer))
.then(mdHandle => window.safeMutableData.getEntries(mdHandle)
.then(entriesHandle => window.safeMutableDataEntries.forEach(entriesHandle, (k, v) => {
Object.defineProperty(encryptedEntries, k, {value: v, writable: true, enumerable: true, configurable: true});
})).then(() => {
console.log(mdHandle);
decryptQueue(mdHandle,0);
})
)
)
Nonce should always be unique for security purposes. I’m just learning about how this works. Thanks to @dirvine for passing along this link for education: https://www.lvh.io/posts/nonce-misuse-resistance-101.html
The critical security property of a nonce is that it’s never repeated under the same key. You can remember this by the mnemonic that a nonce is a “number used once”. If you were to repeat the nonce, the keystream would also repeat. That means that an attacker can take the two ciphertexts and XOR them to compute the XOR of the plaintexts.