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

refactor: application dependency management #2363

Merged
merged 33 commits into from Jul 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
730c44b
internal(wip): keyset revocation
moughxyz Jul 14, 2023
8ed3464
chore: fill
moughxyz Jul 15, 2023
fa83324
chore: fill
moughxyz Jul 15, 2023
4565444
chore: test fill
moughxyz Jul 16, 2023
cd236fb
Merge branch 'main' of github.com:standardnotes/app into internal/key…
moughxyz Jul 17, 2023
00cc844
chore: fill tests and some ui
moughxyz Jul 17, 2023
b083fd2
fix: asymmetric message sorting
moughxyz Jul 18, 2023
86fd95c
chore: update ui
moughxyz Jul 19, 2023
f008449
chore: deleting messages wip
moughxyz Jul 20, 2023
8391f5c
refactor(wip): implicit key revocation
moughxyz Jul 21, 2023
1b55a1a
refactor: usecase refactor
moughxyz Jul 21, 2023
5af9174
chore: lint usecases
moughxyz Jul 22, 2023
7e16a39
feat: dependency manager
moughxyz Jul 22, 2023
ad88dd3
wip: dependency manager
moughxyz Jul 22, 2023
2fd7e7a
refactor: inversify
moughxyz Jul 22, 2023
52ca60c
Revert "refactor: inversify"
moughxyz Jul 22, 2023
1234389
refactor: dynamic creation
moughxyz Jul 22, 2023
641b5c5
chore: lint
moughxyz Jul 22, 2023
b0b3590
chore: passing tests
moughxyz Jul 23, 2023
a0bd9f4
chore: lint web
moughxyz Jul 23, 2023
70073d5
chore: fill types
moughxyz Jul 23, 2023
26ab06c
chore: lint tests
moughxyz Jul 23, 2023
d54dab0
Merge branch 'main' of github.com:standardnotes/app into internal/key…
moughxyz Jul 23, 2023
cc87c1e
chore: lint
moughxyz Jul 23, 2023
32235af
refactor: use event bus for handle application stage
moughxyz Jul 23, 2023
be129d7
chore: lint
moughxyz Jul 23, 2023
847afaf
chore: lint
moughxyz Jul 23, 2023
e0182f4
chore: lint
moughxyz Jul 23, 2023
42c1ba0
chore: lint
moughxyz Jul 23, 2023
299cddd
chore: lint
moughxyz Jul 23, 2023
95c9345
refactor: encryption service
moughxyz Jul 23, 2023
9b17d48
chore: lint
moughxyz Jul 23, 2023
562a95c
chore: lint
moughxyz Jul 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/api/src/Domain/Server/SharedVaultInvites/Paths.ts
Expand Up @@ -13,4 +13,5 @@ export const SharedVaultInvitesPaths = {
`/v1/shared-vaults/${sharedVaultUuid}/invites/${inviteUuid}`,
deleteAllSharedVaultInvites: (sharedVaultUuid: string) => `/v1/shared-vaults/${sharedVaultUuid}/invites`,
deleteAllInboundInvites: '/v1/shared-vaults/invites/inbound',
deleteAllOutboundInvites: '/v1/shared-vaults/invites/outbound',
}
Expand Up @@ -72,4 +72,8 @@ export class SharedVaultInvitesServer implements SharedVaultInvitesServerInterfa
deleteAllInboundInvites(): Promise<HttpResponse<{ success: boolean }>> {
return this.httpService.delete(SharedVaultInvitesPaths.deleteAllInboundInvites)
}

