|
|
@ -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 { |
|
|
|