mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
support seal key handling in webapp
This commit is contained in:
parent
538094bf7f
commit
009f5c3a96
@ -3699,9 +3699,12 @@ components:
|
||||
- privateKeyEncrypted
|
||||
- publicKey
|
||||
properties:
|
||||
salt:
|
||||
passwordSalt:
|
||||
type: string
|
||||
format: base64 encoded data
|
||||
format: hex encoded data
|
||||
privateKeyIv:
|
||||
type: string
|
||||
format: hex encoded data
|
||||
privateKeyEncrypted:
|
||||
type: string
|
||||
format: base64 encoded data
|
||||
|
@ -23,7 +23,8 @@ func GetAccountStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// construct response
|
||||
seal := &Seal{}
|
||||
seal.Salt = account.AccountDetail.SealSalt
|
||||
seal.PasswordSalt = account.AccountDetail.SealSalt
|
||||
seal.PrivateKeyIV = account.AccountDetail.SealIV
|
||||
seal.PrivateKeyEncrypted = account.AccountDetail.SealPrivate
|
||||
seal.PublicKey = account.AccountDetail.SealPublic
|
||||
status := &AccountStatus{}
|
||||
|
@ -22,7 +22,8 @@ func SetAccountSeal(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// update record
|
||||
account.AccountDetail.SealSalt = seal.Salt
|
||||
account.AccountDetail.SealSalt = seal.PasswordSalt
|
||||
account.AccountDetail.SealIV = seal.PrivateKeyIV
|
||||
account.AccountDetail.SealPrivate = seal.PrivateKeyEncrypted
|
||||
account.AccountDetail.SealPublic = seal.PublicKey
|
||||
|
||||
|
@ -406,9 +406,11 @@ type Revision struct {
|
||||
|
||||
//Seal key for channel sealing
|
||||
type Seal struct {
|
||||
Salt string `json:"salt"`
|
||||
PasswordSalt string `json:"passwordSalt"`
|
||||
|
||||
PrivateKeyEncrypted string `json:"privateKeyEncrypted,omitempty"`
|
||||
PrivateKeyIV string `json:"privateKeyIv,omitempty"`
|
||||
|
||||
PrivateKeyEncrypted string `json:"privateKeyEncrypted,omitempty"`
|
||||
|
||||
PublicKey string `json:"publicKey,omitempty"`
|
||||
}
|
||||
|
@ -96,6 +96,7 @@ type AccountDetail struct {
|
||||
Location string
|
||||
Image string
|
||||
SealSalt string
|
||||
SealIV string
|
||||
SealPrivate string
|
||||
SealPublic string
|
||||
}
|
||||
|
@ -6,9 +6,11 @@
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
"@testing-library/react": "^12.0.0",
|
||||
"@testing-library/user-event": "^13.2.1",
|
||||
"antd": "^4.19.1",
|
||||
"antd": "^5.0.4",
|
||||
"axios": "^0.27.2",
|
||||
"base-64": "^1.0.0",
|
||||
"crypto-js": "^4.1.1",
|
||||
"jsencrypt": "^2.3.1",
|
||||
"react": "^17.0.2",
|
||||
"react-color": "^2.19.3",
|
||||
"react-dom": "^17.0.2",
|
||||
@ -17,7 +19,6 @@
|
||||
"react-resize-detector": "^7.0.0",
|
||||
"react-router-dom": "^6.2.2",
|
||||
"react-scripts": "5.0.0",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"styled-components": "^5.3.3",
|
||||
"web-vitals": "^2.1.0"
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
import 'antd/dist/antd.min.css';
|
||||
import 'antd/dist/reset.css';
|
||||
import { HashRouter as Router, Routes, Route } from "react-router-dom";
|
||||
|
||||
import { AppContextProvider } from 'context/AppContext';
|
||||
@ -29,8 +29,8 @@ function App() {
|
||||
<GroupContextProvider>
|
||||
<ArticleContextProvider>
|
||||
<ProfileContextProvider>
|
||||
<AccountContextProvider>
|
||||
<StoreContextProvider>
|
||||
<StoreContextProvider>
|
||||
<AccountContextProvider>
|
||||
<ViewportContextProvider>
|
||||
<AppContextProvider>
|
||||
<AppWrapper>
|
||||
@ -51,8 +51,8 @@ function App() {
|
||||
</AppWrapper>
|
||||
</AppContextProvider>
|
||||
</ViewportContextProvider>
|
||||
</StoreContextProvider>
|
||||
</AccountContextProvider>
|
||||
</AccountContextProvider>
|
||||
</StoreContextProvider>
|
||||
</ProfileContextProvider>
|
||||
</ArticleContextProvider>
|
||||
</GroupContextProvider>
|
||||
|
7
net/web/src/api/setAccountSeal.js
Normal file
7
net/web/src/api/setAccountSeal.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setAccountSeal(token, seal) {
|
||||
let res = await fetchWithTimeout('/account/seal?agent=' + token, { method: 'PUT', body: JSON.stringify(seal) })
|
||||
checkResponse(res);
|
||||
}
|
||||
|
@ -1,17 +1,23 @@
|
||||
import { useState, useRef } from 'react';
|
||||
import { useContext, useState, useRef } from 'react';
|
||||
import { setAccountSearchable } from 'api/setAccountSearchable';
|
||||
import { setAccountSeal } from 'api/setAccountSeal';
|
||||
import { getAccountStatus } from 'api/getAccountStatus';
|
||||
import { setAccountLogin } from 'api/setAccountLogin';
|
||||
import { StoreContext } from './StoreContext';
|
||||
|
||||
export function useAccountContext() {
|
||||
const [state, setState] = useState({
|
||||
init: false,
|
||||
status: null,
|
||||
seal: null,
|
||||
sealPrivate: null,
|
||||
});
|
||||
const access = useRef(null);
|
||||
const revision = useRef(null);
|
||||
const next = useRef(null);
|
||||
|
||||
const storeContext = useContext(StoreContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }))
|
||||
}
|
||||
@ -20,7 +26,30 @@ export function useAccountContext() {
|
||||
if (next.current == null) {
|
||||
if (revision.current !== rev) {
|
||||
let status = await getAccountStatus(access.current);
|
||||
updateState({ init: true, status });
|
||||
let seal = status.seal?.publicKey ? status.seal : null;
|
||||
let sealPrivate = null;
|
||||
const pubKey = await storeContext.actions.getValue("seal:public");
|
||||
const privKey = await storeContext.actions.getValue("seal:private");
|
||||
if (status.seal?.publicKey == null) {
|
||||
if (pubKey != null) {
|
||||
await storeContext.actions.setValue("seal:public", null);
|
||||
}
|
||||
if (privKey != null) {
|
||||
await storeContext.actions.setValue("seal:private", null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pubKey !== status.seal?.publicKey) {
|
||||
if (privKey != null) {
|
||||
await storeContext.actions.setValue("seal:private", null);
|
||||
}
|
||||
await storeContext.actions.setValue("seal:public", status.seal?.publicKey);
|
||||
}
|
||||
if (privKey != null) {
|
||||
sealPrivate = privKey;
|
||||
}
|
||||
}
|
||||
updateState({ init: true, status, seal, sealPrivate });
|
||||
revision.current = rev;
|
||||
}
|
||||
if (next.current != null) {
|
||||
@ -48,6 +77,18 @@ export function useAccountContext() {
|
||||
setSearchable: async (flag) => {
|
||||
await setAccountSearchable(access.current, flag);
|
||||
},
|
||||
setSeal: async (seal, sealPrivate) => {
|
||||
await storeContext.actions.setValue("seal:private", null);
|
||||
await storeContext.actions.setValue("seal:public", seal.publicKey);
|
||||
await storeContext.actions.setValue("seal:private", sealPrivate);
|
||||
await setAccountSeal(access.current, seal);
|
||||
updateState({ seal, sealPrivate });
|
||||
},
|
||||
unlockSeal: async (sealPrivate) => {
|
||||
console.log("UNLOCKING: ", sealPrivate);
|
||||
await storeContext.actions.setValue("seal:private", sealPrivate);
|
||||
updateState({ sealPrivate });
|
||||
},
|
||||
setLogin: async (username, password) => {
|
||||
await setAccountLogin(access.current, username, password);
|
||||
},
|
||||
|
@ -1,16 +1,30 @@
|
||||
import { AccountAccessWrapper, EditFooter } from './AccountAccess.styled';
|
||||
import { AccountAccessWrapper, SealModal, EditFooter } from './AccountAccess.styled';
|
||||
import { useAccountAccess } from './useAccountAccess.hook';
|
||||
import { AccountLogin } from './accountLogin/AccountLogin';
|
||||
import { Button, Modal, Checkbox } from 'antd';
|
||||
import { LockOutlined } from '@ant-design/icons';
|
||||
import { Button, Modal, Switch, Input } from 'antd';
|
||||
import { SettingOutlined, LockOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
export function AccountAccess() {
|
||||
|
||||
const { state, actions } = useAccountAccess();
|
||||
|
||||
const saveSearchable = async (e) => {
|
||||
const saveSeal = async () => {
|
||||
try {
|
||||
await actions.setSearchable(e.target.checked);
|
||||
await actions.saveSeal();
|
||||
actions.clearEditSeal();
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
Modal.error({
|
||||
title: 'Failed to Set Sealing Key',
|
||||
comment: 'Please try again.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const saveSearchable = async (enable) => {
|
||||
try {
|
||||
await actions.setSearchable(enable);
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
@ -43,13 +57,71 @@ export function AccountAccess() {
|
||||
</EditFooter>
|
||||
);
|
||||
|
||||
const editSealFooter = (
|
||||
<EditFooter>
|
||||
<div class="select"></div>
|
||||
<Button key="back" onClick={actions.clearEditSeal}>Cancel</Button>
|
||||
{ state.editSealMode == null && state.seal && !state.sealPrivate && (
|
||||
<Button key="save" type="primary" onClick={() => saveSeal()} disabled={!actions.canSaveSeal()} loading={state.busy}>Unlock</Button>
|
||||
)}
|
||||
{ !(state.editSealMode == null && state.seal && !state.sealPrivate) && (
|
||||
<Button key="save" type="primary" onClick={() => saveSeal()} disabled={!actions.canSaveSeal()} loading={state.busy}>Save</Button>
|
||||
)}
|
||||
</EditFooter>
|
||||
);
|
||||
|
||||
return (
|
||||
<AccountAccessWrapper>
|
||||
<Checkbox checked={state.searchable} onChange={(e) => saveSearchable(e)}>Visible in Registry</Checkbox>
|
||||
<div class="switch">
|
||||
<Switch size="small" checked={state.searchable} onChange={enable => saveSearchable(enable)} />
|
||||
<div class="switchLabel">Visible in Registry </div>
|
||||
</div>
|
||||
<div class="link" onClick={actions.setEditSeal}>
|
||||
<SettingOutlined />
|
||||
<div class="label">Sealed Topics</div>
|
||||
</div>
|
||||
<div class="link" onClick={actions.setEditLogin}>
|
||||
<LockOutlined />
|
||||
<div class="label">Change Login</div>
|
||||
</div>
|
||||
<Modal title="Topic Sealing Key" centered visible={state.editSeal} footer={editSealFooter} onCancel={actions.clearEditSeal}>
|
||||
<SealModal>
|
||||
<div class="switch">
|
||||
<Switch size="small" checked={state.editSealEnabled} onChange={enable => actions.enableSeal(enable)} />
|
||||
<div class="switchLabel">Enable Sealed Topics</div>
|
||||
</div>
|
||||
{ (state.editSealMode === 'updating' || state.editSealMode === 'sealing') && (
|
||||
<div class="sealPassword">
|
||||
<Input.Password placeholder="New Password" spellCheck="false" onChange={(e) => actions.setSealPassword(e.target.value)}
|
||||
autocomplete="new-password" prefix={<LockOutlined />} />
|
||||
</div>
|
||||
)}
|
||||
{ (state.editSealMode === 'updating' || state.editSealMode === 'sealing') && (
|
||||
<div class="sealPassword">
|
||||
<Input.Password placeholder="Confirm Password" spellCheck="false" onChange={(e) => actions.setSealConfirm(e.target.value)}
|
||||
autocomplete="new-password" prefix={<LockOutlined />} />
|
||||
</div>
|
||||
)}
|
||||
{ state.editSealMode === 'unsealing' && (
|
||||
<div class="sealPassword">
|
||||
<Input placeholder="Type 'delete' to remove key" spellCheck="false" onChange={(e) => actions.setUnseal(e.target.value)}
|
||||
prefix={<ExclamationCircleOutlined />} />
|
||||
</div>
|
||||
)}
|
||||
{ state.editSealMode == null && state.editSealEnabled && state.sealPrivate && (
|
||||
<div class="sealPassword" onClick={() => actions.updateSeal()}>
|
||||
<Input.Password defaultValue="xxxxxxxxxx" disabled={true} prefix={<LockOutlined />} />
|
||||
<div class="editPassword" />
|
||||
</div>
|
||||
)}
|
||||
{ state.editSealMode == null && state.seal && !state.sealPrivate && (
|
||||
<div class="sealPassword">
|
||||
<Input placeholder="Password" spellCheck="false" onChange={(e) => actions.setUnlock(e.target.value)}
|
||||
prefix={<LockOutlined />} />
|
||||
</div>
|
||||
)}
|
||||
</SealModal>
|
||||
</Modal>
|
||||
<Modal title="Account Login" centered visible={state.editLogin} footer={editLoginFooter}
|
||||
onCancel={actions.clearEditLogin}>
|
||||
<AccountLogin state={state} actions={actions} />
|
||||
|
@ -8,6 +8,27 @@ export const AccountAccessWrapper = styled.div`
|
||||
justify-content: center;
|
||||
padding-bottom: 8px;
|
||||
|
||||
.switch {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-bottom: 8px;
|
||||
|
||||
.switchEnabled {
|
||||
color: ${Colors.primary};
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.switchDisabled {
|
||||
color: ${Colors.grey};
|
||||
}
|
||||
|
||||
.switchLabel {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -15,6 +36,7 @@ export const AccountAccessWrapper = styled.div`
|
||||
cursor: pointer;
|
||||
color: ${Colors.primary};
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
.label {
|
||||
padding-left: 8px;
|
||||
@ -22,6 +44,42 @@ export const AccountAccessWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export const SealModal = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 8px;
|
||||
|
||||
.switch {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-bottom: 8px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.switchLabel {
|
||||
color: ${Colors.text};
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.sealPassword {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
position: relative;
|
||||
|
||||
.editPassword {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const EditFooter = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
@ -2,20 +2,31 @@ import { useRef, useState, useEffect, useContext } from 'react';
|
||||
import { AccountContext } from 'context/AccountContext';
|
||||
import { ProfileContext } from 'context/ProfileContext';
|
||||
import { getUsername } from 'api/getUsername';
|
||||
import CryptoJS from 'crypto-js';
|
||||
import { JSEncrypt } from 'jsencrypt'
|
||||
|
||||
export function useAccountAccess() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
editLogin: false,
|
||||
editSeal: false,
|
||||
handle: null,
|
||||
editHandle: null,
|
||||
editStatus: null,
|
||||
editMessage: null,
|
||||
editPassword: null,
|
||||
editConfirm: null,
|
||||
EditConfirm: null,
|
||||
busy: false,
|
||||
searchable: null,
|
||||
checked: true,
|
||||
editSealEnabled: false,
|
||||
editSealMode: null,
|
||||
sealPassword: null,
|
||||
sealConfirm: null,
|
||||
unseal: null,
|
||||
unlock: null,
|
||||
seal: null,
|
||||
sealPrivate: null,
|
||||
});
|
||||
|
||||
const profile = useContext(ProfileContext);
|
||||
@ -35,11 +46,241 @@ export function useAccountAccess() {
|
||||
|
||||
useEffect(() => {
|
||||
if (account?.state?.status) {
|
||||
updateState({ searchable: account.state.status.searchable });
|
||||
const { seal, sealPrivate, status } = account.state;
|
||||
updateState({ searchable: status.searchabled, seal, sealPrivate });
|
||||
}
|
||||
}, [account]);
|
||||
|
||||
const 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
|
||||
};
|
||||
|
||||
const sealUnlock = async () => {
|
||||
|
||||
console.log("UNLOCKING");
|
||||
console.log(state.seal.passwordSalt);
|
||||
console.log(state.seal.privateKeyIv);
|
||||
console.log(state.unlock);
|
||||
// generate key to encrypt private key
|
||||
const salt = CryptoJS.enc.Hex.parse(state.seal.passwordSalt);
|
||||
const aes = CryptoJS.PBKDF2(state.unlock, salt, {
|
||||
keySize: 256 / 32,
|
||||
iterations: 1024,
|
||||
});
|
||||
|
||||
// decrypt private key
|
||||
const iv = CryptoJS.enc.Hex.parse(state.seal.privateKeyIv);
|
||||
const enc = CryptoJS.enc.Base64.parse(state.seal.privateKeyEncrypted)
|
||||
let cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext: enc,
|
||||
iv: iv
|
||||
});
|
||||
const dec = CryptoJS.AES.decrypt(cipherParams, aes, { iv: iv });
|
||||
|
||||
// store keuy
|
||||
await account.actions.unlockSeal(dec.toString(CryptoJS.enc.Utf8))
|
||||
};
|
||||
|
||||
const sealEnable = async () => {
|
||||
|
||||
// generate key to encrypt private key
|
||||
const salt = CryptoJS.lib.WordArray.random(128 / 8);
|
||||
const aes = CryptoJS.PBKDF2(state.sealPassword, salt, {
|
||||
keySize: 256 / 32,
|
||||
iterations: 1024,
|
||||
});
|
||||
|
||||
// generate rsa key for sealing channel
|
||||
const crypto = new JSEncrypt({ default_key_size: 2048 });
|
||||
const key = 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 });
|
||||
|
||||
// update account
|
||||
const seal = {
|
||||
passwordSalt: salt.toString(),
|
||||
privateKeyIv: iv.toString(),
|
||||
privateKeyEncrypted: enc.ciphertext.toString(CryptoJS.enc.Base64),
|
||||
publicKey: convertPem(crypto.getPublicKey()),
|
||||
}
|
||||
await account.actions.setSeal(seal, privateKey);
|
||||
};
|
||||
|
||||
const sealRemove = async () => {
|
||||
await account.actions.setSeal({});
|
||||
};
|
||||
|
||||
const sealUpdate = async () => {
|
||||
|
||||
// generate key to encrypt private key
|
||||
const salt = CryptoJS.lib.WordArray.random(128 / 8);
|
||||
const aes = CryptoJS.PBKDF2(state.sealPassword, salt, {
|
||||
keySize: 256 / 32,
|
||||
iterations: 1024,
|
||||
});
|
||||
|
||||
// encrypt private key
|
||||
const iv = CryptoJS.lib.WordArray.random(128 / 8);
|
||||
const enc = CryptoJS.AES.encrypt(state.privateKey, aes, { iv: iv });
|
||||
|
||||
// update account
|
||||
const seal = {
|
||||
passwordSalt: salt.toString(),
|
||||
privateKeyIv: iv.toString(),
|
||||
privateKeyEncrypted: enc.ciphertext.toString(CryptoJS.enc.Base64),
|
||||
publicKey: state.seal.publicKey,
|
||||
}
|
||||
await account.actions.setSeal(seal, state.privateKey);
|
||||
};
|
||||
|
||||
const test = async () => {
|
||||
console.log("TESTING");
|
||||
var salt = CryptoJS.lib.WordArray.random(128 / 8);
|
||||
var key256Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, {
|
||||
keySize: 256 / 32,
|
||||
iterations: 1024,
|
||||
});
|
||||
console.log(key256Bits);
|
||||
|
||||
const crypto = new JSEncrypt({ default_key_size: 2048 });
|
||||
console.log(crypto);
|
||||
|
||||
const key = crypto.getKey();
|
||||
console.log(key);
|
||||
console.log(crypto.getPrivateKey());
|
||||
|
||||
const encrypted = crypto.encrypt("TEST MESSAGE");
|
||||
|
||||
console.log(encrypted);
|
||||
|
||||
const decrypted = crypto.decrypt(encrypted);
|
||||
|
||||
console.log(decrypted);
|
||||
|
||||
const recrypt = crypto.encrypt("TEST MESSAGE");
|
||||
|
||||
console.log(recrypt);
|
||||
|
||||
const output = crypto.decrypt(recrypt);
|
||||
|
||||
console.log(output);
|
||||
|
||||
|
||||
var aes = CryptoJS.lib.WordArray.random(256 / 8);
|
||||
var iv = CryptoJS.lib.WordArray.random(128 / 8);
|
||||
var enc = CryptoJS.AES.encrypt("Message", key, { iv: iv });
|
||||
|
||||
console.log(aes);
|
||||
console.log(key256Bits);
|
||||
|
||||
console.log(enc);
|
||||
|
||||
var cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext: enc.ciphertext,
|
||||
iv: iv
|
||||
});
|
||||
|
||||
var dec = CryptoJS.AES.decrypt(cipherParams, key, { iv: iv });
|
||||
|
||||
console.log(dec);
|
||||
|
||||
console.log(dec.toString(CryptoJS.enc.Utf8));
|
||||
};
|
||||
|
||||
|
||||
const actions = {
|
||||
setEditSeal: () => {
|
||||
updateState({ editSeal: true, editSealMode: null, unlock: null, editSealEnabled: state.seal });
|
||||
},
|
||||
clearEditSeal: () => {
|
||||
updateState({ editSeal: false });
|
||||
},
|
||||
setSealPassword: (sealPassword) => {
|
||||
updateState({ sealPassword });
|
||||
},
|
||||
setSealConfirm: (sealConfirm) => {
|
||||
updateState({ sealConfirm });
|
||||
},
|
||||
setUnseal: (unseal) => {
|
||||
updateState({ unseal });
|
||||
},
|
||||
setUnlock: (unlock) => {
|
||||
updateState({ unlock });
|
||||
},
|
||||
updateSeal: () => {
|
||||
updateState({ editSealMode: 'updating', sealConfirm: null, sealPassword: null });
|
||||
},
|
||||
enableSeal: (enable) => {
|
||||
if (enable && state.seal) {
|
||||
updateState({ editSealEnabled: true, editSealMode: null });
|
||||
}
|
||||
else if (enable) {
|
||||
updateState({ editSealEnabled: true, editSealMode: 'sealing', sealConfirm: null, sealPassword: null });
|
||||
}
|
||||
else if (!enable && state.seal) {
|
||||
updateState({ editSealEnabled: false, editSealMode: 'unsealing', unseal: null });
|
||||
}
|
||||
else {
|
||||
updateState({ editSealEnabled: false, editSealMode: null });
|
||||
}
|
||||
},
|
||||
canSaveSeal: () => {
|
||||
if (state.editSealMode === 'unsealing' && state.unseal === 'delete') {
|
||||
return true;
|
||||
}
|
||||
if (state.editSealMode === 'sealing' && state.sealPassword && state.sealPassword === state.sealConfirm) {
|
||||
return true;
|
||||
}
|
||||
if (state.editSealMode === 'updating' && state.sealPassword && state.sealPassword === state.sealConfirm) {
|
||||
return true;
|
||||
}
|
||||
if (state.editSealMode == null && state.seal && !state.sealPrivate) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
saveSeal: async () => {
|
||||
if (state.busy) {
|
||||
throw new Error("operation in progress");
|
||||
}
|
||||
updateState({ busy: true });
|
||||
try {
|
||||
if (state.editSealMode === 'sealing') {
|
||||
await sealEnable();
|
||||
}
|
||||
else if (state.editSealMode === 'unsealing') {
|
||||
await sealRemove();
|
||||
}
|
||||
else if (state.editSealMode === 'updating') {
|
||||
await sealUpdate();
|
||||
}
|
||||
else {
|
||||
await sealUnlock();
|
||||
}
|
||||
updateState({ busy: false });
|
||||
}
|
||||
catch (err) {
|
||||
updateState({ busy: false });
|
||||
console.log(err);
|
||||
throw new Error("failed to save seal");
|
||||
}
|
||||
},
|
||||
setEditLogin: () => {
|
||||
updateState({ editLogin: true });
|
||||
},
|
||||
|
15620
net/web/yarn.lock
15620
net/web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user