deleteAllOutboundInvites(): Promise<HttpResponse<{ success: boolean }>> {
return this.httpService.delete(SharedVaultInvitesPaths.deleteAllOutboundInvites)
}
}
Expand Up @@ -32,4 +32,5 @@ export interface SharedVaultInvitesServerInterface {
): Promise<HttpResponse<DeleteAllSharedVaultInvitesResponse>>
deleteInvite(params: DeleteInviteRequestParams): Promise<HttpResponse<DeleteInviteResponse>>
deleteAllInboundInvites(): Promise<HttpResponse<{ success: boolean }>>
deleteAllOutboundInvites(): Promise<HttpResponse<{ success: boolean }>>
}
20 changes: 17 additions & 3 deletions packages/encryption/src/Domain/Operator/001/Operator001.ts
Expand Up @@ -13,6 +13,7 @@ import {
KeySystemRootKeyInterface,
RootKeyInterface,
KeySystemRootKeyParamsInterface,
PortablePublicKeySet,
} from '@standardnotes/models'
import { PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { firstHalfOfString, secondHalfOfString, splitString, UuidGenerator } from '@standardnotes/utils'
Expand All @@ -28,11 +29,12 @@ import { ItemAuthenticatedData } from '../../Types/ItemAuthenticatedData'
import { LegacyAttachedData } from '../../Types/LegacyAttachedData'
import { RootKeyEncryptedAuthenticatedData } from '../../Types/RootKeyEncryptedAuthenticatedData'
import { OperatorInterface } from '../OperatorInterface/OperatorInterface'
import { PublicKeySet } from '../Types/PublicKeySet'

import { AsymmetricDecryptResult } from '../Types/AsymmetricDecryptResult'
import { AsymmetricSignatureVerificationDetachedResult } from '../Types/AsymmetricSignatureVerificationDetachedResult'
import { AsyncOperatorInterface } from '../OperatorInterface/AsyncOperatorInterface'
import { ContentType } from '@standardnotes/domain-core'
import { ContentType, Result } from '@standardnotes/domain-core'
import { AsymmetricItemAdditionalData } from '../../Types/EncryptionAdditionalData'

const NO_IV = '00000000000000000000000000000000'

Expand Down Expand Up @@ -272,11 +274,23 @@ export class SNProtocolOperator001 implements OperatorInterface, AsyncOperatorIn
throw new Error('Method not implemented.')
}

asymmetricDecryptOwnMessage(_dto: {
message: string
ownPrivateKey: string
recipientPublicKey: string
}): Result<AsymmetricDecryptResult> {
throw new Error('Method not implemented.')
}

asymmetricSignatureVerifyDetached(_encryptedString: string): AsymmetricSignatureVerificationDetachedResult {
throw new Error('Method not implemented.')
}

