Skip to content

Commit

Permalink
feat: save post key into db, close #63
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed Jul 16, 2019
1 parent c194646 commit bccd455
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 34 deletions.
5 changes: 1 addition & 4 deletions src/components/InjectedComponents/DecryptedPost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,13 @@ function DecryptPost(props: DecryptPostProps) {
},
[requestAppendDecryptor],
)
function ifError(x: any): x is { error: string } {
return 'error' in x
}
return (
<AsyncComponent
promise={() => Services.Crypto.decryptFrom(encryptedText, postBy, whoAmI)}
dependencies={[encryptedText, people, alreadySelectedPreviously]}
awaitingComponent={DecryptPostAwaiting}
completeComponent={props =>
ifError(props.data) ? (
'error' in props.data ? (
<DecryptPostFailed error={new Error(props.data.error)} />
) : (
<DecryptPostSuccess
Expand Down
8 changes: 4 additions & 4 deletions src/crypto/crypto-alpha-40.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export async function decryptMessage1ToNByOther(info: {
authorsPublicKeyECDH: CryptoKey
AESKeyEncrypted: PublishedAESKey
iv: ArrayBuffer | string
}): Promise<ArrayBuffer> {
}): Promise<[ArrayBuffer, CryptoKey]> {
const { AESKeyEncrypted, version, encryptedContent, privateKeyECDH, authorsPublicKeyECDH, iv } = info
const aesKeyJWK = decodeText(
await decryptMessage1To1({
Expand All @@ -205,7 +205,7 @@ export async function decryptMessage1ToNByOther(info: {
false,
['decrypt'],
)
return decryptWithAES({ aesKey, iv, encrypted: encryptedContent })
return [await decryptWithAES({ aesKey, iv, encrypted: encryptedContent }), aesKey]
}
export async function extractAESKeyInMessage(
version: -40,
Expand All @@ -231,12 +231,12 @@ export async function decryptMessage1ToNByMyself(info: {
encryptedAESKey: string | ArrayBuffer
myLocalKey: CryptoKey
iv: string | ArrayBuffer
}): Promise<ArrayBuffer> {
}): Promise<[ArrayBuffer, CryptoKey]> {
const { encryptedContent, myLocalKey, version } = info
const decryptedAESKey = await extractAESKeyInMessage(-40, info.encryptedAESKey, info.iv, info.myLocalKey)
const iv = typeof info.iv === 'string' ? decodeArrayBuffer(info.iv) : info.iv
const post = await decryptWithAES({ aesKey: decryptedAESKey, encrypted: encryptedContent, iv })
return post
return [post, decryptedAESKey]
}
/**
* Decrypt the content encrypted by AES
Expand Down
3 changes: 0 additions & 3 deletions src/database/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import { openDB, DBSchema } from 'idb/with-async-ittr'

function outDb(db: PostDBRecordV40): PostOutDBRecordV40 {
const { identifier, ...rest } = db
// Restore prototype
rest.recipients.forEach(y => Object.setPrototypeOf(y, PersonIdentifier.prototype))
return {
...rest,
identifier: Identifier.fromString(identifier) as PostIdentifier,
Expand All @@ -24,7 +22,6 @@ interface PostDBRecordV40 {
*/
postCryptoKey: CryptoKey
version: -40
recipients: PersonIdentifier[]
}
interface PostDB extends DBSchema {
/** Use inline keys */
Expand Down
73 changes: 52 additions & 21 deletions src/extension/background-script/CryptoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import { geti18nString } from '../../utils/i18n'
import { toCompressSecp256k1Point, unCompressSecp256k1Point } from '../../utils/type-transform/SECP256k1-Compression'
import { Person, getMyPrivateKeyAtFacebook, queryPerson } from '../../database'
import { queryMyIdentityAtDB, storeNewPersonDB, queryPersonDB, queryLocalKeyDB } from '../../database/people'
import { PersonIdentifier } from '../../database/type'
import { PersonIdentifier, PostIdentifier } from '../../database/type'
import { addPersonPublicKey } from '../../key-management/people-gun'
import { gun } from '../../network/gun/version.1'
import { storePostCryptoKeyDB, queryPostCryptoKeyDB } from '../../database/post'

OnlyRunInContext('background', 'EncryptService')
//#region Encrypt & Decrypt
Expand Down Expand Up @@ -120,6 +121,25 @@ export async function decryptFrom(
}
if (data.version === -40) {
const { encryptedText, iv: salt, ownersAESKeyEncrypted, signature, version } = data
const postIdentifier = new PostIdentifier(by, salt.replace(/\//g, '|'))
const unverified = ['2/4', ownersAESKeyEncrypted, salt, encryptedText].join('|')
{
const cachedKey = await queryPostCryptoKeyDB(postIdentifier)
if (cachedKey) {
return {
content: decodeText(
await Alpha40.decryptWithAES({
aesKey: cachedKey.postCryptoKey,
encrypted: encryptedText,
iv: salt,
}),
),
// ! TODO: verify the message again
signatureVerifyResult: true,
}
}
}

async function getKey(user: PersonIdentifier) {
let person = await queryPersonDB(by)
try {
Expand All @@ -136,20 +156,25 @@ export async function decryptFrom(
const mine = await getMyPrivateKeyAtFacebook(whoAmI)
if (!mine) return { error: geti18nString('service_not_setup_yet') }
try {
const unverified = ['2/4', ownersAESKeyEncrypted, salt, encryptedText].join('|')
if (by.equals(whoAmI)) {
const content = decodeText(
await Alpha40.decryptMessage1ToNByMyself({
version: -40,
encryptedAESKey: ownersAESKeyEncrypted,
encryptedContent: encryptedText,
myLocalKey: (await queryLocalKeyDB(whoAmI))!,
iv: salt,
}),
)
const [contentArrayBuffer, postAESKey] = await Alpha40.decryptMessage1ToNByMyself({
version: -40,
encryptedAESKey: ownersAESKeyEncrypted,
encryptedContent: encryptedText,
myLocalKey: (await queryLocalKeyDB(whoAmI))!,
iv: salt,
})
const content = decodeText(contentArrayBuffer)
try {
if (!signature) throw new TypeError('No signature')
const signatureVerifyResult = await Alpha40.verify(unverified, signature, mine.publicKey)
// Store the key to speed up next time decrypt
signatureVerifyResult &&
storePostCryptoKeyDB({
identifier: postIdentifier,
postCryptoKey: postAESKey,
version: -40,
})
return { signatureVerifyResult, content }
} catch {
return { signatureVerifyResult: false, content }
Expand All @@ -165,19 +190,25 @@ export async function decryptFrom(
error: geti18nString('service_not_share_target'),
}
}
const content = decodeText(
await Alpha40.decryptMessage1ToNByOther({
version: -40,
AESKeyEncrypted: aesKeyEncrypted,
authorsPublicKeyECDH: byKey,
encryptedContent: encryptedText,
privateKeyECDH: mine.privateKey,
iv: salt,
}),
)
const [contentArrayBuffer, postAESKey] = await Alpha40.decryptMessage1ToNByOther({
version: -40,
AESKeyEncrypted: aesKeyEncrypted,
authorsPublicKeyECDH: byKey,
encryptedContent: encryptedText,
privateKeyECDH: mine.privateKey,
iv: salt,
})
const content = decodeText(contentArrayBuffer)
try {
if (!signature) throw new TypeError('No signature')
const signatureVerifyResult = await Alpha40.verify(unverified, signature, byKey)
// Store the key to speed up next time decrypt
signatureVerifyResult &&
storePostCryptoKeyDB({
identifier: postIdentifier,
postCryptoKey: postAESKey,
version: -40,
})
return { signatureVerifyResult, content }
} catch {
return { signatureVerifyResult: false, content }
Expand Down
4 changes: 2 additions & 2 deletions src/tests/1toN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async function test1toN(msg: string = 'test string') {
ownersLocalKey: aliceLocal,
})

const aliceDecrypt = await decryptMessage1ToNByMyself({
const [aliceDecrypt] = await decryptMessage1ToNByMyself({
version: -40,
encryptedAESKey: encrypted.ownersAESKeyEncrypted,
encryptedContent: encrypted.encryptedContent,
Expand All @@ -26,7 +26,7 @@ async function test1toN(msg: string = 'test string') {
})
if (decodeText(aliceDecrypt) !== msg) throw new Error('Alice decrypted not equal')

const bobDecrypt = await decryptMessage1ToNByOther({
const [bobDecrypt] = await decryptMessage1ToNByOther({
version: -40,
AESKeyEncrypted: encrypted.othersAESKeyEncrypted.find(x => x.name === 'bob')!.key,
authorsPublicKeyECDH: alice.publicKey,
Expand Down

0 comments on commit bccd455

Please sign in to comment.