Source

relin-keys.ts

  1. import { ComprModeType } from './compr-mode-type'
  2. import { Context } from './context'
  3. import { Exception, SealError } from './exception'
  4. import { Instance, Library, LoaderOptions } from './seal'
  5. import { VectorConstructorOptions } from './vector'
  6. export type RelinKeysDependencyOptions = {
  7. readonly Exception: Exception
  8. readonly ComprModeType: ComprModeType
  9. readonly Vector: VectorConstructorOptions
  10. }
  11. export type RelinKeysDependencies = {
  12. ({
  13. Exception,
  14. ComprModeType,
  15. Vector
  16. }: RelinKeysDependencyOptions): RelinKeysConstructorOptions
  17. }
  18. export type RelinKeysConstructorOptions = {
  19. (): RelinKeys
  20. }
  21. export type RelinKeys = {
  22. readonly instance: Instance
  23. readonly inject: (instance: Instance) => void
  24. readonly delete: () => void
  25. readonly size: number
  26. readonly getIndex: (keyPower: number) => number
  27. readonly hasKey: (keyPower: number) => boolean
  28. readonly save: (compression?: ComprModeType) => string
  29. readonly saveArray: (compression?: ComprModeType) => Uint8Array
  30. readonly load: (context: Context, encoded: string) => void
  31. readonly loadArray: (context: Context, array: Uint8Array) => void
  32. readonly copy: (key: RelinKeys) => void
  33. readonly clone: () => RelinKeys
  34. readonly move: (key: RelinKeys) => void
  35. }
  36. const RelinKeysConstructor =
  37. (library: Library): RelinKeysDependencies =>
  38. ({
  39. Exception,
  40. ComprModeType,
  41. Vector
  42. }: RelinKeysDependencyOptions): RelinKeysConstructorOptions =>
  43. (): RelinKeys => {
  44. const Constructor = library.RelinKeys
  45. let _instance = new Constructor()
  46. /**
  47. * @implements RelinKeys
  48. */
  49. /**
  50. * @interface RelinKeys
  51. */
  52. return {
  53. /**
  54. * Get the underlying WASM instance
  55. *
  56. * @private
  57. * @readonly
  58. * @name RelinKeys#instance
  59. * @type {Instance}
  60. */
  61. get instance() {
  62. return _instance
  63. },
  64. /**
  65. * Inject this object with a raw WASM instance
  66. *
  67. * @private
  68. * @function
  69. * @name RelinKeys#inject
  70. * @param {Instance} instance WASM instance
  71. */
  72. inject(instance: Instance) {
  73. if (_instance) {
  74. _instance.delete()
  75. _instance = undefined
  76. }
  77. _instance = new Constructor(instance)
  78. instance.delete()
  79. },
  80. /**
  81. * Delete the underlying WASM instance.
  82. *
  83. * Should be called before dereferencing this object to prevent the
  84. * WASM heap from growing indefinitely.
  85. * @function
  86. * @name RelinKeys#delete
  87. */
  88. delete() {
  89. if (_instance) {
  90. _instance.delete()
  91. _instance = undefined
  92. }
  93. },
  94. /**
  95. * Returns the current number of keyswitching keys. Only keys that are
  96. * non-empty are counted.
  97. *
  98. * @readonly
  99. * @name RelinKeys#size
  100. * @type {number}
  101. */
  102. get size() {
  103. return _instance.size()
  104. },
  105. /**
  106. * Returns the index of a relinearization key in the backing KSwitchKeys
  107. * instance that corresponds to the given secret key power, assuming that
  108. * it exists in the backing KSwitchKeys.
  109. *
  110. * @function
  111. * @name RelinKeys#getIndex
  112. * @param {number} keyPower The power of the secret key
  113. * @returns {number} The index of the relin key
  114. */
  115. getIndex(keyPower: number): number {
  116. try {
  117. return _instance.getIndex(keyPower)
  118. } catch (e) {
  119. throw Exception.safe(e as SealError)
  120. }
  121. },
  122. /**
  123. * Returns whether a relinearization key corresponding to a given power of
  124. * the secret key exists.
  125. *
  126. * @function
  127. * @name RelinKeys#hasKey
  128. * @param {number} keyPower The power of the secret key
  129. * @returns {boolean} True if the power exists
  130. */
  131. hasKey(keyPower: number): boolean {
  132. try {
  133. return _instance.hasKey(keyPower)
  134. } catch (e) {
  135. throw Exception.safe(e as SealError)
  136. }
  137. },
  138. /**
  139. * Save the Encryption Parameters to a base64 string
  140. *
  141. * @function
  142. * @name RelinKeys#save
  143. * @param {ComprModeType} [compression={@link ComprModeType.zstd}] The compression mode to use
  144. * @returns {string} Base64 encoded string
  145. */
  146. save(compression: ComprModeType = ComprModeType.zstd): string {
  147. try {
  148. return _instance.saveToString(compression)
  149. } catch (e) {
  150. throw Exception.safe(e as SealError)
  151. }
  152. },
  153. /**
  154. * Save the RelinKeys as a binary Uint8Array
  155. *
  156. * @function
  157. * @name RelinKeys#saveArray
  158. * @param {ComprModeType} [compression={@link ComprModeType.zstd}] The compression mode to use
  159. * @returns {Uint8Array} A byte array containing the RelinKeys in binary form
  160. */
  161. saveArray(compression: ComprModeType = ComprModeType.zstd): Uint8Array {
  162. const tempVect = Vector()
  163. const instance = _instance.saveToArray(compression)
  164. tempVect.unsafeInject(instance)
  165. tempVect.setType('Uint8Array')
  166. const tempArr = tempVect.toArray() as Uint8Array
  167. tempVect.delete()
  168. return tempArr
  169. },
  170. /**
  171. * Load a RelinKeys from a base64 string
  172. *
  173. * @function
  174. * @name RelinKeys#load
  175. * @param {Context} context Encryption context to enforce
  176. * @param {string} encoded Base64 encoded string
  177. */
  178. load(context: Context, encoded: string) {
  179. try {
  180. _instance.loadFromString(context.instance, encoded)
  181. } catch (e) {
  182. throw Exception.safe(e as SealError)
  183. }
  184. },
  185. /**
  186. * Load a RelinKeys from an Uint8Array holding binary data
  187. *
  188. * @function
  189. * @name RelinKeys#loadArray
  190. * @param {Context} context Encryption context to enforce
  191. * @param {Uint8Array} array TypedArray containing binary data
  192. */
  193. loadArray(context: Context, array: Uint8Array) {
  194. try {
  195. _instance.loadFromArray(context.instance, array)
  196. } catch (e) {
  197. throw Exception.safe(e as SealError)
  198. }
  199. },
  200. /**
  201. * Copy an existing RelinKeys and overwrite this instance
  202. *
  203. * @function
  204. * @name RelinKeys#copy
  205. * @param {RelinKeys} key RelinKeys to copy
  206. * @example
  207. * const keyA = keyGenerator.createRelinKeys()
  208. * const keyB = seal.RelinKeys()
  209. * keyB.copy(keyA)
  210. * // keyB holds a copy of keyA
  211. */
  212. copy(key: RelinKeys) {
  213. try {
  214. _instance.copy(key.instance)
  215. } catch (e) {
  216. throw Exception.safe(e as SealError)
  217. }
  218. },
  219. /**
  220. * Clone and return a new instance of this RelinKeys
  221. *
  222. * @function
  223. * @name RelinKeys#clone
  224. * @returns {RelinKeys}
  225. * @example
  226. * const keyA = keyGenerator.createRelinKeys()
  227. * const keyB = keyA.clone()
  228. * // keyB holds a copy of keyA
  229. */
  230. clone(): RelinKeys {
  231. try {
  232. const clonedInstance = _instance.clone()
  233. const key = RelinKeysConstructor(library)({
  234. Exception,
  235. ComprModeType,
  236. Vector
  237. })()
  238. key.inject(clonedInstance)
  239. return key
  240. } catch (e) {
  241. throw Exception.safe(e as SealError)
  242. }
  243. },
  244. /**
  245. * Move a RelinKeys into this one and delete the old reference
  246. *
  247. * @function
  248. * @name RelinKeys#move
  249. * @param {RelinKeys} key RelinKeys to move
  250. * @example
  251. * const keyA = keyGenerator.createRelinKeys()
  252. * const keyB = seal.RelinKeys()
  253. * keyB.move(keyA)
  254. * // keyB holds a the instance of keyA.
  255. * // keyA no longer holds an instance
  256. */
  257. move(key: RelinKeys) {
  258. try {
  259. _instance.move(key.instance)
  260. // TODO: find optimization
  261. // This method results in a copy instead of a real move.
  262. // Therefore, we need to delete the old instance.
  263. key.delete()
  264. } catch (e) {
  265. throw Exception.safe(e as SealError)
  266. }
  267. }
  268. }
  269. }
  270. export const RelinKeysInit = ({
  271. loader
  272. }: LoaderOptions): RelinKeysDependencies => {
  273. const library: Library = loader.library
  274. return RelinKeysConstructor(library)
  275. }