Skip to content

Commit

Permalink
update cryptoservice and remove dm service
Browse files Browse the repository at this point in the history
  • Loading branch information
adrastaea committed Nov 25, 2024
1 parent fc8b3e5 commit 1e7aa6e
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 146 deletions.
58 changes: 53 additions & 5 deletions packages/backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@
"yargs": "^17.1.0"
},
"dependencies": {
"@localfirst/auth": "file:../../3rd-party/auth/packages/auth/dist",
"@localfirst/crdx": "file:../../3rd-party/auth/packages/crdx/dist",
"@chainsafe/libp2p-gossipsub": "6.1.0",
"@chainsafe/libp2p-noise": "11.0.0",
"@localfirst/auth": "file:../../3rd-party/auth/packages/auth/dist",
"@localfirst/crdx": "file:../../3rd-party/auth/packages/crdx/dist",
"@nestjs/common": "^10.2.10",
"@nestjs/core": "^10.2.10",
"@nestjs/platform-express": "^10.2.10",
Expand All @@ -100,6 +100,7 @@
"@quiet/logger": "^2.0.2-alpha.0",
"@quiet/types": "^2.0.2-alpha.1",
"abortable-iterator": "^3.0.0",
"bs58": "^6.0.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.1",
"cli-table": "^0.3.6",
Expand All @@ -112,8 +113,8 @@
"express": "^4.17.1",
"fastq": "^1.17.1",
"fetch-retry": "^6.0.0",
"getmac": "^6.6.0",
"get-port": "^5.1.1",
"getmac": "^6.6.0",
"go-ipfs": "npm:[email protected]",
"http-server": "^0.12.3",
"https-proxy-agent": "^5.0.0",
Expand Down Expand Up @@ -144,8 +145,8 @@
"socks-proxy-agent": "^5.0.0",
"string-replace-loader": "3.1.0",
"ts-jest-resolver": "^2.0.0",
"validator": "^13.11.0",
"utf-8-validate": "^5.0.2"
"utf-8-validate": "^5.0.2",
"validator": "^13.11.0"
},
"overrides": {
"level": "$level",
Expand Down
184 changes: 100 additions & 84 deletions packages/backend/src/nest/auth/services/crypto/crypto.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
/**
* Handles invite-related chain operations
*/
import * as bs58 from 'bs58'

import { EncryptedAndSignedPayload, EncryptedPayload, EncryptionScope, EncryptionScopeType } from './types'
import { ChainServiceBase } from '../chainServiceBase'
import { SigChain } from '../../sigchain'
import { Base58, Keyset, KeysetWithSecrets, LocalUserContext, Member, SignedEnvelope } from '@localfirst/auth'
import {
asymmetric,
Base58,
Keyset,
KeysetWithSecrets,
LocalUserContext,
Member,
SignedEnvelope,
} from '@localfirst/auth'
import { DEFAULT_SEARCH_OPTIONS, MemberSearchOptions } from '../members/types'
import { ChannelService } from '../roles/channel.service'
import { createLogger } from '../../../common/logger'
Expand All @@ -28,70 +37,71 @@ class CryptoService extends ChainServiceBase {
})
}

