@time-file/browser-file-crypto 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -78,6 +78,73 @@ export declare const AUTH_TAG_LENGTH = 16;
78
78
  */
79
79
  export declare function computeKeyFileHash(keyData: string): Promise<string>;
80
80
 
81
+ /**
82
+ * Creates a streaming decryption TransformStream.
83
+ *
84
+ * @description
85
+ * Creates a TransformStream that decrypts streaming-encrypted data.
86
+ * The stream automatically parses the header and decrypts each chunk
87
+ * using the appropriate key derivation method.
88
+ *
89
+ * @param options - Streaming decryption options
90
+ * @returns A TransformStream that decrypts data
91
+ *
92
+ * @throws {CryptoError} When password is required but not provided (PASSWORD_REQUIRED)
93
+ * @throws {CryptoError} When keyfile is required but not provided (KEYFILE_REQUIRED)
94
+ * @throws {CryptoError} When decryption fails (DECRYPTION_FAILED)
95
+ * @throws {CryptoError} When format is unsupported (UNSUPPORTED_FORMAT)
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const stream = createDecryptStream({
100
+ * password: 'my-secret',
101
+ * onProgress: ({ processedBytes }) => console.log(`${processedBytes} bytes processed`)
102
+ * });
103
+ *
104
+ * await encryptedStream.pipeThrough(stream).pipeTo(outputStream);
105
+ * ```
106
+ *
107
+ * @since 1.1.0
108
+ */
109
+ export declare function createDecryptStream(options: StreamDecryptOptions): TransformStream<Uint8Array, Uint8Array>;
110
+
111
+ /**
112
+ * Creates a streaming encryption TransformStream.
113
+ *
114
+ * @description
115
+ * Creates a TransformStream that encrypts data in chunks using AES-256-GCM.
116
+ * Each chunk is independently encrypted with a unique IV derived from the
117
+ * base IV and chunk index. This allows memory-efficient encryption of
118
+ * arbitrarily large files.
119
+ *
120
+ * @param options - Streaming encryption options
121
+ * @returns Promise resolving to an object containing the TransformStream and header
122
+ *
123
+ * @throws {CryptoError} When neither password nor keyData is provided (PASSWORD_REQUIRED)
124
+ * @throws {CryptoError} When encryption fails (ENCRYPTION_FAILED)
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const { stream, header } = await createEncryptStream({
129
+ * password: 'my-secret',
130
+ * chunkSize: 1024 * 1024, // 1MB chunks
131
+ * onProgress: ({ processedBytes }) => console.log(`${processedBytes} bytes processed`)
132
+ * });
133
+ *
134
+ * // Write header first, then pipe data through the stream
135
+ * const writer = writableStream.getWriter();
136
+ * await writer.write(header);
137
+ * writer.releaseLock();
138
+ * await readableStream.pipeThrough(stream).pipeTo(writableStream);
139
+ * ```
140
+ *
141
+ * @since 1.1.0
142
+ */
143
+ export declare function createEncryptStream(options: StreamEncryptOptions): Promise<{
144
+ stream: TransformStream<Uint8Array, Uint8Array>;
145
+ header: Uint8Array;
146
+ }>;
147
+
81
148
  /**
82
149
  * Custom error class for crypto operations.
83
150
  *
@@ -197,6 +264,37 @@ export declare type CryptoErrorCode = 'INVALID_INPUT' | 'PASSWORD_REQUIRED' | 'K
197
264
  */
198
265
  export declare function decryptFile(encrypted: Blob | ArrayBuffer, options: DecryptOptions): Promise<Blob>;
199
266
 
