@@ -13,6 +13,8 @@ export type Options = {
1313 ivLength ?: number ;
1414} ;
1515
16+ type ProcessedOptions = Readonly < Required < Options > > ;
17+
1618/**
1719 * Implements an encrypted Svelte writable store using the Crypto and
1820 * SubtleCrypto APIs with AES-GCM. The data is written to and read from a
@@ -27,6 +29,20 @@ export type Options = {
2729 * The written format is IV + Salt + Ciphertext concatenated, and then Base64
2830 * encoded as a string. The data read is first processed with TextEncoder.
2931 *
32+ * The returned store also has the an extra property called `options`, which is
33+ * an object containing the options used to create the store. This can be used
34+ * to check how it was created and save them since they are necessary to decrypt
35+ * the data. Also note that the supplied options are treated very strictly, and
36+ * in case they are present but invalid values they are replaced by the
37+ * defaults. For example, `iterations`, `saltLength` and `ivLength` are all
38+ * expected to be of type number and be positive, finite integers. If you supply
39+ * somthing like '16' or 16.1 for `saltLength`, then the default will be used.
40+ * In the case you rely on loose inputs for these parameters, use the returned
41+ * `options` member of the store to assert that they were interpreted as you
42+ * expected them to. Your backing store will not be written to if it already has
43+ * a string in it so you still have the chance to check your options. Otherwise
44+ * use properly defined data in constants or sanitize your inputs.
45+ *
3046 * @param crypto - The Crypto implementation, which is typically found as
3147 * window.crypto in browser contexts.
3248 * @param backend - A writable Svelte store that implements set and subscribe.
@@ -53,10 +69,10 @@ export const subtleCryptoStore = Object.freeze(function(
5369 backend : Writable < string > ,
5470 password : string ,
5571 opts ?: Options ,
56- ) : Writable < Promise < string > > {
72+ ) : Readonly < Writable < Promise < string > > > {
5773 if ( typeof opts === 'undefined' )
5874 opts = { } ;
59- const o : InternalOptions = Object . freeze ( {
75+ const o : ProcessedOptions = Object . freeze ( {
6076 iterations : positiveIntOrDefault ( opts , 'iterations' , defaultIterations ) ,
6177 saltLength : positiveIntOrDefault ( opts , 'saltLength' , defaultSaltLength ) ,
6278 ivLength : positiveIntOrDefault ( opts , 'ivLength' , defaultIvLength ) ,
@@ -92,14 +108,15 @@ export const subtleCryptoStore = Object.freeze(function(
92108 backend . set ( newVal ) ;
93109 } ) ,
94110
111+ options : o ,
95112 } ) ;
96113} ) ;
97114
98115/** Returns a fucntion that decrypts a ciphertext using AES-GCM */
99116const newDecryptFunc = Object . freeze ( function (
100117 crypto : Crypto ,
101118 getMemoized : ( ) => Promise < Memoized > ,
102- o : InternalOptions ,
119+ o : ProcessedOptions ,
103120) : ( s : string ) => Promise < string > {
104121 return Object . freeze ( async function ( s : string ) : Promise < string > {
105122 if ( typeof s !== 'string' || s === '' )
@@ -133,7 +150,7 @@ const newDecryptFunc = Object.freeze(function(
133150const encrypt = Object . freeze ( async function (
134151 crypto : Crypto ,
135152 getMemoized : ( ) => Promise < Memoized > ,
136- o : InternalOptions ,
153+ o : ProcessedOptions ,
137154 plainText : Promise < string > ,
138155) : Promise < string > {
139156 if ( typeof plainText === 'undefined' )
@@ -241,8 +258,6 @@ const memoize = Object.freeze(function<T>(makeT: () => T): () => T {
241258 } ) ;
242259} ) ;
243260
244- type InternalOptions = Readonly < Required < Options > > ;
245-
246261/**
247262 * Attempts to get the given property of the object and returns it if it is a
248263 * positive, finite integer. Otherwise it returns the default value.
@@ -277,7 +292,7 @@ const toCodePoint = Object.freeze(function(s: string): number {
277292 if ( typeof res !== 'number' )
278293 // shouldn't happen in practice since this function is receiving the
279294 // output of atob
280- throw new Error ( 'invalid codepoint' , { cause : s } ) ;
295+ throw new Error ( 'invalid codepoint' ) ;
281296 return res ;
282297} ) ;
283298
0 commit comments