generated from garrettmills/template-npm-typescript
	Add mechanism to REMOVE keys
This commit is contained in:
		
							parent
							
								
									6eb656f051
								
							
						
					
					
						commit
						f25a10b5e6
					
				| @ -22,10 +22,10 @@ const keyOne = 'some key' | ||||
| const keyTwo = 'some other key' | ||||
| 
 | ||||
| // Encode a new shared value using keyOne | ||||
| const shared = await SharedValue.create<string>(keyOne, value) | ||||
| const shared = await SharedValue.create<string>('key1', keyOne, value) | ||||
| 
 | ||||
| // Allow keyTwo to access the shared value: | ||||
| await shared.addKey(keyOne, keyTwo) | ||||
| await shared.addKey(keyOne, 'key2', keyTwo) | ||||
| 
 | ||||
| // Get the shared value: | ||||
| const decodedValue = await shared.get(keyTwo)  // => 'value to be encoded' | ||||
| @ -33,6 +33,9 @@ const decodedValue = await shared.get(keyTwo)  // => 'value to be encoded' | ||||
| // Set the shared value: | ||||
| const encodedValue = await shared.set(keyTwo, 'override string') | ||||
| 
 | ||||
| // Remove "key1" from the shared value: | ||||
| await shared.removeKey(keyTwo, "key1") | ||||
| 
 | ||||