getSenderPublicKeySetFromAsymmetricallyEncryptedString(_string: string): PublicKeySet {
asymmetricStringGetAdditionalData(_dto: { encryptedString: string }): Result<AsymmetricItemAdditionalData> {
throw new Error('Method not implemented.')
}

getSenderPublicKeySetFromAsymmetricallyEncryptedString(_string: string): PortablePublicKeySet {
throw new Error('Method not implemented.')
}
}
36 changes: 27 additions & 9 deletions packages/encryption/src/Domain/Operator/004/Operator004.ts
Expand Up @@ -12,6 +12,7 @@ import {
KeySystemIdentifier,
RootKeyInterface,
KeySystemRootKeyParamsInterface,
PortablePublicKeySet,
} from '@standardnotes/models'
import { KeyParamsOrigination, ProtocolVersion } from '@standardnotes/common'
import { HexString, PkcKeyPair, PureCryptoInterface, Utf8String } from '@standardnotes/sncrypto-common'
Expand All @@ -30,9 +31,9 @@ import { OperatorInterface } from '../OperatorInterface/OperatorInterface'
import { AsymmetricallyEncryptedString } from '../Types/Types'
import { AsymmetricItemAdditionalData } from '../../Types/EncryptionAdditionalData'
import { V004AsymmetricStringComponents } from './V004AlgorithmTypes'
import { AsymmetricEncryptUseCase } from './UseCase/Asymmetric/AsymmetricEncrypt'
import { AsymmetricEncrypt004 } from './UseCase/Asymmetric/AsymmetricEncrypt'
import { ParseConsistentBase64JsonPayloadUseCase } from './UseCase/Utils/ParseConsistentBase64JsonPayload'
import { AsymmetricDecryptUseCase } from './UseCase/Asymmetric/AsymmetricDecrypt'
import { AsymmetricDecrypt004 } from './UseCase/Asymmetric/AsymmetricDecrypt'
import { GenerateDecryptedParametersUseCase } from './UseCase/Symmetric/GenerateDecryptedParameters'
import { GenerateEncryptedParametersUseCase } from './UseCase/Symmetric/GenerateEncryptedParameters'
import { DeriveRootKeyUseCase } from './UseCase/RootKey/DeriveRootKey'
Expand All @@ -41,14 +42,15 @@ import { CreateRootKeyUseCase } from './UseCase/RootKey/CreateRootKey'
import { UuidGenerator } from '@standardnotes/utils'
import { CreateKeySystemItemsKeyUseCase } from './UseCase/KeySystem/CreateKeySystemItemsKey'
import { AsymmetricDecryptResult } from '../Types/AsymmetricDecryptResult'
import { PublicKeySet } from '../Types/PublicKeySet'
import { CreateRandomKeySystemRootKey } from './UseCase/KeySystem/CreateRandomKeySystemRootKey'
import { CreateUserInputKeySystemRootKey } from './UseCase/KeySystem/CreateUserInputKeySystemRootKey'
import { AsymmetricSignatureVerificationDetachedResult } from '../Types/AsymmetricSignatureVerificationDetachedResult'
import { AsymmetricSignatureVerificationDetachedUseCase } from './UseCase/Asymmetric/AsymmetricSignatureVerificationDetached'
import { AsymmetricSignatureVerificationDetached004 } from './UseCase/Asymmetric/AsymmetricSignatureVerificationDetached'
import { DeriveKeySystemRootKeyUseCase } from './UseCase/KeySystem/DeriveKeySystemRootKey'
import { SyncOperatorInterface } from '../OperatorInterface/SyncOperatorInterface'
import { ContentType } from '@standardnotes/domain-core'
import { ContentType, Result } from '@standardnotes/domain-core'
import { AsymmetricStringGetAdditionalData004 } from './UseCase/Asymmetric/AsymmetricStringGetAdditionalData'
import { AsymmetricDecryptOwnMessage004 } from './UseCase/Asymmetric/AsymmetricDecryptOwnMessage'

export class SNProtocolOperator004 implements OperatorInterface, SyncOperatorInterface {
constructor(protected readonly crypto: PureCryptoInterface) {}
Expand Down Expand Up @@ -167,26 +169,42 @@ export class SNProtocolOperator004 implements OperatorInterface, SyncOperatorInt
senderSigningKeyPair: PkcKeyPair
recipientPublicKey: HexString
}): AsymmetricallyEncryptedString {
const usecase = new AsymmetricEncryptUseCase(this.crypto)
const usecase = new AsymmetricEncrypt004(this.crypto)
return usecase.execute(dto)
}

asymmetricDecrypt(dto: {
stringToDecrypt: AsymmetricallyEncryptedString
recipientSecretKey: HexString
}): AsymmetricDecryptResult | null {
const usecase = new AsymmetricDecryptUseCase(this.crypto)
const usecase = new AsymmetricDecrypt004(this.crypto)
return usecase.execute(dto)
}

asymmetricDecryptOwnMessage(dto: {
message: AsymmetricallyEncryptedString
ownPrivateKey: HexString
recipientPublicKey: HexString
}): Result<AsymmetricDecryptResult> {
const usecase = new AsymmetricDecryptOwnMessage004(this.crypto)
return usecase.execute(dto)
}

asymmetricSignatureVerifyDetached(
encryptedString: AsymmetricallyEncryptedString,
): AsymmetricSignatureVerificationDetachedResult {
const usecase = new AsymmetricSignatureVerificationDetachedUseCase(this.crypto)
const usecase = new AsymmetricSignatureVerificationDetached004(this.crypto)
return usecase.execute({ encryptedString })
}

