Skip to content

Commit

Permalink
feat: add a new payload version v38 ("4/4")
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed Oct 10, 2019
1 parent 6c608c2 commit ff9c49e
Show file tree
Hide file tree
Showing 21 changed files with 164 additions and 84 deletions.
1 change: 1 addition & 0 deletions src/background-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ Object.assign(window, {
gun2: require('./network/gun/version.2'),
crypto40: require('./crypto/crypto-alpha-40'),
crypto39: require('./crypto/crypto-alpha-39'),
crypto38: require('./crypto/crypto-alpha-38'),
db: {
avatar: require('./database/avatar'),
group: require('./database/group'),
Expand Down
2 changes: 1 addition & 1 deletion src/components/InjectedComponents/AdditionalPostBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export function AdditionalPostBox(props: Partial<Props>) {
warningText: geti18nString('additional_post_box__encrypted_failed'),
shouldOpenPostDialog: false,
})
Services.Crypto.publishPostAESKey(token, identity[0].identifier)
Services.Crypto.publishPostAESKey(token)
},
[identity],
)
Expand Down
5 changes: 4 additions & 1 deletion src/components/InjectedComponents/DecryptedPost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,16 @@ function DecryptPost(props: DecryptPostProps) {
const postPayload = deconstructPayload(encryptedText, null)
if (!postPayload) return null
const postByMyself = <DebugModeUI_PostHashDialog network={postBy.network} post={encryptedText} />

const ownersAESKeyEncrypted =
postPayload.version === -38 ? postPayload.AESKeyEncrypted : postPayload.ownersAESKeyEncrypted
return (
<DebugList
items={[
postBy.equals(whoAmI) ? postByMyself : (['Hash of this post', debugHash] as const),
['Decrypt reason', decryptedResult ? decryptedResult.through.join(',') : 'Unknown'],
['Payload version', postPayload.version],
['Payload ownersAESKeyEncrypted', postPayload.ownersAESKeyEncrypted],
['Payload ownersAESKeyEncrypted', ownersAESKeyEncrypted],
['Payload iv', postPayload.iv],
['Payload encryptedText', postPayload.encryptedText],
['Payload signature', postPayload.signature],
Expand Down
6 changes: 5 additions & 1 deletion src/components/InjectedComponents/PostInspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ export function PostInspector(props: PostInspectorProps) {

if (type.encryptedPost) {
if (!isDebugging) props.needZip()
const { iv, ownersAESKeyEncrypted, version } = type.encryptedPost
const { iv, version } = type.encryptedPost
const ownersAESKeyEncrypted =
type.encryptedPost.version === -38
? type.encryptedPost.AESKeyEncrypted
: type.encryptedPost.ownersAESKeyEncrypted
return (
<>
<DecryptPostUI.UI
Expand Down
1 change: 1 addition & 0 deletions src/crypto/crypto-alpha-38.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './crypto-alpha-39'
26 changes: 18 additions & 8 deletions src/crypto/crypto-alpha-39.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
/**
* @deprecated This version of payload is not in use.
* Please goto Crypto alpha v38
*/
import {
generateOthersAESKeyEncrypted as generateOthersAESKeyEncryptedV40,
encrypt1ToN as encrypt1ToN40,
} from './crypto-alpha-40'
export type PublishedAESKey = { encryptedKey: string; salt: string }
export type PublishedAESKeyRecordV39 = {
export type PublishedAESKeyRecordV39OrV38 = {
aesKey: PublishedAESKey
receiverKey: CryptoKey
}
export async function generateOthersAESKeyEncrypted(
version: -39,
version: -39 | -38,
AESKey: CryptoKey,
privateKeyECDH: CryptoKey,
othersPublicKeyECDH: CryptoKey[],
): Promise<PublishedAESKeyRecordV39[]> {
): Promise<PublishedAESKeyRecordV39OrV38[]> {
const othersPublicKeyECDH_ = othersPublicKeyECDH.map((x, index) => ({ key: x, name: index.toString() }))
const othersAESKeyEncrypted = await generateOthersAESKeyEncryptedV40(
-40,
AESKey,
privateKeyECDH,
othersPublicKeyECDH_,
)
const othersAESKeyEncrypted_ = othersAESKeyEncrypted.map<PublishedAESKeyRecordV39>(key => ({
const othersAESKeyEncrypted_ = othersAESKeyEncrypted.map<PublishedAESKeyRecordV39OrV38>(key => ({
aesKey: key.key,
receiverKey: othersPublicKeyECDH[parseInt(key.name, 10)],
}))
Expand All @@ -32,7 +36,7 @@ export async function generateOthersAESKeyEncrypted(
* This function is generally based on encrypt1ToN in crypto-alpha-40
*/
export async function encrypt1ToN(info: {
version: -39
version: -38
/** Message to encrypt */
content: string | ArrayBuffer
/** Your private key */
Expand All @@ -44,13 +48,13 @@ export async function encrypt1ToN(info: {
/** iv */
iv: ArrayBuffer
}): Promise<{
version: -39
version: -38
encryptedContent: ArrayBuffer
iv: ArrayBuffer
/** Your encrypted post aes key. Should be attached in the post. */
ownersAESKeyEncrypted: ArrayBuffer
/** All encrypted post aes key. Should be post on the gun. */
othersAESKeyEncrypted: PublishedAESKeyRecordV39[]
othersAESKeyEncrypted: PublishedAESKeyRecordV39OrV38[]
}> {
const othersPublicKeyECDH = info.othersPublicKeyECDH.map((x, index) => ({ key: x, name: index.toString() }))
const { encryptedContent, iv, othersAESKeyEncrypted, ownersAESKeyEncrypted } = await encrypt1ToN40({
Expand All @@ -62,7 +66,13 @@ export async function encrypt1ToN(info: {
aesKey: key.key,
receiverKey: othersPublicKeyECDH[parseInt(key.name, 10)].key,
}))
return { encryptedContent, iv, version: -39, ownersAESKeyEncrypted, othersAESKeyEncrypted: othersAESKeyEncrypted_ }
return {
encryptedContent,
iv,
version: info.version,
ownersAESKeyEncrypted,
othersAESKeyEncrypted: othersAESKeyEncrypted_,
}
}

export { encrypt1To1, decryptMessage1To1 } from './crypto-alpha-40'
Expand Down
15 changes: 8 additions & 7 deletions src/crypto/crypto-alpha-40.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @deprecated This version of payload is not in use.
* Please goto Crypto alpha v39
* Please goto Crypto alpha v38
*/
import {
encodeText,
Expand Down Expand Up @@ -69,7 +69,7 @@ async function deriveAESKey(
* Encrypt 1 to 1
*/
export async function encrypt1To1(info: {
version: -40 | -39
version: -38
/** Message that you want to encrypt */
content: string | ArrayBuffer
/** Your private key */
Expand Down Expand Up @@ -99,7 +99,8 @@ export async function generateOthersAESKeyEncrypted(
return Promise.all(
othersPublicKeyECDH.map<Promise<PublishedAESKeyRecordV40>>(async ({ key, name }) => {
const encrypted = await encrypt1To1({
version: -40,
// This is the deprecated -40 code path
version: (-40 as unknown) as -38,
content: exportedAESKey,
othersPublicKeyECDH: key,
privateKeyECDH: privateKeyECDH,
Expand Down Expand Up @@ -162,7 +163,7 @@ export async function encrypt1ToN(info: {
* Decrypt 1 to 1
*/
export async function decryptMessage1To1(info: {
version: -40 | -39
version: -40 | -39 | -38
encryptedContent: string | ArrayBuffer
salt: string | ArrayBuffer
/** Your private key */
Expand All @@ -181,7 +182,7 @@ export async function decryptMessage1To1(info: {
* Decrypt 1 to N message that send by other
*/
export async function decryptMessage1ToNByOther(info: {
version: -40 | -39
version: -40 | -39 | -38
encryptedContent: string | ArrayBuffer
privateKeyECDH: CryptoKey
authorsPublicKeyECDH: CryptoKey
Expand Down Expand Up @@ -211,7 +212,7 @@ export async function decryptMessage1ToNByOther(info: {
return [await decryptWithAES({ aesKey, iv, encrypted: encryptedContent }), aesKey]
}
export async function extractAESKeyInMessage(
version: -40 | -39,
version: -40 | -39 | -38,
encodedEncryptedKey: string | ArrayBuffer,
_iv: string | ArrayBuffer,
myLocalKey: CryptoKey,
Expand All @@ -228,7 +229,7 @@ export async function extractAESKeyInMessage(
* Decrypt 1 to N message that send by myself
*/
export async function decryptMessage1ToNByMyself(info: {
version: -40 | -39
version: -40 | -39 | -38
encryptedContent: string | ArrayBuffer
/** This should be included in the message */
encryptedAESKey: string | ArrayBuffer
Expand Down
16 changes: 8 additions & 8 deletions src/database/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { PostIdentifier, PersonIdentifier, Identifier, PostIVIdentifier } from './type'
import { openDB, DBSchema } from 'idb/with-async-ittr'

function outDb(db: PostDBRecordV40_Or_v39): PostOutDBRecordV40_Or_v39 {
function outDb(db: PostDBRecordV40ToV38): PostOutDBRecordV40ToV38 {
const { identifier, ...rest } = db
// Restore prototype
;(rest.recipients || []).forEach(y => Object.setPrototypeOf(y, PersonIdentifier.prototype))
Expand All @@ -11,25 +11,25 @@ function outDb(db: PostDBRecordV40_Or_v39): PostOutDBRecordV40_Or_v39 {
identifier: Identifier.fromString(identifier) as PostIVIdentifier,
}
}
function toDb(out: PostOutDBRecordV40_Or_v39): PostDBRecordV40_Or_v39 {
function toDb(out: PostOutDBRecordV40ToV38): PostDBRecordV40ToV38 {
return { ...out, identifier: out.identifier.toText() }
}
interface PostOutDBRecordV40_Or_v39 extends Omit<PostDBRecordV40_Or_v39, 'identifier'> {
interface PostOutDBRecordV40ToV38 extends Omit<PostDBRecordV40ToV38, 'identifier'> {
identifier: PostIVIdentifier
}
interface PostDBRecordV40_Or_v39 {
interface PostDBRecordV40ToV38 {
identifier: string
/**
* ! This MUST BE a native CryptoKey
*/
postCryptoKey?: CryptoKey
version: -40 | -39
version: -40 | -39 | -38
recipients?: PersonIdentifier[]
}
interface PostDB extends DBSchema {
/** Use inline keys */
post: {
value: PostDBRecordV40_Or_v39
value: PostDBRecordV40ToV38
key: string
}
}
Expand Down Expand Up @@ -62,7 +62,7 @@ const db = openDB<PostDB>('maskbook-post-v2', 2, {
},
})
export async function updatePostDB(
record: Partial<PostOutDBRecordV40_Or_v39> & Pick<PostOutDBRecordV40_Or_v39, 'identifier'>,
record: Partial<PostOutDBRecordV40ToV38> & Pick<PostOutDBRecordV40ToV38, 'identifier'>,
mode: 'append' | 'override',
): Promise<void> {
const _rec = (await queryPostDB(record.identifier)) || { identifier: record.identifier, version: -40 }
Expand All @@ -72,7 +72,7 @@ export async function updatePostDB(
const t = (await db).transaction('post', 'readwrite')
await t.objectStore('post').put(toDb(rec))
}
export async function queryPostDB(record: PostIVIdentifier): Promise<PostOutDBRecordV40_Or_v39 | null> {
export async function queryPostDB(record: PostIVIdentifier): Promise<PostOutDBRecordV40ToV38 | null> {
const t = (await db).transaction('post')
const result = await t.objectStore('post').get(record.toText())
if (result) return outDb(result)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
import * as Alpha40 from '../../../crypto/crypto-alpha-40'
import * as Alpha39 from '../../../crypto/crypto-alpha-39'
import * as Alpha38 from '../../../crypto/crypto-alpha-38'
import * as Gun1 from '../../../network/gun/version.1'
import * as Gun2 from '../../../network/gun/version.2'
import { getMyPrivateKey } from '../../../database'
import { queryLocalKeyDB } from '../../../database/people'
import { PersonIdentifier } from '../../../database/type'
import { prepareOthersKeyForEncryptionV40, prepareOthersKeyForEncryptionV39 } from '../prepareOthersKeyForEncryption'
import {
prepareOthersKeyForEncryptionV40,
prepareOthersKeyForEncryptionV39OrV38,
} from '../prepareOthersKeyForEncryption'
export async function appendShareTarget(
version: -40 | -39,
version: -40 | -39 | -38,
postIdentifier: string,
ownersAESKeyEncrypted: string,
iv: string,
people: PersonIdentifier[],
whoAmI: PersonIdentifier,
): Promise<void> {
const cryptoProvider = version === -40 ? Alpha40 : Alpha39
const toKey = await prepareOthersKeyForEncryptionV40(people)
const cryptoProviderTable = {
[-40]: Alpha40,
[-39]: Alpha39,
[-38]: Alpha38,
}
const cryptoProvider = cryptoProviderTable[version]
const AESKey = await cryptoProvider.extractAESKeyInMessage(
version,
ownersAESKeyEncrypted,
iv,
(await queryLocalKeyDB(whoAmI))!,
)
const myPrivateKey = (await getMyPrivateKey(whoAmI))!.privateKey
if (version === -39) {
const toKey = await prepareOthersKeyForEncryptionV39(people)
const othersAESKeyEncrypted = await Alpha39.generateOthersAESKeyEncrypted(-39, AESKey, myPrivateKey, toKey)
Gun2.publishPostAESKeyOnGun2(-39, iv, othersAESKeyEncrypted)
if (version === -39 || version === -38) {
const toKey = await prepareOthersKeyForEncryptionV39OrV38(people)
const othersAESKeyEncrypted = await Alpha39.generateOthersAESKeyEncrypted(version, AESKey, myPrivateKey, toKey)
Gun2.publishPostAESKeyOnGun2(version, iv, othersAESKeyEncrypted)
} else if (version === -40) {
const toKey = await prepareOthersKeyForEncryptionV40(people)
const othersAESKeyEncrypted = await Alpha40.generateOthersAESKeyEncrypted(-40, AESKey, myPrivateKey, toKey)
Expand Down
31 changes: 22 additions & 9 deletions src/extension/background-script/CryptoServices/decryptFrom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as Alpha40 from '../../../crypto/crypto-alpha-40'
import * as Alpha39 from '../../../crypto/crypto-alpha-39'
import * as Alpha38 from '../../../crypto/crypto-alpha-38'
import * as Gun1 from '../../../network/gun/version.1'
import * as Gun2 from '../../../network/gun/version.2'
import { decodeText } from '../../../utils/type-transform/String-ArrayBuffer'
Expand Down Expand Up @@ -57,10 +58,21 @@ export async function* decryptFromMessageWithProgress(
}
}
const version = data.version
if (version === -40 || version === -39) {
const { encryptedText, iv, ownersAESKeyEncrypted, signature, version } = data
const unverified = [version === -40 ? '2/4' : '3/4', ownersAESKeyEncrypted, iv, encryptedText].join('|')
const cryptoProvider = version === -40 ? Alpha40 : Alpha39
if (version === -40 || version === -39 || version === -38) {
const { encryptedText, iv, signature, version } = data
const ownersAESKeyEncrypted = data.version === -38 ? data.AESKeyEncrypted : data.ownersAESKeyEncrypted
const versionTable = {
[-40]: '2/4',
[-39]: '3/4',
[-38]: '4/4',
}
const cryptoProviderTable = {
[-40]: Alpha40,
[-39]: Alpha39,
[-38]: Alpha38,
}
const unverified = [versionTable[version], ownersAESKeyEncrypted, iv, encryptedText].join('|')
const cryptoProvider = cryptoProviderTable[version]

const [cachedPostResult, setPostCache] = await decryptFromCache(data, by)

Expand Down Expand Up @@ -152,8 +164,8 @@ export async function* decryptFromMessageWithProgress(
return { signatureVerifyResult: false, content, through: ['normal_decrypted'] } as Success
}
} else {
if (cachedPostResult) {
const { keyHash, postHash } = await Gun2.queryPostKeysOnGun2(-39, iv, mine.publicKey)
if (cachedPostResult && version !== -40) {
const { keyHash, postHash } = await Gun2.queryPostKeysOnGun2(version, iv, mine.publicKey)
yield { debug: 'debug_finding_hash', hash: [postHash, keyHash] }
return {
signatureVerifyResult: await cryptoProvider.verify(
Expand All @@ -173,8 +185,8 @@ export async function* decryptFromMessageWithProgress(
const result = await Gun1.queryPostAESKey(iv, whoAmI.userId)
if (result === undefined) return { error: geti18nString('service_not_share_target') }
aesKeyEncrypted.push(result)
} else if (version === -39) {
const { keyHash, keys, postHash } = await Gun2.queryPostKeysOnGun2(-39, iv, mine.publicKey)
} else if (version === -39 || version === -38) {
const { keyHash, keys, postHash } = await Gun2.queryPostKeysOnGun2(version, iv, mine.publicKey)
yield { debug: 'debug_finding_hash', hash: [postHash, keyHash] }
aesKeyEncrypted.push(...keys)
}
Expand All @@ -199,7 +211,8 @@ export async function* decryptFromMessageWithProgress(

// Failed, we have to wait for the future info from gun.
return new Promise<Success>((resolve, reject) => {
const undo = Gun2.subscribePostKeysOnGun2(-39, iv, mine.publicKey, async key => {
if (version === -40) return reject()
const undo = Gun2.subscribePostKeysOnGun2(version, iv, mine.publicKey, async key => {
console.log('New key received, trying', key)
try {
const result = await decryptWith(key)
Expand Down
Loading

0 comments on commit ff9c49e

Please sign in to comment.