import { ComprModeType } from './compr-mode-type'
import { Context } from './context'
import { Exception, SealError } from './exception'
import { Instance, Library, LoaderOptions } from './seal'
import { VectorConstructorOptions } from './vector'
export type GaloisKeysDependencyOptions = {
readonly Exception: Exception
readonly ComprModeType: ComprModeType
readonly Vector: VectorConstructorOptions
}
export type GaloisKeysDependencies = {
({
Exception,
ComprModeType,
Vector
}: GaloisKeysDependencyOptions): GaloisKeysConstructorOptions
}
export type GaloisKeysConstructorOptions = {
(): GaloisKeys
}
export type GaloisKeys = {
readonly instance: Instance
readonly inject: (instance: Instance) => void
readonly delete: () => void
readonly size: number
readonly getIndex: (galoisElt: number) => number
readonly hasKey: (galoisElt: number) => boolean
readonly save: (compression?: ComprModeType) => string
readonly saveArray: (compression?: ComprModeType) => Uint8Array
readonly load: (context: Context, encoded: string) => void
readonly loadArray: (context: Context, array: Uint8Array) => void
readonly copy: (key: GaloisKeys) => void
readonly clone: () => GaloisKeys
readonly move: (key: GaloisKeys) => void
}
const GaloisKeysConstructor =
(library: Library): GaloisKeysDependencies =>
({
Exception,
ComprModeType,
Vector
}: GaloisKeysDependencyOptions): GaloisKeysConstructorOptions =>
(): GaloisKeys => {
const Constructor = library.GaloisKeys
let _instance = new Constructor()
/**
* @implements GaloisKeys
*/
/**
* @interface GaloisKeys
*/
return {
/**
* Get the underlying WASM instance
*
* @private
* @readonly
* @name GaloisKeys#instance
* @type {Instance}
*/
get instance() {
return _instance
},
/**
* Inject this object with a raw WASM instance
*
* @private
* @function
* @name GaloisKeys#inject
* @param {Instance} instance WASM instance
*/
inject(instance: Instance) {
if (_instance) {
_instance.delete()
_instance = undefined
}
_instance = new Constructor(instance)
instance.delete()
},
/**
* Delete the underlying WASM instance.
*
* Should be called before dereferencing this object to prevent the
* WASM heap from growing indefinitely.
* @function
* @name GaloisKeys#delete
*/
delete() {
if (_instance) {
_instance.delete()
_instance = undefined
}
},
/**
* Returns the current number of keyswitching keys. Only keys that are
* non-empty are counted.
*
* @readonly
* @name GaloisKeys#size
* @type {number}
*/
get size() {
return _instance.size()
},
/**
* Returns the index of a Galois key in the backing KSwitchKeys instance that
* corresponds to the given Galois element, assuming that it exists in the
* backing KSwitchKeys.
*
* @function
* @name GaloisKeys#getIndex
* @param {number} galoisElt The Galois element
* @returns {number} The index of the galois element
*/
getIndex(galoisElt: number): number {
try {
return _instance.getIndex(galoisElt)
} catch (e) {
throw Exception.safe(e as SealError)
}
},
/**
* Returns whether a Galois key corresponding to a given Galois element exists.
*
* @function
* @name GaloisKeys#hasKey
* @param {number} galoisElt The Galois element
* @returns {boolean} True if the key exists
*/
hasKey(galoisElt: number): boolean {
try {
return _instance.hasKey(galoisElt)
} catch (e) {
throw Exception.safe(e as SealError)
}
},
/**
* Save the Encryption Parameters to a base64 string
*
* @function
* @name GaloisKeys#save
* @param {ComprModeType} [compression={@link ComprModeType.zstd}] The compression mode to use
* @returns {string} Base64 encoded string
*/
save(compression: ComprModeType = ComprModeType.zstd): string {
try {
return _instance.saveToString(compression)
} catch (e) {
throw Exception.safe(e as SealError)
}
},
/**
* Save the GaloisKeys as a binary Uint8Array
*
* @function
* @name GaloisKeys#saveArray
* @param {ComprModeType} [compression={@link ComprModeType.zstd}] The compression mode to use
* @returns {Uint8Array} A byte array containing the GaloisKeys in binary form
*/
saveArray(compression: ComprModeType = ComprModeType.zstd): Uint8Array {
const tempVect = Vector()
const instance = _instance.saveToArray(compression)
tempVect.unsafeInject(instance)
tempVect.setType('Uint8Array')
const tempArr = tempVect.toArray() as Uint8Array
tempVect.delete()
return tempArr
},
/**
* Load a GaloisKeys from a base64 string
*
* @function
* @name GaloisKeys#load
* @param {Context} context Encryption context to enforce
* @param {string} encoded Base64 encoded string
*/
load(context: Context, encoded: string) {
try {
_instance.loadFromString(context.instance, encoded)
} catch (e) {
throw Exception.safe(e as SealError)
}
},
/**
* Load a GaloisKeys from an Uint8Array holding binary data
*
* @function
* @name GaloisKeys#loadArray
* @param {Context} context Encryption context to enforce
* @param {Uint8Array} array TypedArray containing binary data
*/
loadArray(context: Context, array: Uint8Array) {
try {
_instance.loadFromArray(context.instance, array)
} catch (e) {
throw Exception.safe(e as SealError)
}
},
/**
* Copy an existing GaloisKeys and overwrite this instance
*
* @function
* @name GaloisKeys#copy
* @param {GaloisKeys} key GaloisKeys to copy
* @example
* const keyA = keyGenerator.createGaloisKeys()
* const keyB = seal.GaloisKeys()
* keyB.copy(keyA)
* // keyB holds a copy of keyA
*/
copy(key: GaloisKeys) {
try {
_instance.copy(key.instance)
} catch (e) {
throw Exception.safe(e as SealError)
}
},
/**
* Clone and return a new instance of this GaloisKeys
*
* @function
* @name GaloisKeys#clone
* @returns {GaloisKeys}
* @example
* const keyA = keyGenerator.createGaloisKeys()
* const keyB = keyA.clone()
* // keyB holds a copy of keyA
*/
clone(): GaloisKeys {
try {
const clonedInstance = _instance.clone()
const key = GaloisKeysConstructor(library)({
Exception,
ComprModeType,
Vector
})()
key.inject(clonedInstance)
return key
} catch (e) {
throw Exception.safe(e as SealError)
}
},
/**
* Move a GaloisKeys into this one and delete the old reference
*
* @function
* @name GaloisKeys#move
* @param {GaloisKeys} key GaloisKeys to move
* @example
* const keyA = keyGenerator.createGaloisKeys()
* const keyB = seal.GaloisKeys()
* keyB.move(keyA)
* // keyB holds a the instance of keyA.
* // keyA no longer holds an instance
*/
move(key: GaloisKeys) {
try {
_instance.move(key.instance)
// TODO: find optimization
// This method results in a copy instead of a real move.
// Therefore, we need to delete the old instance.
key.delete()
} catch (e) {
throw Exception.safe(e as SealError)
}
}
}
}
export const GaloisKeysInit = ({
loader
}: LoaderOptions): GaloisKeysDependencies => {
const library: Library = loader.library
return GaloisKeysConstructor(library)
}
Source