getSenderPublicKeySetFromAsymmetricallyEncryptedString(string: AsymmetricallyEncryptedString): PublicKeySet {
asymmetricStringGetAdditionalData(dto: {
encryptedString: AsymmetricallyEncryptedString
}): Result<AsymmetricItemAdditionalData> {
const usecase = new AsymmetricStringGetAdditionalData004(this.crypto)
return usecase.execute(dto)
}

getSenderPublicKeySetFromAsymmetricallyEncryptedString(string: AsymmetricallyEncryptedString): PortablePublicKeySet {
const [_, __, ___, additionalDataString] = <V004AsymmetricStringComponents>string.split(':')
const parseBase64Usecase = new ParseConsistentBase64JsonPayloadUseCase(this.crypto)
const additionalData = parseBase64Usecase.execute<AsymmetricItemAdditionalData>(additionalDataString)
Expand Down
@@ -1,27 +1,27 @@
import { PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { getMockedCrypto } from '../../MockedCrypto'
import { AsymmetricDecryptUseCase } from './AsymmetricDecrypt'
import { AsymmetricEncryptUseCase } from './AsymmetricEncrypt'
import { AsymmetricDecrypt004 } from './AsymmetricDecrypt'
import { AsymmetricEncrypt004 } from './AsymmetricEncrypt'
import { V004AsymmetricStringComponents } from '../../V004AlgorithmTypes'
import { AsymmetricItemAdditionalData } from '../../../../Types/EncryptionAdditionalData'

describe('asymmetric decrypt use case', () => {
let crypto: PureCryptoInterface
let usecase: AsymmetricDecryptUseCase
let usecase: AsymmetricDecrypt004
let recipientKeyPair: PkcKeyPair
let senderKeyPair: PkcKeyPair
let senderSigningKeyPair: PkcKeyPair

beforeEach(() => {
crypto = getMockedCrypto()
usecase = new AsymmetricDecryptUseCase(crypto)
usecase = new AsymmetricDecrypt004(crypto)
recipientKeyPair = crypto.sodiumCryptoBoxSeedKeypair('recipient-seedling')
senderKeyPair = crypto.sodiumCryptoBoxSeedKeypair('sender-seedling')
senderSigningKeyPair = crypto.sodiumCryptoSignSeedKeypair('sender-signing-seedling')
})

const getEncryptedString = () => {
const encryptUsecase = new AsymmetricEncryptUseCase(crypto)
const encryptUsecase = new AsymmetricEncrypt004(crypto)

const result = encryptUsecase.execute({
stringToEncrypt: 'foobar',
Expand Down
Expand Up @@ -5,7 +5,7 @@ import { ParseConsistentBase64JsonPayloadUseCase } from '../Utils/ParseConsisten
import { AsymmetricItemAdditionalData } from '../../../../Types/EncryptionAdditionalData'
import { AsymmetricDecryptResult } from '../../../Types/AsymmetricDecryptResult'

export class AsymmetricDecryptUseCase {
export class AsymmetricDecrypt004 {
private parseBase64Usecase = new ParseConsistentBase64JsonPayloadUseCase(this.crypto)

constructor(private readonly crypto: PureCryptoInterface) {}
Expand Down
@@ -0,0 +1,51 @@
import { HexString, PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { AsymmetricallyEncryptedString } from '../../../Types/Types'
import { V004AsymmetricStringComponents } from '../../V004AlgorithmTypes'
import { ParseConsistentBase64JsonPayloadUseCase } from '../Utils/ParseConsistentBase64JsonPayload'
import { AsymmetricItemAdditionalData } from '../../../../Types/EncryptionAdditionalData'
import { AsymmetricDecryptResult } from '../../../Types/AsymmetricDecryptResult'
import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core'

export class AsymmetricDecryptOwnMessage004 implements SyncUseCaseInterface<AsymmetricDecryptResult> {
private parseBase64Usecase = new ParseConsistentBase64JsonPayloadUseCase(this.crypto)

constructor(private readonly crypto: PureCryptoInterface) {}

execute(dto: {
message: AsymmetricallyEncryptedString
ownPrivateKey: HexString
recipientPublicKey: HexString
}): Result<AsymmetricDecryptResult> {
const [_, nonce, ciphertext, additionalDataString] = <V004AsymmetricStringComponents>dto.message.split(':')

const additionalData = this.parseBase64Usecase.execute<AsymmetricItemAdditionalData>(additionalDataString)

try {
const plaintext = this.crypto.sodiumCryptoBoxEasyDecrypt(
ciphertext,
nonce,
dto.recipientPublicKey,
dto.ownPrivateKey,
)

if (!plaintext) {
return Result.fail('Could not decrypt message')
}

const signatureVerified = this.crypto.sodiumCryptoSignVerify(
ciphertext,
additionalData.signingData.signature,
additionalData.signingData.publicKey,
)

return Result.ok({
plaintext,
signatureVerified,
signaturePublicKey: additionalData.signingData.publicKey,
senderPublicKey: additionalData.senderPublicKey,
})
} catch (error) {
return Result.fail('Could not decrypt message')
}
}
}
@@ -1,20 +1,20 @@
import { PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { getMockedCrypto } from '../../MockedCrypto'
import { AsymmetricEncryptUseCase } from './AsymmetricEncrypt'
import { AsymmetricEncrypt004 } from './AsymmetricEncrypt'
import { V004AsymmetricStringComponents } from '../../V004AlgorithmTypes'
import { ParseConsistentBase64JsonPayloadUseCase } from '../Utils/ParseConsistentBase64JsonPayload'
import { AsymmetricItemAdditionalData } from '../../../../Types/EncryptionAdditionalData'

describe('asymmetric encrypt use case', () => {
let crypto: PureCryptoInterface
let usecase: AsymmetricEncryptUseCase
let usecase: AsymmetricEncrypt004
let encryptionKeyPair: PkcKeyPair
let signingKeyPair: PkcKeyPair
let parseBase64Usecase: ParseConsistentBase64JsonPayloadUseCase

beforeEach(() => {
crypto = getMockedCrypto()
usecase = new AsymmetricEncryptUseCase(crypto)
usecase = new AsymmetricEncrypt004(crypto)
encryptionKeyPair = crypto.sodiumCryptoBoxSeedKeypair('seedling')
signingKeyPair = crypto.sodiumCryptoSignSeedKeypair('seedling')
parseBase64Usecase = new ParseConsistentBase64JsonPayloadUseCase(crypto)
Expand Down
Expand Up @@ -5,7 +5,7 @@ import { V004AsymmetricCiphertextPrefix, V004AsymmetricStringComponents } from '
import { CreateConsistentBase64JsonPayloadUseCase } from '../Utils/CreateConsistentBase64JsonPayload'
import { AsymmetricItemAdditionalData } from '../../../../Types/EncryptionAdditionalData'

export class AsymmetricEncryptUseCase {
export class AsymmetricEncrypt004 {
private base64DataUsecase = new CreateConsistentBase64JsonPayloadUseCase(this.crypto)

constructor(private readonly crypto: PureCryptoInterface) {}
Expand All @@ -21,8 +21,8 @@ export class AsymmetricEncryptUseCase {
const ciphertext = this.crypto.sodiumCryptoBoxEasyEncrypt(
dto.stringToEncrypt,
nonce,
dto.senderKeyPair.privateKey,
dto.recipientPublicKey,
dto.senderKeyPair.privateKey,
)

const additionalData: AsymmetricItemAdditionalData = {
Expand Down
Expand Up @@ -5,7 +5,7 @@ import { ParseConsistentBase64JsonPayloadUseCase } from '../Utils/ParseConsisten
import { AsymmetricItemAdditionalData } from '../../../../Types/EncryptionAdditionalData'
import { AsymmetricSignatureVerificationDetachedResult } from '../../../Types/AsymmetricSignatureVerificationDetachedResult'

export class AsymmetricSignatureVerificationDetachedUseCase {
export class AsymmetricSignatureVerificationDetached004 {
private parseBase64Usecase = new ParseConsistentBase64JsonPayloadUseCase(this.crypto)

constructor(private readonly crypto: PureCryptoInterface) {}
Expand Down
@@ -0,0 +1,20 @@
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { AsymmetricallyEncryptedString } from '../../../Types/Types'
import { V004AsymmetricStringComponents } from '../../V004AlgorithmTypes'
import { ParseConsistentBase64JsonPayloadUseCase } from '../Utils/ParseConsistentBase64JsonPayload'
import { AsymmetricItemAdditionalData } from '../../../../Types/EncryptionAdditionalData'
import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core'

export class AsymmetricStringGetAdditionalData004 implements SyncUseCaseInterface<AsymmetricItemAdditionalData> {
private parseBase64Usecase = new ParseConsistentBase64JsonPayloadUseCase(this.crypto)

constructor(private readonly crypto: PureCryptoInterface) {}

execute(dto: { encryptedString: AsymmetricallyEncryptedString }): Result<AsymmetricItemAdditionalData> {
const [_, __, ___, additionalDataString] = <V004AsymmetricStringComponents>dto.encryptedString.split(':')

const additionalData = this.parseBase64Usecase.execute<AsymmetricItemAdditionalData>(additionalDataString)

return Result.ok(additionalData)
}
}
Expand Up @@ -2,8 +2,9 @@ import { ProtocolVersion, ProtocolVersionLatest } from '@standardnotes/common'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { createOperatorForVersion } from './Functions'
import { AnyOperatorInterface } from './OperatorInterface/TypeCheck'
import { EncryptionOperatorsInterface } from './EncryptionOperatorsInterface'

export class OperatorManager {
export class EncryptionOperators implements EncryptionOperatorsInterface {
private operators: Record<string, AnyOperatorInterface> = {}

constructor(private crypto: PureCryptoInterface) {
Expand Down
@@ -0,0 +1,8 @@
import { ProtocolVersion } from '@standardnotes/common'
import { AnyOperatorInterface } from './OperatorInterface/TypeCheck'

export interface EncryptionOperatorsInterface {
operatorForVersion(version: ProtocolVersion): AnyOperatorInterface
defaultOperator(): AnyOperatorInterface
deinit(): void
}
Expand Up @@ -6,6 +6,7 @@ import {
KeySystemRootKeyInterface,
KeySystemIdentifier,
KeySystemRootKeyParamsInterface,
PortablePublicKeySet,
} from '@standardnotes/models'
import { SNRootKeyParams } from '../../Keys/RootKey/RootKeyParams'
import { EncryptedOutputParameters } from '../../Types/EncryptedParameters'
Expand All @@ -15,8 +16,9 @@ import { RootKeyEncryptedAuthenticatedData } from '../../Types/RootKeyEncryptedA
import { HexString, PkcKeyPair } from '@standardnotes/sncrypto-common'
import { AsymmetricallyEncryptedString } from '../Types/Types'
import { AsymmetricDecryptResult } from '../Types/AsymmetricDecryptResult'
import { PublicKeySet } from '../Types/PublicKeySet'
import { AsymmetricSignatureVerificationDetachedResult } from '../Types/AsymmetricSignatureVerificationDetachedResult'
import { AsymmetricItemAdditionalData } from '../../Types/EncryptionAdditionalData'
import { Result } from '@standardnotes/domain-core'

/**w
* An operator is responsible for performing crypto operations, such as generating keys
Expand Down Expand Up @@ -92,11 +94,21 @@ export interface OperatorInterface {
recipientSecretKey: HexString
}): AsymmetricDecryptResult | null

asymmetricDecryptOwnMessage(dto: {
message: AsymmetricallyEncryptedString
ownPrivateKey: HexString
recipientPublicKey: HexString
}): Result<AsymmetricDecryptResult>

asymmetricSignatureVerifyDetached(
encryptedString: AsymmetricallyEncryptedString,
): AsymmetricSignatureVerificationDetachedResult

getSenderPublicKeySetFromAsymmetricallyEncryptedString(string: AsymmetricallyEncryptedString): PublicKeySet
asymmetricStringGetAdditionalData(dto: {
encryptedString: AsymmetricallyEncryptedString
}): Result<AsymmetricItemAdditionalData>

getSenderPublicKeySetFromAsymmetricallyEncryptedString(string: AsymmetricallyEncryptedString): PortablePublicKeySet

versionForAsymmetricallyEncryptedString(encryptedString: string): ProtocolVersion
}