added multiple publish encryption

This commit is contained in:
Phillip 2023-05-05 01:11:43 +03:00
parent 82bfcc3b28
commit 64d6510c4b
3 changed files with 65 additions and 84 deletions

View File

@ -645,7 +645,8 @@
"bchange42": "Items", "bchange42": "Items",
"bchange43": "Do you give this application permission to add to this list?", "bchange43": "Do you give this application permission to add to this list?",
"bchange44": "Do you give this application permission to delete from this list?", "bchange44": "Do you give this application permission to delete from this list?",
"bchange45": "Encrypt" "bchange45": "Encrypt",
"bchange46": "Do you give this application permission to save the following file:"
}, },
"datapage": { "datapage": {
"dchange1": "Data Management", "dchange1": "Data Management",

View File

@ -42,3 +42,6 @@ export const ENCRYPT_DATA = 'ENCRYPT_DATA'
// DECRYPT_DATA // DECRYPT_DATA
export const DECRYPT_DATA = 'DECRYPT_DATA' export const DECRYPT_DATA = 'DECRYPT_DATA'
// SAVE_FILE
export const SAVE_FILE = 'SAVE_FILE'

View File

@ -24,7 +24,7 @@ import { QORT_DECIMALS } from 'qortal-ui-crypto/api/constants';
import nacl from '../../../../../qortal-ui-crypto/api/deps/nacl-fast.js' import nacl from '../../../../../qortal-ui-crypto/api/deps/nacl-fast.js'
import ed2curve from '../../../../../qortal-ui-crypto/api/deps/ed2curve.js' import ed2curve from '../../../../../qortal-ui-crypto/api/deps/ed2curve.js'
import { mimeToExtensionMap } from '../../components/qdn-action-constants'; import { mimeToExtensionMap } from '../../components/qdn-action-constants';
import { encryptData } from '../../components/qdn-action-encryption'; import { base64ToUint8Array, encryptData, uint8ArrayToBase64 } from '../../components/qdn-action-encryption';
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }); const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
class WebBrowser extends LitElement { class WebBrowser extends LitElement {
@ -561,79 +561,9 @@ class WebBrowser extends LitElement {
break; break;
} }
} }
case actions.ENCRYPT_DATA: {
const requiredFields = ['Uint8ArrayData', 'destinationPublicKey'];
const missingFields = [];
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`
let data = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
const { Uint8ArrayData, destinationPublicKey } = data
const uint8Array = new Uint8Array(Object.values(Uint8ArrayData));
if (!(uint8Array instanceof Uint8Array)) {
data['error'] = "The Uint8ArrayData you've submitted is invalid";
response = JSON.stringify(data);
break
}
try {
const privateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey
if (!privateKey) {
data['error'] = "Unable to retrieve keys"
response = JSON.stringify(data);
break
}
const publicKeyUnit8Array = window.parent.Base58.decode(destinationPublicKey)
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
const convertedPublicKey = ed2curve.convertPublicKey(publicKeyUnit8Array)
const sharedSecret = new Uint8Array(32)
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey)
const chatEncryptionSeed = new window.parent.Sha256().process(sharedSecret).finish().result
const nonce = new Uint8Array(24);
window.crypto.getRandomValues(nonce);
const encryptedData = nacl.secretbox(uint8Array, nonce, chatEncryptionSeed)
const str = "qortalEncryptedData";
const strEncoder = new TextEncoder();
const strUint8Array = strEncoder.encode(str);
const combinedData = new Uint8Array(strUint8Array.length + nonce.length + encryptedData.length);
combinedData.set(strUint8Array);
combinedData.set(nonce, strUint8Array.length);
combinedData.set(encryptedData, strUint8Array.length + nonce.length);
let data = {};
data['encryptedData'] = combinedData
data['destinationPublicKey'] = destinationPublicKey
response = JSON.stringify(data);
break;
} catch (error) {
const data = {};
const errorMsg = error.message || "Error in encrypting data"
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
}
case actions.DECRYPT_DATA: { case actions.DECRYPT_DATA: {
const requiredFields = ['encryptedData', 'senderPublicKey']; const requiredFields = ['encryptedData', 'publicKey'];
const missingFields = []; const missingFields = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
@ -650,11 +580,11 @@ class WebBrowser extends LitElement {
response = JSON.stringify(data); response = JSON.stringify(data);
break break
} }
const { encryptedData, senderPublicKey } = data const { encryptedData, publicKey } = data
try { try {
const uint8Array = new Uint8Array(Object.values(encryptedData)); const uint8Array = base64ToUint8Array(encryptedData)
const combinedData = uint8Array const combinedData = uint8Array
const str = "qortalEncryptedData"; const str = "qortalEncryptedData";
const strEncoder = new TextEncoder(); const strEncoder = new TextEncoder();
@ -665,26 +595,27 @@ class WebBrowser extends LitElement {
const _encryptedData = combinedData.slice(strUint8Array.length + 24); const _encryptedData = combinedData.slice(strUint8Array.length + 24);
const privateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey const privateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey
const publicKey = window.parent.Base58.decode(senderPublicKey) const _publicKey = window.parent.Base58.decode(publicKey)
if (!privateKey || !publicKey) { if (!privateKey || !_publicKey) {
data['error'] = "Unable to retrieve keys" data['error'] = "Unable to retrieve keys"
response = JSON.stringify(data); response = JSON.stringify(data);
break break
} }
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey) const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
const convertedPublicKey = ed2curve.convertPublicKey(publicKey) const convertedPublicKey = ed2curve.convertPublicKey(_publicKey)
const sharedSecret = new Uint8Array(32); const sharedSecret = new Uint8Array(32);
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey) nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey)
const _chatEncryptionSeed = new window.parent.Sha256().process(sharedSecret).finish().result const _chatEncryptionSeed = new window.parent.Sha256().process(sharedSecret).finish().result
const _decryptedData = nacl.secretbox.open(_encryptedData, nonce, _chatEncryptionSeed) const _decryptedData = nacl.secretbox.open(_encryptedData, nonce, _chatEncryptionSeed)
let data = {}; const decryptedDataToBase64 = uint8ArrayToBase64(_decryptedData)
data['decryptedData'] = _decryptedData response = JSON.stringify(decryptedDataToBase64);
response = JSON.stringify(data);
break; break;
} catch (error) { } catch (error) {
console.log({ error })
const data = {}; const data = {};
const errorMsg = error.message || "Error in decrypting data" const errorMsg = error.message || "Error in decrypting data"
data['error'] = errorMsg; data['error'] = errorMsg;
@ -1059,6 +990,12 @@ class WebBrowser extends LitElement {
response = JSON.stringify(data); response = JSON.stringify(data);
break break
} }
if (data.encrypt && !data.recipientPublicKey) {
let data = {};
data['error'] = "Encrypting data requires the recipient's public key";
response = JSON.stringify(data);
break
}
const res2 = await showModalAndWait( const res2 = await showModalAndWait(
actions.PUBLISH_MULTIPLE_QDN_RESOURCES, actions.PUBLISH_MULTIPLE_QDN_RESOURCES,
{ {
@ -1091,7 +1028,7 @@ class WebBrowser extends LitElement {
const service = resource.service; const service = resource.service;
const name = resource.name; const name = resource.name;
let identifier = resource.identifier; let identifier = resource.identifier;
const data64 = resource.data64; let data64 = resource.data64;
const filename = resource.filename; const filename = resource.filename;
const title = resource.title; const title = resource.title;
const description = resource.description; const description = resource.description;
@ -1105,6 +1042,24 @@ class WebBrowser extends LitElement {
identifier = 'default'; identifier = 'default';
} }
if (data.encrypt) {
try {
const encryptDataResponse = encryptData({
data64, recipientPublicKey: data.recipientPublicKey
})
if (encryptDataResponse.encryptedData) {
data64 = encryptDataResponse.encryptedData
}
} catch (error) {
const errorMsg = error.message || 'Upload failed due to failed encryption'
throw new Error(errorMsg)
}
}
const worker = new WebWorker(); const worker = new WebWorker();
try { try {
@ -1422,8 +1377,9 @@ class WebBrowser extends LitElement {
// If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}` // If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}`
break; break;
} }
case 'DOWNLOAD': { case actions.SAVE_FILE: {
try { try {
const requiredFields = ['filename', 'blob']; const requiredFields = ['filename', 'blob'];
const missingFields = []; const missingFields = [];
@ -1442,9 +1398,24 @@ class WebBrowser extends LitElement {
break break
} }
const filename = data.filename const filename = data.filename
const blob = data.blob const blob = data.blob
const res = await showModalAndWait(
actions.SAVE_FILE,
{
filename
}
);
if (res.action === 'reject') {
response = '{"error": "User declined request"}';
break
}
const mimeType = blob.type || data.mimeType const mimeType = blob.type || data.mimeType
let backupExention = filename.split('.').pop() let backupExention = filename.split('.').pop()
if (backupExention) { if (backupExention) {
@ -2952,6 +2923,12 @@ async function showModalAndWait(type, data) {
<p class="modal-paragraph">${get("browserpage.bchange42")}: <span> ${data.items.join(', ')}</span></p> <p class="modal-paragraph">${get("browserpage.bchange42")}: <span> ${data.items.join(', ')}</span></p>
</div> </div>
` : ''} ` : ''}
${type === actions.SAVE_FILE ? `
<div class="modal-subcontainer">
<p class="modal-paragraph">${get("browserpage.bchange46")}: <span> ${data.filename}</span></p>
</div>
` : ''}
${type === actions.DELETE_LIST_ITEM ? ` ${type === actions.DELETE_LIST_ITEM ? `
<div class="modal-subcontainer"> <div class="modal-subcontainer">
<p class="modal-paragraph">${get("browserpage.bchange44")}</p> <p class="modal-paragraph">${get("browserpage.bchange44")}</p>