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