Skip to content

Decouple Context and Scheme #210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions Benchmarks/RlweBenchmark/RlweBenchmark.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func getRandomPlaintextData<T: ScalarType>(count: Int, in range: Range<T>) -> [T

struct RlweBenchmarkContext<Scheme: HeScheme>: Sendable {
var encryptionParameters: EncryptionParameters<Scheme.Scalar>
var context: Context<Scheme>
var context: Context<Scheme.Scalar>

let data: [Scheme.Scalar]
let signedData: [Scheme.SignedScalar]
Expand Down Expand Up @@ -163,7 +163,7 @@ func contextInitBenchmark<Scheme: HeScheme>(_: Scheme.Type, config: EncryptionPa
let encryptionParameters = try EncryptionParameters<Scheme.Scalar>(config: config)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
try blackHole(_ = Context<Scheme>(encryptionParameters: encryptionParameters))
try blackHole(_ = Context<Scheme.Scalar>(encryptionParameters: encryptionParameters))
}
}
}
Expand Down Expand Up @@ -279,8 +279,7 @@ func decodeSignedSimdBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void {
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
try blackHole(
benchmarkContext.coeffPlaintext.decode(format: .simd) as [Scheme.SignedScalar])
try blackHole(benchmarkContext.coeffPlaintext.decode(format: .simd) as [Scheme.SignedScalar])
}
}
}
Expand All @@ -292,7 +291,7 @@ func generateSecretKeyBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
try blackHole(benchmarkContext.context.generateSecretKey())
try blackHole(benchmarkContext.context.generateSecretKey() as SecretKey<Scheme>)
}
}
}
Expand Down Expand Up @@ -320,8 +319,7 @@ func encryptBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void {
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
try blackHole(
benchmarkContext.coeffPlaintext.encrypt(using: benchmarkContext.secretKey))
try blackHole(benchmarkContext.coeffPlaintext.encrypt(using: benchmarkContext.secretKey))
}
}
}
Expand All @@ -333,9 +331,7 @@ func decryptBenchmark<Scheme: HeScheme>(_: Scheme.Type) -> () -> Void {
let benchmarkContext: RlweBenchmarkContext<Scheme> = try StaticRlweBenchmarkContext.getBenchmarkContext()
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
try blackHole(
benchmarkContext.evalCiphertext.decrypt(
using: benchmarkContext.secretKey))
try blackHole(benchmarkContext.evalCiphertext.decrypt(using: benchmarkContext.secretKey))
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions Snippets/HomomorphicEncryption/BasicsSnippet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import HomomorphicEncryption
let encryptParams =
try EncryptionParameters<UInt64>(from: .insecure_n_8_logq_5x18_logt_5)
// Perform pre-computation for HE computation with these parameters.
let context = try Context<Bfv<UInt64>>(encryptionParameters: encryptParams)
let context = try Context<UInt64>(encryptionParameters: encryptParams)

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

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

// Decrypting the plaintext yields the original values.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ func summarize<Scheme: HeScheme>(
parameters: EncryptionParameters<Scheme.Scalar>, _: Scheme.Type) throws
{
let values = (0..<8).map { Scheme.Scalar($0) }
let context = try Context<Scheme>(encryptionParameters: parameters)
let context = try Context<Scheme.Scalar>(encryptionParameters: parameters)
let plaintext: Scheme.CoeffPlaintext = try context.encode(
values: values,
format: .coefficient)
let secretKey = try context.generateSecretKey()
let secretKey: SecretKey<Scheme> = try context.generateSecretKey()
let ciphertext = try plaintext.encrypt(using: secretKey)
let noiseBudget = try ciphertext.noiseBudget(
using: secretKey,
Expand Down
4 changes: 2 additions & 2 deletions Snippets/HomomorphicEncryption/EvaluationKeySnippet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ let encryptionParameters =
try EncryptionParameters<UInt32>(from: .insecure_n_8_logq_5x18_logt_5)
precondition(encryptionParameters.plaintextModulus == 17)
// Perform pre-computation for HE computation with these parameters.
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptionParameters)
let context = try Context<UInt32>(encryptionParameters: encryptionParameters)

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

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

// We generate an evaluation key. This is a key used in some HE operations.
Expand Down
4 changes: 2 additions & 2 deletions Snippets/HomomorphicEncryption/MultiplicationSnippet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ let encryptParams =
try EncryptionParameters<UInt32>(from: .insecure_n_8_logq_5x18_logt_5)
precondition(encryptParams.plaintextModulus == 17)
// Perform pre-computation for HE computation with these parameters.
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptParams)
let context = try Context<UInt32>(encryptionParameters: encryptParams)

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

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