267
+ /**
268
+ * Decrypts a streaming-encrypted file.
269
+ *
270
+ * @description
271
+ * Convenience function that decrypts a streaming-encrypted File, Blob,
272
+ * or ReadableStream and returns a ReadableStream of the decrypted data.
273
+ *
274
+ * @param encrypted - The encrypted data (File, Blob, or ReadableStream)
275
+ * @param options - Streaming decryption options
276
+ * @returns A ReadableStream of decrypted data
277
+ *
278
+ * @throws {CryptoError} When password is required but not provided (PASSWORD_REQUIRED)
279
+ * @throws {CryptoError} When keyfile is required but not provided (KEYFILE_REQUIRED)
280
+ * @throws {CryptoError} When decryption fails (DECRYPTION_FAILED)
281
+ *
282
+ * @example
283
+ * ```typescript
284
+ * const decryptedStream = decryptFileStream(encryptedBlob, {
285
+ * password: 'my-secret',
286
+ * onProgress: ({ processedBytes }) => console.log(`${processedBytes} bytes decrypted`)
287
+ * });
288
+ *
289
+ * // Convert to Blob
290
+ * const response = new Response(decryptedStream);
291
+ * const decryptedBlob = await response.blob();
292
+ * ```
293
+ *
294
+ * @since 1.1.0
295
+ */
296
+ export declare function decryptFileStream(encrypted: File | Blob | ReadableStream<Uint8Array>, options: StreamDecryptOptions): ReadableStream<Uint8Array>;
297
+
200
298
  /**
201
299
  * Options for file decryption.
202
300
  *
@@ -223,6 +321,12 @@ export declare interface DecryptOptions {
223
321
  onProgress?: ProgressCallback;
224
322
  }
225
323
 
324
+ /**
325
+ * Default chunk size for streaming encryption (64KB).
326
+ * @since 1.1.0
327
+ */
328
+ export declare const DEFAULT_CHUNK_SIZE: number;
329
+
226
330
  /**
227
331
  * Downloads an encrypted file from URL, decrypts it, and saves to disk.
228
332
  *
@@ -365,27 +469,78 @@ export declare function downloadKeyFile(keyData: string, fileName: string, exten
365
469
  */
366
470
  export declare function encryptFile(file: File | Blob | ArrayBuffer, options: EncryptOptions): Promise<Blob>;
367
471
 
472
+ /**
473
+ * Encrypts a file using streaming encryption.
474
+ *
475
+ * @description
476
+ * Convenience function that encrypts a File or Blob using streaming
477
+ * encryption and returns a ReadableStream of the encrypted data.
478
+ * The stream includes the encryption header followed by encrypted chunks.
479
+ *
480
+ * @param file - The file to encrypt
481
+ * @param options - Streaming encryption options
482
+ * @returns Promise resolving to a ReadableStream of encrypted data
483
+ *
484
+ * @throws {CryptoError} When neither password nor keyData is provided (PASSWORD_REQUIRED)
485
+ * @throws {CryptoError} When encryption fails (ENCRYPTION_FAILED)
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * const encryptedStream = await encryptFileStream(largeFile, {
490
+ * password: 'my-secret',
491
+ * chunkSize: 1024 * 1024, // 1MB chunks
492
+ * onProgress: ({ processedBytes, totalBytes }) => {
493
+ * const percent = Math.round((processedBytes / totalBytes!) * 100);
494
+ * console.log(`${percent}%`);
495
+ * }
496
+ * });
497
+ *
498
+ * // Convert to Blob
499
+ * const response = new Response(encryptedStream);
500
+ * const encryptedBlob = await response.blob();
501
+ * ```
502
+ *
503
+ * @since 1.1.0
504
+ */
505
+ export declare function encryptFileStream(file: File | Blob, options: StreamEncryptOptions): Promise<ReadableStream<Uint8Array>>;
506
+
368
507
  /**
369
508
  * Encryption marker byte for keyfile-based encryption.
370
509
  * Used to identify the encryption method when decrypting.
371
510
  */
372
511
  export declare const ENCRYPTION_MARKER_KEYFILE = 2;
373
512
 