public getKeysForRole(roleName: string, generation?: number): KeysetWithSecrets {
return this.sigChain.team.roleKeys(roleName, generation)
public encryptAndSign(message: any, scope: EncryptionScope, context: LocalUserContext): EncryptedAndSignedPayload {
let encryptedPayload: EncryptedPayload
switch (scope.type) {
// Symmetrical Encryption Types
case EncryptionScopeType.CHANNEL:
case EncryptionScopeType.ROLE:
case EncryptionScopeType.TEAM:
encryptedPayload = this.symEncrypt(message, scope)
break
// Asymmetrical Encryption Types
case EncryptionScopeType.USER:
encryptedPayload = this.asymUserEncrypt(message, scope, context)
break
// Unknown Type
default:
throw new Error(`Unknown encryption type ${scope.type} provided!`)
}

const signature = this.sigChain.team.sign(encryptedPayload.contents)

return {
encrypted: encryptedPayload,
signature,
ts: Date.now(),
username: context.user.userName,
}
}

public getKeysForChannel(channelName: string, generation?: number): KeysetWithSecrets {
return this.getKeysForRole(ChannelService.getPrivateChannelRoleName(channelName), generation)
private symEncrypt(message: any, scope: EncryptionScope): EncryptedPayload {
if (scope.type != EncryptionScopeType.TEAM && scope.name == null) {
throw new Error(`Must provide a scope name when encryption scope is set to ${scope.type}`)
}

const envelope = this.sigChain.team.encrypt(message, scope.name)
return {
contents: bs58.default.encode(envelope.contents) as Base58,
scope: {
...scope,
generation: envelope.recipient.generation,
},
}
}

public encryptAndSign(message: any, scope: EncryptionScope, context: LocalUserContext): EncryptedAndSignedPayload {
let recipientKey: Base58
let senderKey: Base58
let generation: number
if (scope.type === EncryptionScopeType.ROLE) {
if (scope.name == null) {
throw new Error(`Must provide a role name when encryption scope is set to ${scope.type}`)
}
const keys = this.getKeysForRole(scope.name)
recipientKey = keys.encryption.publicKey
senderKey = keys.encryption.secretKey
generation = keys.generation
} else if (scope.type === EncryptionScopeType.CHANNEL) {
if (scope.name == null) {
throw new Error(`Must provide a channel name when encryption scope is set to ${scope.type}`)
}
const keys = this.getKeysForChannel(scope.name)
recipientKey = keys.encryption.publicKey
senderKey = keys.encryption.secretKey
generation = keys.generation
} else if (scope.type === EncryptionScopeType.USER) {
if (scope.name == null) {
throw new Error(`Must provide a user ID when encryption scope is set to ${scope.type}`)
}
const recipientKeys = this.getPublicKeysForMembersById([scope.name])
recipientKey = recipientKeys[0].encryption
senderKey = context.user.keys.encryption.secretKey
generation = recipientKeys[0].generation
} else if (scope.type === EncryptionScopeType.TEAM) {
const keys = this.sigChain.team.teamKeys()
recipientKey = keys.encryption.publicKey
senderKey = keys.encryption.secretKey
generation = keys.generation
} else {
throw new Error(`Unknown encryption scope type ${scope.type}`)
private asymUserEncrypt(message: any, scope: EncryptionScope, context: LocalUserContext): EncryptedPayload {
if (scope.name == null) {
throw new Error(`Must provide a user ID when encryption scope is set to ${scope.type}`)
}

const encryptedContents = SigChain.lfa.asymmetric.encrypt({
const recipientKeys = this.getPublicKeysForMembersById([scope.name])
const recipientKey = recipientKeys[0].encryption
const senderKey = context.user.keys.encryption.secretKey
const generation = recipientKeys[0].generation

const encryptedContents = asymmetric.encrypt({
secret: message,
senderSecretKey: senderKey,
recipientPublicKey: recipientKey,
})

const signature = this.sigChain.team.sign(encryptedContents)

return {
encrypted: {
contents: encryptedContents,
scope: {
...scope,
generation,
},
contents: encryptedContents,
scope: {
...scope,
generation,
},
signature,
ts: Date.now(),
username: context.user.userName,
}
}

Expand All @@ -101,44 +111,50 @@ class CryptoService extends ChainServiceBase {
throw new Error(`Couldn't verify signature on message`)
}

let recipientKey: Base58
let senderKey: Base58
if (encrypted.scope.type === EncryptionScopeType.ROLE) {
if (encrypted.scope.name == null) {
throw new Error(`Must provide a role name when encryption scope is set to ${encrypted.scope.type}`)
}
const keys = this.getKeysForRole(encrypted.scope.name, encrypted.scope.generation)
recipientKey = keys.encryption.secretKey
senderKey = keys.encryption.publicKey
} else if (encrypted.scope.type === EncryptionScopeType.CHANNEL) {
if (encrypted.scope.name == null) {
throw new Error(`Must provide a channel name when encryption scope is set to ${encrypted.scope.type}`)
}
const keys = this.getKeysForChannel(encrypted.scope.name, encrypted.scope.generation)
recipientKey = keys.encryption.secretKey
senderKey = keys.encryption.publicKey
} else if (encrypted.scope.type === EncryptionScopeType.USER) {
if (encrypted.scope.name == null) {
throw new Error(`Must provide a user ID when encryption scope is set to ${encrypted.scope.type}`)
}
const senderKeys = this.sigChain.crypto.getPublicKeysForMembersById([signature.author.name])
recipientKey = context.user.keys.encryption.secretKey
senderKey = senderKeys[0].encryption
} else if (encrypted.scope.type === EncryptionScopeType.TEAM) {
const keys = this.sigChain.team.teamKeys(encrypted.scope.generation)
recipientKey = keys.encryption.publicKey
senderKey = keys.encryption.secretKey
} else {
throw new Error(`Unknown encryption scope type ${encrypted.scope.type}`)
switch (encrypted.scope.type) {
// Symmetrical Encryption Types
case EncryptionScopeType.CHANNEL:
case EncryptionScopeType.ROLE:
case EncryptionScopeType.TEAM:
return this.symDecrypt(encrypted)
// Asymmetrical Encryption Types
case EncryptionScopeType.USER:
return this.asymUserDecrypt(encrypted, signature, context)
// Unknown Type
default:
throw new Error(`Unknown encryption scope type ${encrypted.scope.type}`)
}
}

private symDecrypt(encrypted: EncryptedPayload): any {
if (encrypted.scope.type !== EncryptionScopeType.TEAM && encrypted.scope.name == null) {
throw new Error(`Must provide a scope name when encryption scope is set to ${encrypted.scope.type}`)
}

const decrypted = SigChain.lfa.asymmetric.decrypt({
return this.sigChain.team.decrypt({
contents: bs58.default.decode(encrypted.contents),
recipient: {
...encrypted.scope,
// you don't need a name on the scope when encrypting but you need one for decrypting because of how LFA searches for keys in lockboxes
name: encrypted.scope.type === EncryptionScopeType.TEAM ? EncryptionScopeType.TEAM : encrypted.scope.name!,
},
})
}

private asymUserDecrypt(encrypted: EncryptedPayload, signature: SignedEnvelope, context: LocalUserContext): any {
if (encrypted.scope.name == null) {
throw new Error(`Must provide a user ID when encryption scope is set to ${encrypted.scope.type}`)
}

const senderKeys = this.sigChain.crypto.getPublicKeysForMembersById([signature.author.name])
const recipientKey = context.user.keys.encryption.secretKey
const senderKey = senderKeys[0].encryption

return asymmetric.decrypt({
cipher: encrypted.contents,
senderPublicKey: senderKey,
recipientSecretKey: recipientKey,
})

return decrypted
}
}

Expand Down
Loading

0 comments on commit 1e7aa6e

Please sign in to comment.