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