Skip to content

Commit 1ccbb03

Browse files
committed
Decouple Context and Scheme
1 parent c89a195 commit 1ccbb03

File tree

62 files changed

+523
-436
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+523
-436
lines changed

Benchmarks/RlweBenchmark/RlweBenchmark.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func getRandomPlaintextData<T: ScalarType>(count: Int, in range: Range<T>) -> [T
4343

4444
struct RlweBenchmarkContext<Scheme: HeScheme>: Sendable {
4545
var encryptionParameters: EncryptionParameters<Scheme.Scalar>
46-
var context: Context<Scheme>
46+
var context: Context<Scheme.Scalar>
4747

4848
let data: [Scheme.Scalar]
4949
let signedData: [Scheme.SignedScalar]
@@ -163,7 +163,7 @@ func contextInitBenchmark<Scheme: HeScheme>(_: Scheme.Type, config: EncryptionPa
163163
let encryptionParameters = try EncryptionParameters<Scheme.Scalar>(config: config)
164164
benchmark.startMeasurement()
165165
for _ in benchmark.scaledIterations {
166-
try blackHole(_ = Context<Scheme>(encryptionParameters: encryptionParameters))
166+
try blackHole(_ = Context<Scheme.Scalar>(encryptionParameters: encryptionParameters))
167167
}
168168
}
169169
}
@@ -279,8 +279,7 @@ func decodeSignedSimdBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void {
279279
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
280280
benchmark.startMeasurement()
281281
for _ in benchmark.scaledIterations {
282-
try blackHole(
283-
benchmarkContext.coeffPlaintext.decode(format: .simd) as [Scheme.SignedScalar])
282+
try blackHole(benchmarkContext.coeffPlaintext.decode(format: .simd) as [Scheme.SignedScalar])
284283
}
285284
}
286285
}
@@ -292,7 +291,7 @@ func generateSecretKeyBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void
292291
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
293292
benchmark.startMeasurement()
294293
for _ in benchmark.scaledIterations {
295-
try blackHole(benchmarkContext.context.generateSecretKey())
294+
try blackHole(benchmarkContext.context.generateSecretKey() as SecretKey<Scheme>)
296295
}
297296
}
298297
}
@@ -320,8 +319,7 @@ func encryptBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void {
320319
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
321320
benchmark.startMeasurement()
322321
for _ in benchmark.scaledIterations {
323-
try blackHole(
324-
benchmarkContext.coeffPlaintext.encrypt(using: benchmarkContext.secretKey))
322+
try blackHole(benchmarkContext.coeffPlaintext.encrypt(using: benchmarkContext.secretKey))
325323
}
326324
}
327325
}
@@ -333,9 +331,7 @@ func decryptBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void {
333331
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
334332
benchmark.startMeasurement()
335333
for _ in benchmark.scaledIterations {
336-
try blackHole(
337-
benchmarkContext.evalCiphertext.decrypt(
338-
using: benchmarkContext.secretKey))
334+
try blackHole(benchmarkContext.evalCiphertext.decrypt(using: benchmarkContext.secretKey))
339335
}
340336
}
341337
}

Snippets/HomomorphicEncryption/BasicsSnippet.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import HomomorphicEncryption
2424
let encryptParams =
2525
try EncryptionParameters<UInt64>(from: .insecure_n_8_logq_5x18_logt_5)
2626
// Perform pre-computation for HE computation with these parameters.
27-
let context = try Context<Bfv<UInt64>>(encryptionParameters: encryptParams)
27+
let context = try Context<UInt64>(encryptionParameters: encryptParams)
2828

2929
// We encode N values using coefficient encoding.
3030
let values: [UInt64] = [8, 5, 12, 12, 15, 0, 8, 5]
@@ -33,7 +33,7 @@ let plaintext: Bfv<UInt64>.CoeffPlaintext = try context.encode(
3333
format: .coefficient)
3434

3535
// We generate a secret key and use it to encrypt the plaintext.
36-
let secretKey = try context.generateSecretKey()
36+
let secretKey: SecretKey<Bfv<UInt64>> = try context.generateSecretKey()
3737
var ciphertext = try plaintext.encrypt(using: secretKey)
3838