513
+ /**
514
+ * Encryption marker byte for keyfile-based streaming encryption.
515
+ * Used to identify streaming encryption with keyfile.
516
+ * @since 1.1.0
517
+ */
518
+ export declare const ENCRYPTION_MARKER_KEYFILE_STREAM = 18;
519
+
374
520
  /**
375
521
  * Encryption marker byte for password-based encryption.
376
522
  * Used to identify the encryption method when decrypting.
377
523
  */
378
524
  export declare const ENCRYPTION_MARKER_PASSWORD = 1;
379
525
 
526
+ /**
527
+ * Encryption marker byte for password-based streaming encryption.
528
+ * Used to identify streaming encryption with password.
529
+ * @since 1.1.0
530
+ */
531
+ export declare const ENCRYPTION_MARKER_PASSWORD_STREAM = 17;
532
+
380
533
  /**
381
534
  * Encryption type detected from encrypted data.
382
535
  *
383
536
  * @description
384
537
  * - `password`: File was encrypted with a password (marker byte 0x01)
385
538
  * - `keyfile`: File was encrypted with a keyfile (marker byte 0x02)
539
+ * - `password-stream`: File was encrypted with password streaming (marker byte 0x11)
540
+ * - `keyfile-stream`: File was encrypted with keyfile streaming (marker byte 0x12)
386
541
  * - `unknown`: Unrecognized format or not encrypted with this library
387
542
  */
388
- export declare type EncryptionType = 'password' | 'keyfile' | 'unknown';
543
+ export declare type EncryptionType = 'password' | 'keyfile' | 'password-stream' | 'keyfile-stream' | 'unknown';
389
544
 
390
545
  /**
391
546
  * Options for file encryption.
@@ -486,10 +641,13 @@ export declare function generateRandomPassword(length?: number): string;
486
641
  *
487
642
  * @description
488
643
  * Reads the first byte (marker) of the encrypted data to determine
489
- * whether it was encrypted with a password or keyfile.
644
+ * whether it was encrypted with a password or keyfile, and whether
645
+ * it uses streaming or non-streaming encryption.
490
646
  *
491
- * - Marker 0x01: Password-based encryption
492
- * - Marker 0x02: Keyfile-based encryption
647
+ * - Marker 0x01: Password-based encryption (non-streaming)
648
+ * - Marker 0x02: Keyfile-based encryption (non-streaming)
649
+ * - Marker 0x11: Password-based streaming encryption
650
+ * - Marker 0x12: Keyfile-based streaming encryption
493
651
  * - Other: Unknown format
494
652
  *
495
653
  * @param data - The encrypted data (Blob or ArrayBuffer)
@@ -501,10 +659,16 @@ export declare function generateRandomPassword(length?: number): string;
501
659
  *
502
660
  * switch (type) {
503
661
  * case 'password':
504
- * // Show password input
662
+ * // Use decryptFile with password
505
663
  * break;
506
664
  * case 'keyfile':
507
- * // Show keyfile picker
665
+ * // Use decryptFile with keyData
666
+ * break;
667
+ * case 'password-stream':
668
+ * // Use decryptFileStream with password
669
+ * break;
670
+ * case 'keyfile-stream':
671
+ * // Use decryptFileStream with keyData
508
672
  * break;
509
673
  * case 'unknown':
510
674
  * // Show error: not encrypted with this library
@@ -547,7 +711,7 @@ export declare function isCryptoError(error: unknown): error is CryptoError;
547
711
  * @description
548
712
  * Performs a quick check to determine if the data was likely encrypted
549
713
  * with browser-file-crypto. This checks:
550
- * 1. The marker byte is valid (0x01 or 0x02)
714
+ * 1. The marker byte is valid (0x01, 0x02, 0x11, or 0x12)
551
715
  * 2. The data meets minimum size requirements
552
716
  *
553
717
  * Note: This is not a cryptographic verification. It only checks
@@ -572,6 +736,31 @@ export declare function isCryptoError(error: unknown): error is CryptoError;
572
736
  */