| // Serialize the shared value securely: | ||||
| const serialized = shared.toJSON() | ||||
| ``` | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import {EncodedValue, isEncodedPayload, KeyValue} from './types' | ||||
| import {EncodedKeyPackage, isEncodedPayload, KeyValue} from './types' | ||||
| import {Cryptor, InvalidKeyError} from './crypt/Cryptor' | ||||
| import {pkg} from './interface' | ||||
| import {Payload} from './Payload' | ||||
| @ -11,7 +11,7 @@ import {Payload} from './Payload' | ||||
|  */ | ||||
| export class KeyPackage { | ||||
|     /** Create a new key package from an initial sharer's key. */ | ||||
|     public static async fromInitialSharer(initialSharerKey: KeyValue): Promise<KeyPackage> { | ||||
|     public static async fromInitialSharer(name: string, initialSharerKey: KeyValue): Promise<KeyPackage> { | ||||
|         // Get the cryptor for the initial sharer
 | ||||
|         const sharerCryptor = pkg.cryptor(initialSharerKey) | ||||
| 
 | ||||
| @ -20,17 +20,17 @@ export class KeyPackage { | ||||
|         const envelopeKey = await sharerCryptor.encode(envelope.encode()) | ||||
| 
 | ||||
|         // Return a new KeyPackage with the created envelope
 | ||||
|         return new KeyPackage([envelopeKey]) | ||||
|         return new KeyPackage({ [name]: envelopeKey }) | ||||
|     } | ||||
| 
 | ||||
|     /** Instantiate a key package from its serialized JSON value. */ | ||||
|     public static fromJSON(value: { envelopes: EncodedValue[] }): KeyPackage { | ||||
|     public static fromJSON(value: { envelopes: EncodedKeyPackage }): KeyPackage { | ||||
|         return new KeyPackage(value.envelopes) | ||||
|     } | ||||
| 
 | ||||
|     constructor( | ||||
|         /** The encoded user keys. */ | ||||
|         private readonly envelopes: EncodedValue[], | ||||
|         private envelopes: EncodedKeyPackage, | ||||
|     ) {} | ||||
| 
 | ||||
|     /** | ||||
| @ -40,7 +40,13 @@ export class KeyPackage { | ||||
|     async getCryptor(key: KeyValue): Promise<Cryptor> { | ||||
|         const envelopeCryptor = pkg.cryptor(key) | ||||
| 
 | ||||
|         for ( const encodedKey of this.envelopes ) { | ||||
|         for ( const encodedKeyName in this.envelopes ) { | ||||
|             if ( !Object.hasOwnProperty.call(this.envelopes, encodedKeyName) ) { | ||||
|                 continue | ||||
|             } | ||||
| 
 | ||||
|             const encodedKey = this.envelopes[encodedKeyName] | ||||
| 
 | ||||
|             // Attempt to decode one of the envelope keys using the input key
 | ||||
|             const decodedKey = await envelopeCryptor.decode(encodedKey) | ||||
|             if ( isEncodedPayload(decodedKey) ) { | ||||
| @ -55,9 +61,10 @@ export class KeyPackage { | ||||
|     /** | ||||
|      * Add a user's key to this package, granting them access to the master key. | ||||
|      * @param sharerKey - a currently valid user's key | ||||
|      * @param shareeName - the name of the sharee key | ||||
|      * @param shareeKey - the key to add to the package | ||||
|      */ | ||||
|     async addCryptor(sharerKey: KeyValue, shareeKey?: KeyValue): Promise<KeyValue> { | ||||
|     async addCryptor(sharerKey: KeyValue, shareeName: string, shareeKey?: KeyValue): Promise<KeyValue> { | ||||
|         // Validate the sharer's key and get the cryptor
 | ||||
|         const sharerCryptor = await this.getCryptor(sharerKey) | ||||
| 
 | ||||
| @ -67,13 +74,35 @@ export class KeyPackage { | ||||
| 
 | ||||
|         // Encode the global key using the sharee's key
 | ||||
|         const envelope = new Payload(sharerCryptor.getKey()) | ||||
|         const envelopeKey = await shareeCryptor.encode(envelope.encode()) | ||||
|         this.envelopes.push(envelopeKey) | ||||
|         this.envelopes[shareeName] = await shareeCryptor.encode(envelope.encode()) | ||||
| 
 | ||||
|         // Return the sharee's key that can be used to decode the global key
 | ||||
|         return determinedShareeKey | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Remove the `shareeKey` from this key package. | ||||
|      * @param sharerKey - a valid key in the package | ||||
|      * @param shareeName - name of the key that will be removed | ||||
|      */ | ||||
|     async removeCryptor(sharerKey: KeyValue, shareeName: string): Promise<void> { | ||||
|         // Validate the sharer's key
 | ||||
|         await this.getCryptor(sharerKey) | ||||
| 
 | ||||
|         const newCryptors = {} as EncodedKeyPackage | ||||
|         for ( const encodedKeyName in this.envelopes ) { | ||||
|             if ( !Object.hasOwnProperty.call(this.envelopes, encodedKeyName) ) { | ||||
|                 continue | ||||
|             } | ||||
| 
 | ||||
|             if ( encodedKeyName !== shareeName ) { | ||||
|                 newCryptors[encodedKeyName] = this.envelopes[encodedKeyName] | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         this.envelopes = newCryptors | ||||
|     } | ||||
| 
 | ||||
|     /** Serialize the key package securely. */ | ||||
|     toJSON() { | ||||
|         return { | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| import {EncodedValue, KeyValue} from './types' | ||||
| import {EncodedKeyPackage, EncodedValue, KeyValue} from './types' | ||||
| import {KeyPackage} from './KeyPackage' | ||||
| import {Payload} from './Payload' | ||||
| 
 | ||||
| /** Interface for a JSON-serializable shared value. */ | ||||
| export interface SerializedSharedValue<T> { | ||||
|     value: EncodedValue, | ||||
|     envelopes: EncodedValue[], | ||||
|     envelopes: EncodedKeyPackage, | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -17,11 +17,12 @@ export class SharedValue<T> { | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new shared value. | ||||
|      * @param name - the name of the initial sharer's key | ||||
|      * @param initialSharerKey - an initial key, used to give access to the encoded value | ||||
|      * @param value - the value to be encoded and shared | ||||
|      */ | ||||
|     public static async create<T>(initialSharerKey: KeyValue, value: T): Promise<SharedValue<T>> { | ||||
|         const keyPackage = await KeyPackage.fromInitialSharer(initialSharerKey) | ||||
|     public static async create<T>(name: string, initialSharerKey: KeyValue, value: T): Promise<SharedValue<T>> { | ||||
|         const keyPackage = await KeyPackage.fromInitialSharer(name, initialSharerKey) | ||||
|         const cryptor = await keyPackage.getCryptor(initialSharerKey) | ||||
|         const payload = new Payload<T>(value) | ||||
| 
 | ||||
| @ -80,10 +81,20 @@ export class SharedValue<T> { | ||||
|      * Add a new key to the key package for this shared value. This allows | ||||
|      * the `shareeKey` to access this shared value. | ||||
|      * @param sharerKey - a currently valid key | ||||
|      * @param shareeName - the name of the new key | ||||
|      * @param shareeKey - the new key to add | ||||
|      */ | ||||
|     async addKey(sharerKey: KeyValue, shareeKey?: KeyValue): Promise<KeyValue> { | ||||
|         return this.package.addCryptor(sharerKey, shareeKey) | ||||
|     async addKey(sharerKey: KeyValue, shareeName: string, shareeKey?: KeyValue): Promise<KeyValue> { | ||||
|         return this.package.addCryptor(sharerKey, shareeName, shareeKey) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Remove a given key from the key package. | ||||
|      * @param sharerKey | ||||
|      * @param shareeKey | ||||
|      */ | ||||
|     async removeKey(sharerKey: KeyValue, shareeName: string): Promise<void> { | ||||
|         await this.package.removeCryptor(sharerKey, shareeName) | ||||
|     } | ||||
| 
 | ||||
|     /** Serialize the shared value securely. */ | ||||
|  | ||||
| @ -8,6 +8,9 @@ export type DecodedValue = string | ||||
| /** String that has been encrypted. */ | ||||
| export type EncodedValue = string | ||||
| 
 | ||||
| /** Collection of encoded keys, by name. */ | ||||
| export type EncodedKeyPackage = { [name: string]: EncodedValue } | ||||
| 
 | ||||
| /** A key used for encryption. */ | ||||
| export type KeyValue = string | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user