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' && (
Account Settings
diff --git a/net/web/src/session/account/profile/Profile.styled.js b/net/web/src/session/account/profile/Profile.styled.js index f5da50ea..1409ccd2 100644 --- a/net/web/src/session/account/profile/Profile.styled.js +++ b/net/web/src/session/account/profile/Profile.styled.js @@ -173,8 +173,6 @@ export const ProfileWrapper = styled.div` flex-direction: column; align-items: center; justify-content: center; - border-top: 1px solid ${Colors.divider}; - border-radius: 4px; padding: 8px; width: 75%; } diff --git a/net/web/src/session/account/profile/accountAccess/AccountAccess.jsx b/net/web/src/session/account/profile/accountAccess/AccountAccess.jsx index e5e8dae5..a2dce1c6 100644 --- a/net/web/src/session/account/profile/accountAccess/AccountAccess.jsx +++ b/net/web/src/session/account/profile/accountAccess/AccountAccess.jsx @@ -1,11 +1,11 @@ import { AccountAccessWrapper, SealModal, EditFooter } from './AccountAccess.styled'; import { useAccountAccess } from './useAccountAccess.hook'; -import { AccountLogin } from './accountLogin/AccountLogin'; -import { Button, Modal, Switch, Input } from 'antd'; -import { SettingOutlined, LockOutlined, ExclamationCircleOutlined } from '@ant-design/icons'; +import { Button, Modal, Switch, Form, Input } from 'antd'; +import { SettingOutlined, UserOutlined, LockOutlined, ExclamationCircleOutlined } from '@ant-design/icons'; export function AccountAccess() { + const [ modal, modalContext ] = Modal.useModal(); const { state, actions } = useAccountAccess(); const saveSeal = async () => { @@ -15,7 +15,7 @@ export function AccountAccess() { } catch (err) { console.log(err); - Modal.error({ + modal.error({ title: 'Failed to Set Sealing Key', comment: 'Please try again.', }); @@ -28,7 +28,7 @@ export function AccountAccess() { } catch (err) { console.log(err); - Modal.error({ + modal.error({ title: 'Update Registry Failed', content: 'Please try again.', }); @@ -42,7 +42,7 @@ export function AccountAccess() { } catch (err) { console.log(err); - Modal.error({ + modal.error({ title: 'Failed to Save', comment: 'Please try again.', }); @@ -51,7 +51,7 @@ export function AccountAccess() { const editLoginFooter = ( -
+
@@ -59,7 +59,7 @@ export function AccountAccess() { const editSealFooter = ( -
+
{ state.sealMode === 'enabled' && ( @@ -75,50 +75,51 @@ export function AccountAccess() { return ( -
+ { modalContext } +
saveSearchable(enable)} /> -
Visible in Registry   
+
Visible in Registry   
-