573
737
  export declare function isEncryptedFile(data: Blob | ArrayBuffer): Promise<boolean>;
574
738
 
739
+ /**
740
+ * Checks if the encryption type is a streaming format.
741
+ *
742
+ * @description
743
+ * Helper function to determine if the encryption type uses
744
+ * streaming encryption, which requires different decryption methods.
745
+ *
746
+ * @param type - The encryption type
747
+ * @returns true if the type is a streaming format
748
+ *
749
+ * @example
750
+ * ```typescript
751
+ * const type = await getEncryptionType(encryptedBlob);
752
+ *
753
+ * if (isStreamingEncryption(type)) {
754
+ * const decrypted = decryptFileStream(encryptedBlob, { password });
755
+ * } else {
756
+ * const decrypted = await decryptFile(encryptedBlob, { password });
757
+ * }
758
+ * ```
759
+ *
760
+ * @since 1.1.0
761
+ */
762
+ export declare function isStreamingEncryption(type: EncryptionType): boolean;
763
+
575
764
  /**
576
765
  * Initialization vector length in bytes for AES-GCM.
577
766
  * 12 bytes (96 bits) is the recommended IV size for AES-GCM per NIST SP 800-38D.
@@ -723,4 +912,72 @@ export declare type ProgressPhase = 'deriving_key' | 'encrypting' | 'decrypting'
723
912
  */
724
913
  export declare const SALT_LENGTH = 16;
725
914
 
915
+ /**
916
+ * Streaming format version.
917
+ * @since 1.1.0
918
+ */
919
+ export declare const STREAM_FORMAT_VERSION = 1;
920
+
921
+ /**
922
+ * Options for streaming file decryption.
923
+ *
924
+ * @since 1.1.0
925
+ */
926
+ export declare interface StreamDecryptOptions {
927
+ /** Password for decryption (required for password-encrypted files) */
928
+ password?: string;
929
+ /** Base64-encoded key data (required for keyfile-encrypted files) */
930
+ keyData?: string;
931
+ /** Progress callback for UI updates */
932
+ onProgress?: StreamProgressCallback;
933
+ }
934
+
935
+ /**
936
+ * Options for streaming file encryption.
937
+ *
938
+ * @since 1.1.0
939
+ */
940
+ export declare interface StreamEncryptOptions {
941
+ /** Password for encryption (required if keyData not provided) */
942
+ password?: string;
943
+ /** Base64-encoded key data from keyfile (required if password not provided) */
944
+ keyData?: string;
945
+ /** Chunk size in bytes (default: 65536 = 64KB) */
946
+ chunkSize?: number;
947
+ /** Progress callback for UI updates */
948
+ onProgress?: StreamProgressCallback;
949
+ }
950
+
951
+ /**
952
+ * Progress information for streaming encryption/decryption operations.
953
+ *
954
+ * @since 1.1.0
955
+ */
956
+ export declare interface StreamProgress {
957
+ /** Current phase of the operation */
958
+ phase: StreamProgressPhase;
959
+ /** Number of bytes processed so far */
960
+ processedBytes: number;
961
+ /** Total bytes to process (undefined if unknown, e.g., for streams) */
962
+ totalBytes?: number;
963
+ /** Number of chunks processed so far */
964
+ processedChunks: number;
965
+ /** Progress percentage (0-100), only available when totalBytes is known */
966
+ progress?: number;
967
+ }
968
+
969
+ /**
970
+ * Callback function for streaming progress updates.
971
+ *
972
+ * @since 1.1.0
973
+ */
974
+ export declare type StreamProgressCallback = (progress: StreamProgress) => void;
975
+
976
+ /**
977
+ * Progress phase during streaming encryption/decryption operations.
978
+ *
979
+ * @since 1.1.0
980
+ */
981
+ export declare type StreamProgressPhase = 'deriving_key' | 'processing' | 'complete';
982
+
726
983
  export { }