Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Signatures and encryption: Preliminary work #1257

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ebe6ee0
Signatures and encryption: Preliminary work
corrideat May 1, 2022
05976eb
Fix typo
corrideat May 1, 2022
c690fe3
Updated tests, added key ops, added keys to contracts
corrideat May 15, 2022
93274b3
New OP_KEYSHARE
corrideat Jun 5, 2022
b1e3763
Merge branch 'master' into feature/password-state-new
corrideat Jun 5, 2022
0e366f7
Broken changes
corrideat Jun 19, 2022
94a7601
ZKPP password salt
corrideat Jul 28, 2022
e9e3851
ZKPP: Frontend implementation
corrideat Aug 8, 2022
c6802d4
Merge branch 'master' into feature/password-state-new
corrideat Aug 15, 2022
1051639
Prevent Grunt from running
corrideat Aug 15, 2022
e86df63
OP_KEY_REQUEST
corrideat Aug 22, 2022
158b35d
Feedback on ZKPP and started moving invites into Chelonia
corrideat Sep 12, 2022
c6b0dfb
Error handling
corrideat Sep 19, 2022
742902e
Implemented OP_KEY_REQUEST
corrideat Sep 19, 2022
f2812fe
Bugfixes
corrideat Sep 26, 2022
55d126a
Merge branch 'master' into feature/password-state-new
corrideat Oct 10, 2022
750703b
Group joining (broken)
corrideat Oct 10, 2022
096f016
Internals: group joining
corrideat Oct 24, 2022
03bd885
Merge branch 'master' into feature/password-state-new
corrideat Oct 24, 2022
579474c
Invite link state, some bugfixes
corrideat Oct 31, 2022
64e34d3
- Implement feedback from PR
corrideat Nov 7, 2022
b44dcb2
Updates: better approach to withEnv as suggestion or code + Enforce m…
corrideat Nov 14, 2022
42df852
Bugfixes: login, group joining
corrideat Jan 9, 2023
ce5223e
Functionality for joining chat
corrideat Jan 16, 2023
2f70afa
State management: support chat
corrideat Jan 23, 2023
8fa39c1
Bugfixes and PoC for tests
corrideat Jan 30, 2023
a6a3ebd
Merge branch 'master' into feature/password-state-new
corrideat Jan 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
.*/frontend/assets/.*
.*/frontend/controller/service-worker.js
.*/frontend/utils/blockies.js
.*/frontend/utils/crypto.js
#.*/frontend/utils/crypto.js
corrideat marked this conversation as resolved.
Show resolved Hide resolved
.*/frontend/utils/flowTyper.js
.*/frontend/utils/vuexQueue.js
.*/historical/.*
Expand Down
2 changes: 1 addition & 1 deletion backend/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default (sbp('sbp/selectors/register', {
const json = `"${strToB64(entry.serialize())}"`
if (currentHEAD !== hash) {
this.push(prefix + json)
currentHEAD = entry.message().previousHEAD
currentHEAD = entry.head().previousHEAD
prefix = ','
} else {
this.push(prefix + json + ']')
Expand Down
70 changes: 68 additions & 2 deletions frontend/controller/actions/chatroom.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,84 @@
'use strict'
import sbp from '@sbp/sbp'
import { CURVE25519XSALSA20POLY1305, EDWARDS25519SHA512BATCH, keyId, keygen, serializeKey, encrypt } from '~/shared/domains/chelonia/crypto.js'
import L from '@view-utils/translations.js'
import { GIErrorUIRuntimeError } from '@model/errors.js'
import { omit } from '~/frontend/utils/giLodash.js'
import { encryptedAction } from './utils.js'
import { GIMessage } from '~/shared/domains/chelonia/GIMessage.js'
import type { GIRegParams } from './types.js'

export default (sbp('sbp/selectors/register', {
'gi.actions/chatroom/create': async function (params: GIRegParams) {
try {
return await sbp('chelonia/out/registerContract', {
// Create the necessary keys to initialise the contract
// eslint-disable-next-line camelcase
const CSK = keygen(EDWARDS25519SHA512BATCH)
const CEK = keygen(CURVE25519XSALSA20POLY1305)

// Key IDs
const CSKid = keyId(CSK)
const CEKid = keyId(CEK)

// Public keys to be stored in the contract
const CSKp = serializeKey(CSK, false)
const CEKp = serializeKey(CEK, false)

// Secret keys to be stored encrypted in the contract
const CSKs = encrypt(CEK, serializeKey(CSK, true))
const CEKs = encrypt(CEK, serializeKey(CEK, true))

const rootState = sbp('state/vuex/state')

const chatroom = await sbp('chelonia/with-env', '', {
additionalKeys: {
[CSKid]: CSK,
[CEKid]: CEK
}
}, ['chelonia/out/registerContract', {
...omit(params, ['options']), // any 'options' are for this action, not for Chelonia
signingKeyId: CSKid,
actionSigningKeyId: CSKid,
actionEncryptionKeyId: CEKid,
keys: [
{
id: CSKid,
type: CSK.type,
data: CSKp,
permissions: [GIMessage.OP_CONTRACT, GIMessage.OP_KEY_ADD, GIMessage.OP_KEY_DEL, GIMessage.OP_ACTION_UNENCRYPTED, GIMessage.OP_ACTION_ENCRYPTED, GIMessage.OP_ATOMIC, GIMessage.OP_CONTRACT_AUTH, GIMessage.OP_CONTRACT_DEAUTH],
meta: {
type: 'csk',
private: {
keyId: CEKid,
content: CSKs
}
}
},
{
id: CEKid,
type: CEK.type,
data: CEKp,
permissions: [GIMessage.OP_ACTION_ENCRYPTED],
meta: {
type: 'cek',
private: {
keyId: CEKid,
content: CEKs
}
}
}
],
contractName: 'gi.contracts/chatroom'
})
}])

const contractID = chatroom.contractID()

await sbp('chelonia/with-env', contractID, { additionalKeys: { [CEKid]: CEK } }, ['chelonia/contract/sync', contractID])

const userID = rootState.loggedIn.identityContractID
await sbp('gi.actions/identity/shareKeysWithSelf', { userID, contractID })

return chatroom
} catch (e) {
console.error('gi.actions/chatroom/register failed!', e)
throw new GIErrorUIRuntimeError(L('Failed to create chat channel.'))
Expand Down
79 changes: 71 additions & 8 deletions frontend/controller/actions/group.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict'

import sbp from '@sbp/sbp'
import { CURVE25519XSALSA20POLY1305, EDWARDS25519SHA512BATCH, keyId, keygen, serializeKey, encrypt } from '~/shared/domains/chelonia/crypto.js'
import { createInvite } from '@model/contracts/group.js'
import {
INVITE_INITIAL_CREATOR,
Expand Down Expand Up @@ -80,6 +81,25 @@ export default (sbp('sbp/selectors/register', {
}
}

// Create the necessary keys to initialise the contract
// eslint-disable-next-line camelcase
const CSK = keygen(EDWARDS25519SHA512BATCH)
const CEK = keygen(CURVE25519XSALSA20POLY1305)

// Key IDs
const CSKid = keyId(CSK)
const CEKid = keyId(CEK)

// Public keys to be stored in the contract
const CSKp = serializeKey(CSK, false)
const CEKp = serializeKey(CEK, false)

// Secret keys to be stored encrypted in the contract
const CSKs = encrypt(CEK, serializeKey(CSK, true))
const CEKs = encrypt(CEK, serializeKey(CEK, true))

const rootState = sbp('state/vuex/state')

try {
const initialInvite = createInvite({ quantity: 60, creator: INVITE_INITIAL_CREATOR })
const proposalSettings = {
Expand All @@ -97,9 +117,45 @@ export default (sbp('sbp/selectors/register', {
// handle Flowtype annotations, even though our .babelrc should make it work.
distributionDate = dateToPeriodStamp(addTimeToDate(new Date(), 3 * DAYS_MILLIS))
}
const message = await sbp('chelonia/out/registerContract', {
const message = await sbp('chelonia/with-env', '', {
additionalKeys: {
[CSKid]: CSK,
[CEKid]: CEK
}
}, ['chelonia/out/registerContract', {
contractName: 'gi.contracts/group',
publishOptions,
signingKeyId: CSKid,
actionSigningKeyId: CSKid,
actionEncryptionKeyId: CEKid,
keys: [
{
id: CSKid,
type: CSK.type,
data: CSKp,
permissions: [GIMessage.OP_CONTRACT, GIMessage.OP_KEY_ADD, GIMessage.OP_KEY_DEL, GIMessage.OP_ACTION_UNENCRYPTED, GIMessage.OP_ACTION_ENCRYPTED, GIMessage.OP_ATOMIC, GIMessage.OP_CONTRACT_AUTH, GIMessage.OP_CONTRACT_DEAUTH],
meta: {
type: 'csk',
private: {
keyId: CEKid,
content: CSKs
}
}
},
{
id: CEKid,
type: CEK.type,
data: CEKp,
permissions: [GIMessage.OP_ACTION_ENCRYPTED, GIMessage.OP_KEYSHARE],
meta: {
type: 'cek',
private: {
keyId: CEKid,
content: CEKs
}
}
}
],
data: {
invites: {
[initialInvite.inviteSecret]: initialInvite
Expand Down Expand Up @@ -137,23 +193,30 @@ export default (sbp('sbp/selectors/register', {
}
}
}
})
}])

const contractID = message.contractID()

await sbp('chelonia/contract/sync', message.contractID())
saveLoginState('creating', message.contractID())
await sbp('chelonia/with-env', contractID, { additionalKeys: { [CEKid]: CEK } }, ['chelonia/contract/sync', contractID])
saveLoginState('creating', contractID)

// create a 'General' chatroom contract and let the creator join
await sbp('gi.actions/group/addAndJoinChatRoom', {
contractID: message.contractID(),
await sbp('chelonia/with-env', contractID, { additionalKeys: { [CEKid]: CEK } }, ['gi.actions/group/addAndJoinChatRoom', {
contractID,
data: {
attributes: {
name: CHATROOM_GENERAL_NAME,
type: CHATROOM_TYPES.GROUP,
description: '',
privacyLevel: CHATROOM_PRIVACY_LEVEL.GROUP
}
}
})
},
signingKeyId: CSKid,
encryptionKeyId: CEKid
}])

const userID = rootState.loggedIn.identityContractID
await sbp('gi.actions/identity/shareKeysWithSelf', { userID, contractID })

return message
} catch (e) {
Expand Down
Loading