Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions packages/sdk/src/StreamrClientError.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { MessageID } from './protocol/MessageID'

export type StreamrClientErrorCode =
'STREAM_NOT_FOUND' |
'NODE_NOT_FOUND' |
Expand All @@ -8,6 +10,7 @@ export type StreamrClientErrorCode =
'PIPELINE_ERROR' |
'UNSUPPORTED_OPERATION' |
'INVALID_STREAM_METADATA' |
'DECRYPT_ERROR' |
'STORAGE_NODE_ERROR' |
'UNKNOWN_ERROR'

Expand All @@ -21,3 +24,7 @@ export class StreamrClientError extends Error {
this.name = this.constructor.name
}
}

export const formMessageIdDescription = (messageId: MessageID): string => {
return JSON.stringify(messageId)
}
17 changes: 7 additions & 10 deletions packages/sdk/src/encryption/EncryptionUtil.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import crypto, { CipherKey } from 'crypto'
import { StreamMessage, StreamMessageAESEncrypted } from '../protocol/StreamMessage'
import { StreamMessageError } from '../protocol/StreamMessageError'
import { GroupKey } from './GroupKey'
import { formMessageIdDescription, StreamrClientError } from '../StreamrClientError'

export class DecryptError extends StreamMessageError {
constructor(streamMessage: StreamMessage, message = '') {
super(`Decrypt error: ${message}`, streamMessage)
}
export const createDecryptError = (message: string, streamMessage: StreamMessage): StreamrClientError => {
return new StreamrClientError(`${message} (messageId=${formMessageIdDescription(streamMessage.messageId)})`, 'DECRYPT_ERROR')
}

export const INITIALIZATION_VECTOR_LENGTH = 16
Expand Down Expand Up @@ -53,17 +51,16 @@ export class EncryptionUtil {
let content: Uint8Array
try {
content = this.decryptWithAES(streamMessage.content, groupKey.data)
} catch (err) {
throw new DecryptError(streamMessage, err.stack)
} catch {
throw createDecryptError('AES decryption failed', streamMessage)
}

let newGroupKey: GroupKey | undefined = undefined
if (streamMessage.newGroupKey) {
try {
newGroupKey = groupKey.decryptNextGroupKey(streamMessage.newGroupKey)
} catch (err) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
throw new DecryptError(streamMessage, `Could not decrypt new group key: ${err.stack}`)
} catch {
throw createDecryptError('Could not decrypt new encryption key', streamMessage)
}
}

Expand Down
7 changes: 3 additions & 4 deletions packages/sdk/src/encryption/decrypt.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DestroySignal } from '../DestroySignal'
import { DecryptError, EncryptionUtil } from '../encryption/EncryptionUtil'
import { createDecryptError, EncryptionUtil } from '../encryption/EncryptionUtil'
import { GroupKey } from '../encryption/GroupKey'
import { GroupKeyManager } from '../encryption/GroupKeyManager'
import { EncryptionType, StreamMessage, StreamMessageAESEncrypted } from '../protocol/StreamMessage'
Expand All @@ -22,12 +22,11 @@ export const decrypt = async (
streamMessage.groupKeyId,
streamMessage.getPublisherId()
)
} catch (e: any) {
} catch {
if (destroySignal.isDestroyed()) {
return streamMessage
}
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
throw new DecryptError(streamMessage, `Could not get GroupKey ${streamMessage.groupKeyId}: ${e.message}`)
throw createDecryptError(`Could not get encryption key ${streamMessage.groupKeyId}`, streamMessage)
}
if (destroySignal.isDestroyed()) {
return streamMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { fastWallet } from '@streamr/test-utils'
import { collect, toEthereumAddress, toStreamID, toUserId } from '@streamr/utils'
import { Stream } from '../../src/Stream'
import { StreamrClient } from '../../src/StreamrClient'
import { DecryptError } from '../../src/encryption/EncryptionUtil'
import { GroupKey } from '../../src/encryption/GroupKey'
import { StreamPermission } from '../../src/permission'
import { FakeEnvironment } from '../test-utils/fake/FakeEnvironment'
import { FakeStorageNode } from '../test-utils/fake/FakeStorageNode'
import { createMockMessage, createRelativeTestStreamId, getLocalGroupKeyStore } from '../test-utils/utils'
import { StreamrClientError } from '../../src/StreamrClientError'

/*
* A subscriber has some GroupKeys in the local store and reads historical data
Expand Down Expand Up @@ -68,7 +68,8 @@ describe('resend with existing key', () => {
await collect(messageStream)
expect(onError).toBeCalled()
const error = onError.mock.calls[0][0]
expect(error).toBeInstanceOf(DecryptError)
expect(error).toBeInstanceOf(StreamrClientError)
expect(error.code).toBe('DECRYPT_ERROR')
}

beforeEach(async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/test/integration/revoke-permissions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe('revoke permissions', () => {
break
}
}
}).rejects.toThrow(/not a subscriber|Could not get GroupKey/)
}).rejects.toThrow(/not a subscriber|Could not get encryption key/)
} finally {
clearTimeout(t)
// run in finally to ensure publish promise finishes before
Expand Down
5 changes: 3 additions & 2 deletions packages/sdk/test/integration/update-encryption-key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import 'reflect-metadata'

import { StreamPartID, StreamPartIDUtils, until } from '@streamr/utils'
import { Message } from '../../src/Message'
import { DecryptError } from '../../src/encryption/EncryptionUtil'
import { GroupKey } from '../../src/encryption/GroupKey'
import { StreamPermission } from '../../src/permission'
import { nextValue } from '../../src/utils/iterators'
import { StreamrClient } from './../../src/StreamrClient'
import { FakeEnvironment } from './../test-utils/fake/FakeEnvironment'
import { StreamrClientError } from '../../src/StreamrClientError'

/*
* Subscriber has subscribed to a stream, and the publisher updates the encryption key for that stream.
Expand Down Expand Up @@ -161,7 +161,8 @@ describe('update encryption key', () => {
mockId: 2
})
await until(() => onError.mock.calls.length > 0, 10 * 1000)
expect(onError.mock.calls[0][0]).toBeInstanceOf(DecryptError)
expect(onError.mock.calls[0][0]).toBeInstanceOf(StreamrClientError)
expect(onError.mock.calls[0][0].code).toBe('DECRYPT_ERROR')
}, 10 * 1000)
})
})
6 changes: 5 additions & 1 deletion packages/sdk/test/unit/Decrypt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { GroupKeyManager } from '../../src/encryption/GroupKeyManager'
import { decrypt } from '../../src/encryption/decrypt'
import { createGroupKeyManager, createMockMessage } from '../test-utils/utils'
import { EncryptionType, StreamMessage, StreamMessageAESEncrypted } from './../../src/protocol/StreamMessage'
import { formMessageIdDescription } from '../../src/StreamrClientError'

describe('Decrypt', () => {

Expand Down Expand Up @@ -54,6 +55,9 @@ describe('Decrypt', () => {
msg as StreamMessageAESEncrypted,
groupKeyManager,
destroySignal)
}).rejects.toThrow(`Decrypt error: Could not get GroupKey ${groupKey.id}`)
}).rejects.toThrowStreamrError({
code: 'DECRYPT_ERROR',
message: `Could not get encryption key ${groupKey.id} (messageId=${formMessageIdDescription(msg.messageId)})`
})
})
})
6 changes: 5 additions & 1 deletion packages/sdk/test/unit/EncryptionUtil.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { GroupKey } from '../../src/encryption/GroupKey'
import { createMockMessage } from '../test-utils/utils'
import { EncryptedGroupKey } from './../../src/protocol/EncryptedGroupKey'
import { StreamMessage, StreamMessageAESEncrypted } from './../../src/protocol/StreamMessage'
import { formMessageIdDescription } from '../../src/StreamrClientError'

const STREAM_ID = toStreamID('streamId')

Expand Down Expand Up @@ -61,6 +62,9 @@ describe('EncryptionUtil', () => {
...msg,
newGroupKey: new EncryptedGroupKey('mockId', hexToBinary('0x1234'))
}) as StreamMessageAESEncrypted
expect(() => EncryptionUtil.decryptStreamMessage(msg2, key)).toThrow('Could not decrypt new group key')
expect(() => EncryptionUtil.decryptStreamMessage(msg2, key)).toThrowStreamrError({
code: 'DECRYPT_ERROR',
message: `Could not decrypt new encryption key (messageId=${formMessageIdDescription(msg2.messageId)})`
})
})
})
8 changes: 5 additions & 3 deletions packages/sdk/test/unit/messagePipeline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { StrictStreamrClientConfig } from '../../src/Config'
import { DestroySignal } from '../../src/DestroySignal'
import { ERC1271ContractFacade } from '../../src/contracts/ERC1271ContractFacade'
import { StreamRegistry } from '../../src/contracts/StreamRegistry'
import { DecryptError, EncryptionUtil } from '../../src/encryption/EncryptionUtil'
import { EncryptionUtil } from '../../src/encryption/EncryptionUtil'
import { GroupKey } from '../../src/encryption/GroupKey'
import { GroupKeyManager } from '../../src/encryption/GroupKeyManager'
import { LitProtocolFacade } from '../../src/encryption/LitProtocolFacade'
Expand All @@ -22,6 +22,7 @@ import { PushPipeline } from '../../src/utils/PushPipeline'
import { mockLoggerFactory } from '../test-utils/utils'
import { MessageID } from './../../src/protocol/MessageID'
import { ContentType, EncryptionType, SignatureType, StreamMessage, StreamMessageType } from './../../src/protocol/StreamMessage'
import { StreamrClientError } from '../../src/StreamrClientError'

const CONTENT = {
foo: 'bar'
Expand Down Expand Up @@ -168,8 +169,9 @@ describe('messagePipeline', () => {
const output = await collect(pipeline)
expect(onError).toBeCalledTimes(1)
const error = onError.mock.calls[0][0]
expect(error).toBeInstanceOf(DecryptError)
expect(error.message).toMatch(/timed out/)
expect(error).toBeInstanceOf(StreamrClientError)
expect(error.code).toBe('DECRYPT_ERROR')
expect(error.message).toMatch(/Could not get encryption key/)
expect(output).toEqual([])
expect(streamRegistry.invalidatePermissionCaches).toBeCalledTimes(1)
expect(streamRegistry.invalidatePermissionCaches).toBeCalledWith(StreamPartIDUtils.getStreamID(streamPartId))
Expand Down
Loading