From 243f208c9563091fc7ab3024d290782b7603427e Mon Sep 17 00:00:00 2001 From: Jack Works Date: Mon, 16 Sep 2019 18:50:28 +0800 Subject: [PATCH] feat: add debug mode for PostInspector --- .../InjectedComponents/DecryptedPost.tsx | 119 +++++++++++------- .../InjectedComponents/PostInspector.tsx | 32 +++-- .../CryptoServices/decryptFrom.ts | 47 +++++-- src/network/gun/version.2/post.ts | 4 +- 4 files changed, 135 insertions(+), 67 deletions(-) diff --git a/src/components/InjectedComponents/DecryptedPost.tsx b/src/components/InjectedComponents/DecryptedPost.tsx index e7cfe39fc242..89441f453038 100644 --- a/src/components/InjectedComponents/DecryptedPost.tsx +++ b/src/components/InjectedComponents/DecryptedPost.tsx @@ -15,6 +15,8 @@ import { FailureDecryption, SuccessDecryption, } from '../../extension/background-script/CryptoServices/decryptFrom' +import { useValueRef } from '../../utils/hooks/useValueRef' +import { debugModeSetting } from '../shared-settings/debugMode' interface DecryptPostSuccessProps { data: { signatureVerifyResult: boolean; content: string } @@ -115,6 +117,9 @@ function DecryptPost(props: DecryptPostProps) { ) const [__, forceReDecrypt] = useState() + const [debugHash, setDebugHash] = useState('Unknown') + const isDebugging = useValueRef(debugModeSetting) + const rAD = useCallback( async (people: Person[]) => { await requestAppendRecipients(people) @@ -122,14 +127,30 @@ function DecryptPost(props: DecryptPostProps) { }, [requestAppendRecipients], ) + const debugHashJSX = ( +
    + {postBy.equals(whoAmI) ? null : ( +
  • + Hash of this post: {debugHash} +
    + It should be same on your friend's Maskbook, if it isn't the same, that means your friend does not + receive your crypto key correctly or you didn't set your Maskbook correctly. +
  • + )} +
  • Decrypted reason: {decryptedResult ? decryptedResult.through.join(',') : 'Unknown'}
  • +
+ ) if (decryptedResult) { return ( - + <> + + {isDebugging ? debugHashJSX : null} + ) } const awaitingComponent = @@ -139,47 +160,57 @@ function DecryptPost(props: DecryptPostProps) { ) return ( - { - const iter = ServicesWithProgress.decryptFrom(encryptedText, postBy, whoAmI) - let last = await iter.next() - while (!last.done) { - setDecryptingStatus(last.value) - last = await iter.next() - } - return last.value - }} - dependencies={[ - __, - encryptedText, - postBy.toText(), - whoAmI.toText(), - Identifier.IdentifiersToString(people.map(x => x.identifier)), - Identifier.IdentifiersToString(alreadySelectedPreviously.map(x => x.identifier)), - ]} - awaitingComponent={awaitingComponent} - completeComponent={result => { - if ('error' in result.data) { + <> + { + const iter = ServicesWithProgress.decryptFrom(encryptedText, postBy, whoAmI) + let last = await iter.next() + while (!last.done) { + if ('debug' in last.value) { + switch (last.value.debug) { + case 'debug_finding_hash': + setDebugHash(last.value.hash.join('-')) + } + } else { + setDecryptingStatus(last.value) + } + last = await iter.next() + } + return last.value + }} + dependencies={[ + __, + encryptedText, + postBy.toText(), + whoAmI.toText(), + Identifier.IdentifiersToString(people.map(x => x.identifier)), + Identifier.IdentifiersToString(alreadySelectedPreviously.map(x => x.identifier)), + ]} + awaitingComponent={awaitingComponent} + completeComponent={result => { + if ('error' in result.data) { + return ( + forceReDecrypt(Math.random())} + error={new Error(result.data.error)} + /> + ) + } + setDecryptedResult(result.data) + props.onDecrypted(result.data.content) return ( - forceReDecrypt(Math.random())} - error={new Error(result.data.error)} + ) - } - setDecryptedResult(result.data) - props.onDecrypted(result.data.content) - return ( - - ) - }} - failedComponent={DecryptPostFailed} - /> + }} + failedComponent={DecryptPostFailed} + /> + {isDebugging ? debugHashJSX : null} + ) } diff --git a/src/components/InjectedComponents/PostInspector.tsx b/src/components/InjectedComponents/PostInspector.tsx index 3df5170b7204..fa55bba31467 100644 --- a/src/components/InjectedComponents/PostInspector.tsx +++ b/src/components/InjectedComponents/PostInspector.tsx @@ -6,11 +6,11 @@ import { deconstructPayload } from '../../utils/type-transform/Payload' import Services from '../../extension/service' import { PersonIdentifier } from '../../database/type' import { Person } from '../../database' -import { styled } from '@material-ui/core/styles' import { useCurrentIdentity, useFriendsList } from '../DataSource/useActivatedUI' import { getActivatedUI } from '../../social-network/ui' +import { useValueRef } from '../../utils/hooks/useValueRef' +import { debugModeSetting } from '../shared-settings/debugMode' -const Debug = styled('div')({ display: 'none' }) interface PostInspectorProps { onDecrypted(post: string): void post: string @@ -24,6 +24,7 @@ export function PostInspector(props: PostInspectorProps) { const people = useFriendsList() const [alreadySelectedPreviously, setAlreadySelectedPreviously] = useState([]) const decodeResult = getActivatedUI().publicKeyDecoder(post) + const isDebugging = useValueRef(debugModeSetting) const type = { encryptedPost: deconstructPayload(post), provePost: decodeResult ? [decodeResult] : null, @@ -39,14 +40,23 @@ export function PostInspector(props: PostInspectorProps) { if (postBy.isUnknown) return null + const debugInfo = isDebugging ? ( +
    +
  • Post content: {props.post}
  • +
  • Post by: {props.postBy.userId}
  • +
  • + Who am I:{' '} + {whoAmI ? `Nickname ${whoAmI.nickname || 'unknown'}, UserID ${whoAmI.identifier.userId}` : 'Unknown'} +
  • +
  • Post ID: {props.postId || 'Unknown'}
  • +
+ ) : null + if (type.encryptedPost) { - props.needZip() + if (!isDebugging) props.needZip() const { iv, ownersAESKeyEncrypted, version } = type.encryptedPost return ( <> - - - { @@ -66,10 +76,16 @@ export function PostInspector(props: PostInspectorProps) { whoAmI={whoAmI ? whoAmI.identifier : PersonIdentifier.unknown} postBy={postBy} /> + {debugInfo} ) } else if (type.provePost) { - return + return ( + <> + + {debugInfo} + + ) } - return null + return debugInfo } diff --git a/src/extension/background-script/CryptoServices/decryptFrom.ts b/src/extension/background-script/CryptoServices/decryptFrom.ts index bdc3c0e8ff4b..71b35c929ad9 100644 --- a/src/extension/background-script/CryptoServices/decryptFrom.ts +++ b/src/extension/background-script/CryptoServices/decryptFrom.ts @@ -14,9 +14,14 @@ import { MessageCenter } from '../../../utils/messages' type Progress = { progress: 'finding_person_public_key' | 'finding_post_key' } +type DebugInfo = { + debug: 'debug_finding_hash' + hash: [string, string] +} type Success = { signatureVerifyResult: boolean content: string + through: ('author_key_not_found' | 'my_key_not_found' | 'post_key_cached' | 'normal_decrypted')[] } type Failure = { error: string @@ -24,8 +29,8 @@ type Failure = { export type SuccessDecryption = Success export type FailureDecryption = Failure export type DecryptionProgress = Progress -type ReturnOfDecryptFromMessageWithProgress = AsyncIterator & { - [Symbol.asyncIterator](): AsyncIterator +type ReturnOfDecryptFromMessageWithProgress = AsyncIterator & { + [Symbol.asyncIterator](): AsyncIterator } /** @@ -65,7 +70,12 @@ export async function* decryptFromMessageWithProgress( byPerson = await addPerson(by).catch(() => null) if (!byPerson || !byPerson.publicKey) { - if (cachedPostResult) return { signatureVerifyResult: false, content: cachedPostResult } + if (cachedPostResult) + return { + signatureVerifyResult: false, + content: cachedPostResult, + through: ['author_key_not_found', 'post_key_cached'], + } as Success let rejectGun = () => {} let rejectDatabase = () => {} const awaitGun = new Promise((resolve, reject) => { @@ -103,7 +113,12 @@ export async function* decryptFromMessageWithProgress( const mine = await getMyPrivateKey(whoAmI) if (!mine) { - if (cachedPostResult) return { signatureVerifyResult: false, content: cachedPostResult } + if (cachedPostResult) + return { + signatureVerifyResult: false, + content: cachedPostResult, + through: ['my_key_not_found', 'post_key_cached'], + } as Success return { error: geti18nString('service_not_setup_yet') } } @@ -113,7 +128,8 @@ export async function* decryptFromMessageWithProgress( return { signatureVerifyResult: await cryptoProvider.verify(unverified, signature || '', mine.publicKey), content: cachedPostResult, - } + through: ['post_key_cached'], + } as Success const [contentArrayBuffer, postAESKey] = await cryptoProvider.decryptMessage1ToNByMyself({ version, @@ -128,12 +144,14 @@ export async function* decryptFromMessageWithProgress( try { if (!signature) throw new Error() const signatureVerifyResult = await cryptoProvider.verify(unverified, signature, mine.publicKey) - return { signatureVerifyResult, content } + return { signatureVerifyResult, content, through: ['normal_decrypted'] } as Success } catch { - return { signatureVerifyResult: false, content } + return { signatureVerifyResult: false, content, through: ['normal_decrypted'] } as Success } } else { - if (cachedPostResult) + if (cachedPostResult) { + const { keyHash, postHash } = await Gun2.queryPostKeysOnGun2(iv, mine.publicKey) + yield { debug: 'debug_finding_hash', hash: [postHash, keyHash] } return { signatureVerifyResult: await cryptoProvider.verify( unverified, @@ -141,7 +159,9 @@ export async function* decryptFromMessageWithProgress( byPerson.publicKey, ), content: cachedPostResult, - } + through: ['post_key_cached'], + } as Success + } yield { progress: 'finding_post_key' } const aesKeyEncrypted: Array = [] if (version === -40) { @@ -151,7 +171,8 @@ export async function* decryptFromMessageWithProgress( if (result === undefined) return { error: geti18nString('service_not_share_target') } aesKeyEncrypted.push(result) } else if (version === -39) { - const keys = await Gun2.queryPostKeysOnGun2(iv, mine.publicKey) + const { keyHash, keys, postHash } = await Gun2.queryPostKeysOnGun2(iv, mine.publicKey) + yield { debug: 'debug_finding_hash', hash: [postHash, keyHash] } aesKeyEncrypted.push(...keys) } @@ -192,7 +213,7 @@ export async function* decryptFromMessageWithProgress( | Alpha39.PublishedAESKey | Alpha40.PublishedAESKey | Array, - ) { + ): Promise { const [contentArrayBuffer, postAESKey] = await cryptoProvider.decryptMessage1ToNByOther({ version, AESKeyEncrypted: key, @@ -212,9 +233,9 @@ export async function* decryptFromMessageWithProgress( signature, byPerson!.publicKey!, ) - return { signatureVerifyResult, content } + return { signatureVerifyResult, content, through: ['normal_decrypted'] } } catch { - return { signatureVerifyResult: false, content } + return { signatureVerifyResult: false, content, through: ['normal_decrypted'] } } } } diff --git a/src/network/gun/version.2/post.ts b/src/network/gun/version.2/post.ts index 3f0d28832de6..f6bca227b500 100644 --- a/src/network/gun/version.2/post.ts +++ b/src/network/gun/version.2/post.ts @@ -13,7 +13,7 @@ OnlyRunInContext('background', 'gun') export async function queryPostKeysOnGun2( postSalt: string, partitionByCryptoKey: CryptoKey, -): Promise { +): Promise<{ keys: SharedAESKeyGun2[]; postHash: string; keyHash: string }> { const postHash = await hashPostSalt(postSalt) const keyHash = await hashCryptoKey(partitionByCryptoKey) @@ -31,7 +31,7 @@ export async function queryPostKeysOnGun2( const resultPromise = internalKeys.map(key => gun2.get(key).once().then!()) const result = (await Promise.all(resultPromise)) as SharedAESKeyGun2[] console.info(`await gun2[${postHash}][${keyHash}]\n`, result) - return result + return { keys: result, keyHash, postHash } } /**