// Multiplication requires the ciphertext and plaintext to be in Evaluation
Expand Down
4 changes: 2 additions & 2 deletions Snippets/HomomorphicEncryption/NoiseBudgetSnippet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func checkDecryptsDecodes<Scheme: HeScheme>(
let encryptionParameters =
try EncryptionParameters<UInt32>(from: .insecure_n_8_logq_5x18_logt_5)
// Perform pre-computation for HE computation with these parameters.
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptionParameters)
let context = try Context<UInt32>(encryptionParameters: encryptionParameters)

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

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

// The noiseBudget of a ciphertext is a measure of how many encrypted operations
Expand Down
4 changes: 2 additions & 2 deletions Snippets/HomomorphicEncryption/SerializationSnippet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extension SerializedCiphertext {
let encryptionParameters =
try EncryptionParameters<UInt32>(from: .n_4096_logq_27_28_28_logt_5)
// Perform pre-computation for HE computation with these parameters.
let context = try Context<Bfv<UInt32>>(encryptionParameters: encryptionParameters)
let context = try Context<UInt32>(encryptionParameters: encryptionParameters)

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

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

Expand Down
6 changes: 3 additions & 3 deletions Sources/BenchmarkUtilities/PirBenchmarkUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ extension PrivateInformationRetrieval.Response {

struct ProcessBenchmarkContext<Server: IndexPirServer> {
let database: [[UInt8]]
let context: Context<Server.Scheme>
let context: Context<Server.Scheme.Scalar>
let parameter: IndexPirParameter
init(server _: Server.Type, pirConfig: IndexPirConfig,
parameterConfig: PirEncryptionParametersConfig) throws
Expand Down Expand Up @@ -171,7 +171,7 @@ struct IndexPirBenchmarkContext<Server: IndexPirServer, Client: IndexPirClient>
{
let encryptParameter: EncryptionParameters<Server.Scheme.Scalar> =
try EncryptionParameters(from: parameterConfig)
let context = try Context<Server.Scheme>(encryptionParameters: encryptParameter)
let context = try Context<Server.Scheme.Scalar>(encryptionParameters: encryptParameter)
let indexPirParameters = Server.generateParameter(config: pirConfig, with: context)
let database = getDatabaseForTesting(
numberOfEntries: pirConfig.entryCount,
Expand Down Expand Up @@ -286,7 +286,7 @@ struct KeywordPirBenchmarkContext<IndexServer: IndexPirServer, IndexClient: Inde
{
let encryptParameter: EncryptionParameters<Server.Scheme.Scalar> =
try EncryptionParameters(from: parameterConfig)
let context = try Context<Server.Scheme>(encryptionParameters: encryptParameter)
let context = try Context<Server.Scheme.Scalar>(encryptionParameters: encryptParameter)
let rows = (0..<databaseCount).map { index in KeywordValuePair(
keyword: [UInt8](String(index).utf8),
value: (0..<payloadSize).map { _ in UInt8.random(in: 0..<UInt8.max) })
Expand Down
4 changes: 2 additions & 2 deletions Sources/BenchmarkUtilities/PnnsBenchmarkUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ extension PrivateNearestNeighborSearch.Response {

struct PnnsProcessBenchmarkContext<Scheme: HeScheme> {
let database: Database
let contexts: [Context<Scheme>]
let contexts: [Context<Scheme.Scalar>]
let serverConfig: ServerConfig<Scheme>

init(databaseConfig: DatabaseConfig,
Expand Down Expand Up @@ -305,7 +305,7 @@ struct PnnsBenchmarkContext<Scheme: HeScheme> {

let database = getDatabaseForTesting(config: databaseConfig)
let contexts = try clientConfig.encryptionParameters
.map { encryptionParameters in try Context<Scheme>(encryptionParameters: encryptionParameters) }
.map { encryptionParameters in try Context<Scheme.Scalar>(encryptionParameters: encryptionParameters) }
self.processedDatabase = try database.process(config: serverConfig, contexts: contexts)
self.client = try Client(config: clientConfig, contexts: contexts)
self.server = try Server(database: processedDatabase)
Expand Down
8 changes: 4 additions & 4 deletions Sources/HomomorphicEncryption/Bfv/Bfv+Encode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@ extension Bfv {

@inlinable
// swiftlint:disable:next missing_docs attributes
public static func encode(context: Context<Bfv<T>>, values: some Collection<Scalar>,
public static func encode(context: Context<T>, values: some Collection<Scalar>,
format: EncodeFormat) throws -> CoeffPlaintext
{
try context.encode(values: values, format: format)
}

@inlinable
// swiftlint:disable:next missing_docs attributes
public static func encode(context: Context<Bfv<T>>, signedValues: some Collection<SignedScalar>,
public static func encode(context: Context<T>, signedValues: some Collection<SignedScalar>,
format: EncodeFormat) throws -> CoeffPlaintext
{
try context.encode(signedValues: signedValues, format: format)
}

@inlinable
// swiftlint:disable:next missing_docs attributes
public static func encode(context: Context<Bfv<T>>, values: some Collection<Scalar>, format: EncodeFormat,
public static func encode(context: Context<T>, values: some Collection<Scalar>, format: EncodeFormat,
moduliCount: Int?) throws -> EvalPlaintext
{
let coeffPlaintext = try Self.encode(context: context, values: values, format: format)
Expand All @@ -50,7 +50,7 @@ extension Bfv {
@inlinable
// swiftlint:disable:next missing_docs attributes
public static func encode(
context: Context<Bfv<T>>,
context: Context<T>,
signedValues: some Collection<SignedScalar>,
format: EncodeFormat,
moduliCount: Int?) throws -> EvalPlaintext
Expand Down
10 changes: 5 additions & 5 deletions Sources/HomomorphicEncryption/Bfv/Bfv+Encrypt.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Apple Inc. and the Swift Homomorphic Encryption project authors
// Copyright 2024-2025 Apple Inc. and the Swift Homomorphic Encryption project authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -23,7 +23,7 @@ extension Bfv {

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

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

@inlinable
static func encryptZero(for context: Context<Bfv<T>>,
static func encryptZero(for context: Context<T>,
using secretKey: SecretKey<Bfv<T>>) throws -> CanonicalCiphertext
{
let ciphertextContext = context.ciphertextContext
return try encryptZero(for: context, using: secretKey, with: ciphertextContext)
}

@inlinable
static func encryptZero(for context: Context<Bfv<T>>,
static func encryptZero(for context: Context<T>,
using secretKey: SecretKey<Bfv<T>>,
with ciphertextContext: PolyContext<T>) throws -> CanonicalCiphertext
{
Expand Down
12 changes: 6 additions & 6 deletions Sources/HomomorphicEncryption/Bfv/Bfv+Keys.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Apple Inc. and the Swift Homomorphic Encryption project authors
// Copyright 2024-2025 Apple Inc. and the Swift Homomorphic Encryption project authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,7 +17,7 @@ import ModularArithmetic
extension Bfv {
@inlinable
// swiftlint:disable:next missing_docs attributes
public static func generateSecretKey(context: Context<Self>) throws -> SecretKey<Bfv<T>> {
public static func generateSecretKey(context: Context<Scalar>) throws -> SecretKey<Bfv<T>> {
var s = PolyRq<Scalar, Coeff>.zero(context: context.secretKeyContext)
var rng = SystemRandomNumberGenerator()
s.randomizeTernary(using: &rng)
Expand All @@ -28,7 +28,7 @@ extension Bfv {
@inlinable
// swiftlint:disable:next missing_docs attributes
public static func generateEvaluationKey(
context: Context<Bfv<T>>,
context: Context<T>,
config: EvaluationKeyConfig,
using secretKey: borrowing SecretKey<Bfv<T>>) throws -> EvaluationKey<Bfv<T>>
{
Expand All @@ -55,7 +55,7 @@ extension Bfv {
}

@inlinable
static func generateRelinearizationKey(context: Context<Self>,
static func generateRelinearizationKey(context: Context<Scalar>,
secretKey: borrowing SecretKey<Self>) throws
-> RelinearizationKey<Self>
{
Expand All @@ -65,7 +65,7 @@ extension Bfv {
}

@inlinable
static func generateKeySwitchKey(context: Context<Bfv<T>>,
static func generateKeySwitchKey(context: Context<T>,
currentKey: consuming PolyRq<T, Eval>,
targetKey: borrowing SecretKey<Bfv<T>>) throws -> KeySwitchKey<Bfv<T>>
{
Expand Down Expand Up @@ -120,7 +120,7 @@ extension Bfv {
/// - seealso: ``Bfv/generateEvaluationKey(context:config:using:)``.
@inlinable
static func computeKeySwitchingUpdate(
context: Context<Bfv<T>>,
context: Context<T>,
target: PolyRq<Scalar, CanonicalCiphertextFormat>,
keySwitchingKey: KeySwitchKey<Self>) throws -> [PolyRq<Scalar, CanonicalCiphertextFormat>]
{
Expand Down
8 changes: 5 additions & 3 deletions Sources/HomomorphicEncryption/Ciphertext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
public typealias Scalar = Scheme.Scalar

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

@inlinable
init(
context: Context<Scheme>,
context: Context<Scheme.Scalar>,
polys: [PolyRq<Scalar, Format>],
correctionFactor: Scalar,
seed: [UInt8] = [])
Expand Down Expand Up @@ -64,7 +64,9 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
/// ```
/// - seelaso: ``Ciphertext/isTransparent()``
@inlinable
public static func zero(context: Context<Scheme>, moduliCount: Int? = nil) throws -> Ciphertext<Scheme, Format> {
public static func zero(context: Context<Scheme.Scalar>,
moduliCount: Int? = nil) throws -> Ciphertext<Scheme, Format>
{
try Scheme.zero(context: context, moduliCount: moduliCount)
}

Expand Down
Loading