3939
// Decrypting the plaintext yields the original values.

Snippets/HomomorphicEncryption/EncryptionParametersSnippet.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ func summarize<Scheme: HeScheme>(
8585
parameters: EncryptionParameters<Scheme.Scalar>, _: Scheme.Type) throws
8686
{
8787
let values = (0..<8).map { Scheme.Scalar($0) }
88-
let context = try Context<Scheme>(encryptionParameters: parameters)
88+
let context = try Context<Scheme.Scalar>(encryptionParameters: parameters)
8989
let plaintext: Scheme.CoeffPlaintext = try context.encode(
9090
values: values,
9191
format: .coefficient)
92-
let secretKey = try context.generateSecretKey()
92+
let secretKey: SecretKey<Scheme> = try context.generateSecretKey()
9393
let ciphertext = try plaintext.encrypt(using: secretKey)
9494
let noiseBudget = try ciphertext.noiseBudget(
9595
using: secretKey,

Snippets/HomomorphicEncryption/EvaluationKeySnippet.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ let encryptionParameters =
4646
try EncryptionParameters<UInt32>(from: .insecure_n_8_logq_5x18_logt_5)
4747
precondition(encryptionParameters.plaintextModulus == 17)
4848
// Perform pre-computation for HE computation with these parameters.
49-
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptionParameters)
49+
let context = try Context<UInt32>(encryptionParameters: encryptionParameters)
5050

5151
// We encode N values using SIMD encoding.
5252
// Each value is a Bfv<UInt32>.Scalar, which is UInt32.
@@ -56,7 +56,7 @@ let plaintext: Bfv<UInt32>.CoeffPlaintext = try context.encode(
5656
format: .simd)
5757

5858
// We generate a secret key and encrypt the plaintext.
59-
let secretKey = try context.generateSecretKey()
59+
let secretKey: SecretKey<Bfv<UInt32>> = try context.generateSecretKey()
6060
var ciphertext = try plaintext.encrypt(using: secretKey)
6161

6262
// We generate an evaluation key. This is a key used in some HE operations.

Snippets/HomomorphicEncryption/MultiplicationSnippet.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ let encryptParams =
3434
try EncryptionParameters<UInt32>(from: .insecure_n_8_logq_5x18_logt_5)
3535
precondition(encryptParams.plaintextModulus == 17)
3636
// Perform pre-computation for HE computation with these parameters.
37-
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptParams)
37+
let context = try Context<UInt32>(encryptionParameters: encryptParams)
3838

3939
// We don't need to use all the slots in the encoding.
4040
// However, performing HE operations on ciphertexts with fewer slots doesn't give
@@ -46,7 +46,7 @@ let plaintext: Bfv<UInt32>.CoeffPlaintext = try context.encode(
4646
format: .simd)
4747

4848
// We generate a secret key and encrypt the plaintext.
49-
let secretKey = try context.generateSecretKey()
49+
let secretKey: SecretKey<Bfv<UInt32>> = try context.generateSecretKey()
5050
let ciphertext = try plaintext.encrypt(using: secretKey)
5151

5252
// Multiplication requires the ciphertext and plaintext to be in Evaluation

Snippets/HomomorphicEncryption/NoiseBudgetSnippet.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func checkDecryptsDecodes<Scheme: HeScheme>(
4545
let encryptionParameters =
4646
try EncryptionParameters<UInt32>(from: .insecure_n_8_logq_5x18_logt_5)
4747
// Perform pre-computation for HE computation with these parameters.
48-
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptionParameters)
48+
let context = try Context<UInt32>(encryptionParameters: encryptionParameters)
4949

5050
// We encode N values in coefficient format and SIMD encoding.
5151
let values = (0..<8).map { UInt32($0) }
@@ -54,7 +54,7 @@ let plaintext: Bfv<UInt32>.CoeffPlaintext = try context.encode(
5454
format: .simd)
5555

5656
// We generate a secret key and encrypt the plaintext.
57-
let secretKey = try context.generateSecretKey()
57+
let secretKey: SecretKey<Bfv<UInt32>> = try context.generateSecretKey()
5858
var ciphertext = try plaintext.encrypt(using: secretKey)
5959

