import { IMultiEncryptedParsedHeader, ISingleEncryptedParsedHeader, Member, TypedIdProviderWrapper, type PlatformID } from '@digitaldefiance/ecies-lib'; import { EncryptedBlockMetadata } from '../encryptedBlockMetadata'; import { BlockDataType } from '../enumerations/blockDataType'; import { BlockEncryptionType } from '../enumerations/blockEncryptionType'; import { BlockSize } from '../enumerations/blockSize'; import { BlockType } from '../enumerations/blockType'; import { IEncryptedBlock } from '../interfaces/blocks/encrypted'; import { IEphemeralBlock } from '../interfaces/blocks/ephemeral'; import { Checksum } from '../types/checksum'; import { EphemeralBlock } from './ephemeral'; /** * Minimal service provider interface to avoid circular dependencies. * Only includes the services that EncryptedBlock actually uses. */ interface IEncryptedBlockServices { idProvider: TypedIdProviderWrapper; eciesService: { parseSingleEncryptedHeader(...args: unknown[]): ISingleEncryptedParsedHeader; parseMultiEncryptedHeader(...args: unknown[]): IMultiEncryptedParsedHeader; }; blockService: { decrypt(creator: Member, block: unknown, newBlockType: BlockType): Promise; decryptMultiple(creator: Member, block: unknown): Promise; }; blockCapacityCalculator: { calculateCapacity(options: { blockSize: BlockSize; blockType: BlockType; encryptionType: BlockEncryptionType; recipientCount?: number; }): { availableCapacity: number; }; }; } /** * Base class for encrypted blocks. * Adds encryption-specific header data and overhead calculations. * * BrightChain adopts ecies-lib's versioned encryption format as the canonical standard. * * Block Structure: * [Layer 0 Header][Layer 1 Header][...][Encryption Header][Encrypted Payload][Padding] * * ═══════════════════════════════════════════════════════════════════════════════════════ * SINGLE-RECIPIENT ENCRYPTION (WITH_LENGTH format, type 0x42) * ═══════════════════════════════════════════════════════════════════════════════════════ * * BrightChain uses WITH_LENGTH format for single-recipient encryption because: * 1. The data length field enables streaming decryption * 2. It's only 8 bytes more than BASIC * 3. Block sizes are known, making length verification valuable * * Byte Layout: * ┌─────────────────────────────────────────────────────────────────────────────────────┐ * │ [EncType][RecipientID][Version][CipherSuite][Type][PubKey][IV][AuthTag][Len][Data] │ * │ [1 ][idSize ][1 ][1 ][1 ][33 ][12][16 ][8 ][...] │ * └─────────────────────────────────────────────────────────────────────────────────────┘ * * | Offset | Size | Field | Description | * |-------------|--------|------------------|------------------------------------------| * | 0 | 1 | EncryptionType | BlockEncryptionType.SingleRecipient (1) | * | 1 | idSize | RecipientID | BrightChain routing ID | * | 1+idSize | 1 | Version | Protocol version (0x01) | * | 2+idSize | 1 | CipherSuite | AES-256-GCM (0x01) | * | 3+idSize | 1 | EncryptionType | WITH_LENGTH (0x42) | * | 4+idSize | 33 | EphemeralPubKey | Compressed secp256k1 public key | * | 37+idSize | 12 | IV | Initialization vector (NIST SP 800-38D) | * | 49+idSize | 16 | AuthTag | GCM authentication tag | * | 65+idSize | 8 | DataLength | Original data length (big-endian) | * | 73+idSize | ... | EncryptedData | Ciphertext | * * Total overhead: 1 + idSize + ECIES.WITH_LENGTH.FIXED_OVERHEAD_SIZE = 1 + idSize + 72 * Default (GUID, idSize=16): 1 + 16 + 72 = 89 bytes * ObjectID (idSize=12): 1 + 12 + 72 = 85 bytes * * ═══════════════════════════════════════════════════════════════════════════════════════ * MULTI-RECIPIENT ENCRYPTION (MULTIPLE format, type 0x63) * ═══════════════════════════════════════════════════════════════════════════════════════ * * Byte Layout: * ┌─────────────────────────────────────────────────────────────────────────────────────┐ * │ [EncType][Ver][CS][PubKey][IV][Tag][Len][Count][RecipientEntries...][EncryptedData] │ * │ [1 ][1 ][1 ][33 ][12][16 ][8 ][2 ][variable ][...] │ * └─────────────────────────────────────────────────────────────────────────────────────┘ * * Recipient Entry Layout (per recipient): * | Offset | Size | Field | Description | * |-------------|--------|---------------|-------------------------------------------| * | 0 | idSize | RecipientID | Recipient identifier | * | idSize | 12 | KeyIV | IV for this recipient's key encryption | * | idSize+12 | 16 | KeyAuthTag | Auth tag for key encryption | * | idSize+28 | 32 | EncryptedKey | Encrypted symmetric key | * * Per-recipient overhead: idSize + ECIES.MULTIPLE.ENCRYPTED_KEY_SIZE = idSize + 60 * * Total overhead formula: * 1 + ECIES.MULTIPLE.FIXED_OVERHEAD_SIZE + DATA_LENGTH_SIZE + RECIPIENT_COUNT_SIZE * + (recipientCount * (idSize + ENCRYPTED_KEY_SIZE)) * = 1 + 64 + 8 + 2 + (recipientCount * (idSize + 60)) * = 75 + (recipientCount * (idSize + 60)) * * @see design.md for complete format specification * @see Requirements 2.2, 2.3, 3.3, 8.4 */ export declare class EncryptedBlock extends EphemeralBlock implements IEncryptedBlock { protected readonly _encryptionType: BlockEncryptionType; protected readonly _recipients: Array; protected readonly _recipientWithKey: Member; protected readonly _serviceProvider: IEncryptedBlockServices; /** * Get the service provider for this block */ protected get serviceProvider(): IEncryptedBlockServices; protected readonly _idProvider: TypedIdProviderWrapper; protected _cachedEncryptionDetails?: ISingleEncryptedParsedHeader | IMultiEncryptedParsedHeader; /** * Creates an instance of EncryptedBlock. * @param type - The type of the block * @param dataType - The type of data in the block * @param data - The encrypted data * @param checksum - The checksum of the data * @param metadata - The block metadata * @param canRead - Whether the block can be read * @param canPersist - Whether the block can be persisted */ constructor(type: BlockType, dataType: BlockDataType, data: Uint8Array, checksum: Checksum, metadata: EncryptedBlockMetadata, recipientWithKey: Member, canRead?: boolean, canPersist?: boolean); /** * Create a new encrypted block from data */ static from(type: BlockType, dataType: BlockDataType, blockSize: BlockSize, data: Uint8Array, checksum: Checksum, creator: Member, dateCreated?: Date, lengthBeforeEncryption?: number, canRead?: boolean, canPersist?: boolean, recipientWithKey?: Member, recipientCount?: number): Promise>; /** * Whether the block can be encrypted * Always returns false since this block is already encrypted */ canEncrypt(): boolean; canMultiEncrypt(recipientCount: number): boolean; encrypt(): Promise>; /** * The type of encryption used for the block */ get encryptionType(): BlockEncryptionType; /** * The recipients of the block */ get recipients(): Array; get recipientWithKey(): Member; /** * The encryption details parsed from the header */ get encryptionDetails(): ISingleEncryptedParsedHeader | IMultiEncryptedParsedHeader; decrypt>(newBlockType: BlockType): Promise; /** * The block type stored in the header */ get blockTypeHeader(): BlockType; /** * The total overhead of the block, including encryption overhead. * For encrypted blocks, the overhead is the ECIES overhead since the * encryption header is part of the data buffer. * * Single-recipient uses WITH_LENGTH format (72 bytes fixed overhead): * overhead = UINT8_SIZE (encryption type) + idSize + ECIES.WITH_LENGTH.FIXED_OVERHEAD_SIZE * = 1 + idSize + 72 * * Multi-recipient uses MULTIPLE format: * overhead = UINT8_SIZE (encryption type) + calculateECIESMultipleRecipientOverhead() * = 1 + 74 + (recipientCount * (idSize + 60)) * * @see Requirements 2.3, 3.3, 5.4 */ get layerOverheadSize(): number; /** * Get this layer's header data (encryption metadata) */ get layerHeaderData(): Uint8Array; /** * Get the encrypted payload data (excluding the encryption header and padding) */ get layerPayload(): Uint8Array; /** * Get the length of the encrypted payload (excluding header and padding). * * For encrypted blocks, the payload is the actual encrypted data portion. * This is calculated as: total data length - header overhead * * Note: This returns the encrypted data size, not the original plaintext size. * Use lengthBeforeEncryption for the original data size. * * @see Requirements 2.2 */ get layerPayloadSize(): number; /** * Get the total encrypted length including headers and payload */ get encryptedLength(): number; /** * Asynchronously validate the block's data and structure * @throws {ChecksumMismatchError} If validation fails due to checksum mismatch */ validateAsync(): Promise; /** * Synchronously validate the block's data and structure * @throws {ChecksumMismatchError} If validation fails due to checksum mismatch */ validateSync(): void; /** * Alias for validateSync() to maintain compatibility * @throws {ChecksumMismatchError} If validation fails due to checksum mismatch */ validate(): void; } export {}; //# sourceMappingURL=encrypted.d.ts.map