diff --git a/net/web/src/context/sealUtil.js b/net/web/src/context/sealUtil.js index d2e2c081..a9624cfb 100644 --- a/net/web/src/context/sealUtil.js +++ b/net/web/src/context/sealUtil.js @@ -79,3 +79,107 @@ export function decryptTopicSubject(subject, contentKey) { return JSON.parse(dec.toString(CryptoJS.enc.Utf8)); } +function convertPem(pem) { + var lines = pem.split('\n'); + var encoded = ''; + for(var i = 0;i < lines.length;i++){ + if (lines[i].trim().length > 0 && + lines[i].indexOf('-BEGIN RSA PRIVATE KEY-') < 0 && + lines[i].indexOf('-BEGIN RSA PUBLIC KEY-') < 0 && + lines[i].indexOf('-BEGIN PUBLIC KEY-') < 0 && + lines[i].indexOf('-END PUBLIC KEY-') < 0 && + lines[i].indexOf('-END RSA PRIVATE KEY-') < 0 && + lines[i].indexOf('-END RSA PUBLIC KEY-') < 0) { + encoded += lines[i].trim(); + } + } + return encoded +}; + +export async function generateSeal(password) { + + // generate key to encrypt private key + const salt = CryptoJS.lib.WordArray.random(128 / 8); + const aes = CryptoJS.PBKDF2(password, salt, { + keySize: 256 / 32, + iterations: 1024, + }); + + // generate rsa key for sealing channel, delay for activity indicators + await new Promise(r => setTimeout(r, 1000)); + const crypto = new JSEncrypt({ default_key_size: 2048 }); + crypto.getKey(); + + // encrypt private key + const iv = CryptoJS.lib.WordArray.random(128 / 8); + const privateKey = convertPem(crypto.getPrivateKey()); + const enc = CryptoJS.AES.encrypt(privateKey, aes, { iv: iv }); + const publicKey = convertPem(crypto.getPublicKey()); + + // update account + const seal = { + passwordSalt: salt.toString(), + privateKeyIv: iv.toString(), + privateKeyEncrypted: enc.ciphertext.toString(CryptoJS.enc.Base64), + publicKey: publicKey, + } + const sealKey = { + public: publicKey, + private: privateKey, + } + + return { seal, sealKey }; +} + +export function unlockSeal(seal, password) { + + // generate key to encrypt private key + const salt = CryptoJS.enc.Hex.parse(seal.passwordSalt); + const aes = CryptoJS.PBKDF2(password, salt, { + keySize: 256 / 32, + iterations: 1024, + }); + + // decrypt private key + const iv = CryptoJS.enc.Hex.parse(seal.privateKeyIv); + const enc = CryptoJS.enc.Base64.parse(seal.privateKeyEncrypted) + + let cipherParams = CryptoJS.lib.CipherParams.create({ + ciphertext: enc, + iv: iv + }); + const dec = CryptoJS.AES.decrypt(cipherParams, aes, { iv: iv }); + const privateKey = dec.toString(CryptoJS.enc.Utf8) + + // store ke + const sealKey = { + public: seal.publicKey, + private: privateKey, + } + + return sealKey; +} + +export function updateSeal(seal, sealKey, password) { + + // generate key to encrypt private key + const salt = CryptoJS.lib.WordArray.random(128 / 8); + const aes = CryptoJS.PBKDF2(password, salt, { + keySize: 256 / 32, + iterations: 1024, + }); + + // encrypt private key + const iv = CryptoJS.lib.WordArray.random(128 / 8); + const enc = CryptoJS.AES.encrypt(sealKey.private, aes, { iv: iv }); + + // update account + const updated = { + passwordSalt: salt.toString(), + privateKeyIv: iv.toString(), + privateKeyEncrypted: enc.ciphertext.toString(CryptoJS.enc.Base64), + publicKey: seal.publicKey, + } + + return { seal: updated, sealKey }; +} diff --git a/net/web/src/context/useProfileContext.hook.js b/net/web/src/context/useProfileContext.hook.js index a9ed4ea1..2bea4585 100644 --- a/net/web/src/context/useProfileContext.hook.js +++ b/net/web/src/context/useProfileContext.hook.js @@ -28,7 +28,7 @@ export function useProfileContext() { const token = access.current; const revision = curRevision.current; const identity = await getProfile(access.current); - const imageUrl = identity.image ? getProfileImageUrl(token, revision) : null; + const imageUrl = identity.image ? getProfileImageUrl(token, identity.revision) : null; setRevision.current = revision; updateState({ offsync: false, identity, imageUrl }); } diff --git a/net/web/src/session/account/profile/Profile.jsx b/net/web/src/session/account/profile/Profile.jsx index f91d1511..5a857852 100644 --- a/net/web/src/session/account/profile/Profile.jsx +++ b/net/web/src/session/account/profile/Profile.jsx @@ -140,7 +140,7 @@ export function Profile({ closeProfile }) { - { state.init && state.display !== 'xlarge' && ( + { state.display !== 'xlarge' && (