6060
// The noiseBudget of a ciphertext is a measure of how many encrypted operations

Snippets/HomomorphicEncryption/SerializationSnippet.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ extension SerializedCiphertext {
3636
let encryptionParameters =
3737
try EncryptionParameters<UInt32>(from: .n_4096_logq_27_28_28_logt_5)
3838
// Perform pre-computation for HE computation with these parameters.
39-
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptionParameters)
39+
let context = try Context<UInt32>(encryptionParameters: encryptionParameters)
4040

4141
// We encode some values in coefficient format and coefficient encoding.
4242
let values = (0..<8).map { UInt32($0) }
@@ -45,7 +45,7 @@ let plaintext: Bfv<UInt32>.CoeffPlaintext = try context.encode(
4545
format: .coefficient)
4646

4747
// We generate a secret key and encrypt the plaintext.
48-
let secretKey = try context.generateSecretKey()
48+
let secretKey: SecretKey<Bfv<UInt32>> = try context.generateSecretKey()
4949
var ciphertext: Bfv<UInt32>.CanonicalCiphertext = try plaintext
5050
.encrypt(using: secretKey)
5151

Sources/BenchmarkUtilities/PirBenchmarkUtilities.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ extension PrivateInformationRetrieval.Response {
8383

8484
struct ProcessBenchmarkContext<Server: IndexPirServer> {
8585
let database: [[UInt8]]
86-
let context: Context<Server.Scheme>
86+
let context: Context<Server.Scheme.Scalar>
8787
let parameter: IndexPirParameter
8888
init(server _: Server.Type, pirConfig: IndexPirConfig,
8989
parameterConfig: PirEncryptionParametersConfig) throws
@@ -171,7 +171,7 @@ struct IndexPirBenchmarkContext<Server: IndexPirServer, Client: IndexPirClient>
171171
{
172172
let encryptParameter: EncryptionParameters<Server.Scheme.Scalar> =
173173
try EncryptionParameters(from: parameterConfig)
174-
let context = try Context<Server.Scheme>(encryptionParameters: encryptParameter)
174+
let context = try Context<Server.Scheme.Scalar>(encryptionParameters: encryptParameter)
175175
let indexPirParameters = Server.generateParameter(config: pirConfig, with: context)
176176
let database = getDatabaseForTesting(
177177
numberOfEntries: pirConfig.entryCount,
@@ -286,7 +286,7 @@ struct KeywordPirBenchmarkContext<IndexServer: IndexPirServer, IndexClient: Inde
286286
{
287287
let encryptParameter: EncryptionParameters<Server.Scheme.Scalar> =
288288
try EncryptionParameters(from: parameterConfig)
289-
let context = try Context<Server.Scheme>(encryptionParameters: encryptParameter)
289+
let context = try Context<Server.Scheme.Scalar>(encryptionParameters: encryptParameter)
290290
let rows = (0..<databaseCount).map { index in KeywordValuePair(
291291
keyword: [UInt8](String(index).utf8),
292292
value: (0..<payloadSize).map { _ in UInt8.random(in: 0..<UInt8.max) })

Sources/BenchmarkUtilities/PnnsBenchmarkUtilities.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ extension PrivateNearestNeighborSearch.Response {
188188

189189
struct PnnsProcessBenchmarkContext<Scheme: HeScheme> {
190190
let database: Database
191-
let contexts: [Context<Scheme>]
191+
let contexts: [Context<Scheme.Scalar>]
192192
let serverConfig: ServerConfig<Scheme>
193193

194194
init(databaseConfig: DatabaseConfig,
@@ -305,7 +305,7 @@ struct PnnsBenchmarkContext<Scheme: HeScheme> {
305305

306306
let database = getDatabaseForTesting(config: databaseConfig)
307307
let contexts = try clientConfig.encryptionParameters
308-
.map { encryptionParameters in try Context<Scheme>(encryptionParameters: encryptionParameters) }
308+
.map { encryptionParameters in try Context<Scheme.Scalar>(encryptionParameters: encryptionParameters) }
309309
self.processedDatabase = try database.process(config: serverConfig, contexts: contexts)
310310
self.client = try Client(config: clientConfig, contexts: contexts)
311311
self.server = try Server(database: processedDatabase)

Sources/HomomorphicEncryption/Bfv/Bfv+Encode.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,23 @@ extension Bfv {
2424

2525
@inlinable
2626
// swiftlint:disable:next missing_docs attributes
27-
public static func encode(context: Context<Bfv<T>>, values: some Collection<Scalar>,
27+
public static func encode(context: Context<T>, values: some Collection<Scalar>,
2828
format: EncodeFormat) throws -> CoeffPlaintext
2929
{
3030
try context.encode(values: values, format: format)
3131
}
3232

3333
@inlinable
3434
// swiftlint:disable:next missing_docs attributes
35-
public static func encode(context: Context<Bfv<T>>, signedValues: some Collection<SignedScalar>,
35+
public static func encode(context: Context<T>, signedValues: some Collection<SignedScalar>,
3636
format: EncodeFormat) throws -> CoeffPlaintext
3737
{
3838
try context.encode(signedValues: signedValues, format: format)
3939
}
4040

4141
@inlinable
4242
// swiftlint:disable:next missing_docs attributes
43-
public static func encode(context: Context<Bfv<T>>, values: some Collection<Scalar>, format: EncodeFormat,
43+
public static func encode(context: Context<T>, values: some Collection<Scalar>, format: EncodeFormat,
4444
moduliCount: Int?) throws -> EvalPlaintext
4545
{
4646
let coeffPlaintext = try Self.encode(context: context, values: values, format: format)
@@ -50,7 +50,7 @@ extension Bfv {
5050
@inlinable
5151
// swiftlint:disable:next missing_docs attributes
5252
public static func encode(
53-
context: Context<Bfv<T>>,
53+
context: Context<T>,
5454
signedValues: some Collection<SignedScalar>,
5555
format: EncodeFormat,
5656
moduliCount: Int?) throws -> EvalPlaintext

Sources/HomomorphicEncryption/Bfv/Bfv+Encrypt.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 Apple Inc. and the Swift Homomorphic Encryption project authors
1+
// Copyright 2024-2025 Apple Inc. and the Swift Homomorphic Encryption project authors
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@ extension Bfv {
2323

2424
@inlinable
2525
// swiftlint:disable:next missing_docs attributes
26-
public static func zeroCiphertextCoeff(context: Context<Self>, moduliCount: Int?) throws -> CoeffCiphertext {
26+
public static func zeroCiphertextCoeff(context: Context<Scalar>, moduliCount: Int?) throws -> CoeffCiphertext {
2727
let moduliCount = moduliCount ?? context.ciphertextContext.moduli.count
2828
let zeroPoly = try PolyRq<Scalar, Coeff>.zero(
2929
context: context.ciphertextContext
@@ -34,7 +34,7 @@ extension Bfv {
3434

3535
@inlinable
3636
// swiftlint:disable:next missing_docs attributes
37-
public static func zeroCiphertextEval(context: Context<Self>, moduliCount: Int?) throws -> EvalCiphertext {
37+
public static func zeroCiphertextEval(context: Context<Scalar>, moduliCount: Int?) throws -> EvalCiphertext {
3838
let moduliCount = moduliCount ?? context.ciphertextContext.moduli.count
3939
let zeroPoly = try PolyRq<Scalar, Eval>.zero(
4040
context: context.ciphertextContext
@@ -143,15 +143,15 @@ extension Bfv {
143143
}
144144

145145
@inlinable
146-
static func encryptZero(for context: Context<Bfv<T>>,
146+
static func encryptZero(for context: Context<T>,
147147
using secretKey: SecretKey<Bfv<T>>) throws -> CanonicalCiphertext
148148
{
149149
let ciphertextContext = context.ciphertextContext
150150
return try encryptZero(for: context, using: secretKey, with: ciphertextContext)
151151
}
152152

153153
@inlinable
154-
static func encryptZero(for context: Context<Bfv<T>>,
154+
static func encryptZero(for context: Context<T>,
155155
using secretKey: SecretKey<Bfv<T>>,
156156
with ciphertextContext: PolyContext<T>) throws -> CanonicalCiphertext
157157
{

Sources/HomomorphicEncryption/Bfv/Bfv+Keys.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 Apple Inc. and the Swift Homomorphic Encryption project authors
1+
// Copyright 2024-2025 Apple Inc. and the Swift Homomorphic Encryption project authors
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@ import ModularArithmetic
1717
extension Bfv {
1818
@inlinable
1919
// swiftlint:disable:next missing_docs attributes
20-
public static func generateSecretKey(context: Context<Self>) throws -> SecretKey<Bfv<T>> {
20+
public static func generateSecretKey(context: Context<Scalar>) throws -> SecretKey<Bfv<T>> {
2121
var s = PolyRq<Scalar, Coeff>.zero(context: context.secretKeyContext)
2222
var rng = SystemRandomNumberGenerator()
2323
s.randomizeTernary(using: &rng)
@@ -28,7 +28,7 @@ extension Bfv {
2828
@inlinable
2929
// swiftlint:disable:next missing_docs attributes
3030
public static func generateEvaluationKey(
31-
context: Context<Bfv<T>>,
31+
context: Context<T>,
3232
config: EvaluationKeyConfig,
3333
using secretKey: borrowing SecretKey<Bfv<T>>) throws -> EvaluationKey<Bfv<T>>
3434
{
@@ -55,7 +55,7 @@ extension Bfv {
5555
}
5656

5757
@inlinable
58-
static func generateRelinearizationKey(context: Context<Self>,
58+
static func generateRelinearizationKey(context: Context<Scalar>,
5959
secretKey: borrowing SecretKey<Self>) throws
6060
-> RelinearizationKey<Self>
6161
{
@@ -65,7 +65,7 @@ extension Bfv {
6565
}
6666

6767
@inlinable
68-
static func generateKeySwitchKey(context: Context<Bfv<T>>,
68+
static func generateKeySwitchKey(context: Context<T>,
6969
currentKey: consuming PolyRq<T, Eval>,
7070
targetKey: borrowing SecretKey<Bfv<T>>) throws -> KeySwitchKey<Bfv<T>>
7171
{
@@ -120,7 +120,7 @@ extension Bfv {
120120
/// - seealso: ``Bfv/generateEvaluationKey(context:config:using:)``.
121121
@inlinable
122122
static func computeKeySwitchingUpdate(
123-
context: Context<Bfv<T>>,
123+
context: Context<T>,
124124
target: PolyRq<Scalar, CanonicalCiphertextFormat>,
125125
keySwitchingKey: KeySwitchKey<Self>) throws -> [PolyRq<Scalar, CanonicalCiphertextFormat>]
126126
{

Sources/HomomorphicEncryption/Ciphertext.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
1717
public typealias Scalar = Scheme.Scalar
1818

1919
/// Context for HE computation.
20-
public let context: Context<Scheme>
20+
public let context: Context<Scheme.Scalar>
2121
@usableFromInline package var polys: [PolyRq<Scalar, Format>]
2222
@usableFromInline var correctionFactor: Scalar
2323
@usableFromInline var seed: [UInt8] = []
@@ -33,7 +33,7 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
3333

3434
@inlinable
3535
init(
36-
context: Context<Scheme>,
36+
context: Context<Scheme.Scalar>,
3737
polys: [PolyRq<Scalar, Format>],
3838
correctionFactor: Scalar,
3939
seed: [UInt8] = [])
@@ -64,7 +64,9 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
6464
/// ```
6565
/// - seelaso: ``Ciphertext/isTransparent()``
6666
@inlinable
67-
public static func zero(context: Context<Scheme>, moduliCount: Int? = nil) throws -> Ciphertext<Scheme, Format> {
67+
public static func zero(context: Context<Scheme.Scalar>,
68+
moduliCount: Int? = nil) throws -> Ciphertext<Scheme, Format>
69+
{
6870
try Scheme.zero(context: context, moduliCount: moduliCount)
6971
}
7072

0 commit comments

Comments
 (0)