From 908ca3bff951db2362876bd3da529cf3d2dac913 Mon Sep 17 00:00:00 2001 From: Ruiyu Zhu Date: Tue, 2 Apr 2024 10:07:42 -0700 Subject: [PATCH] update publicity in swift-he (#77) Make some more functions public to ease PIR development --- Sources/SwiftHe/Ciphertext.swift | 10 ++-- Sources/SwiftHe/NoOpScheme.swift | 82 +++++++++++++++++--------------- Sources/SwiftHe/Scalar.swift | 2 +- 3 files changed, 49 insertions(+), 45 deletions(-) diff --git a/Sources/SwiftHe/Ciphertext.swift b/Sources/SwiftHe/Ciphertext.swift index aaa2ac56..6b07f044 100644 --- a/Sources/SwiftHe/Ciphertext.swift +++ b/Sources/SwiftHe/Ciphertext.swift @@ -220,7 +220,7 @@ public struct Ciphertext { } @inlinable - func convertToCanonicalFormat() throws -> Ciphertext + public func convertToCanonicalFormat() throws -> Ciphertext where Format == Coeff { if Scheme.CanonicalCiphertextFormat.self == Coeff.self { @@ -238,7 +238,7 @@ public struct Ciphertext { } @inlinable - func convertToCanonicalFormat() throws -> Ciphertext + public func convertToCanonicalFormat() throws -> Ciphertext where Format == Eval { if Scheme.CanonicalCiphertextFormat.self == Eval.self { @@ -299,7 +299,7 @@ extension Ciphertext: CustomStringConvertible { } } -extension Ciphertext { +public extension Ciphertext { // MARK: ciphertext + plaintext @inlinable @@ -492,7 +492,7 @@ extension Ciphertext { } } -extension Ciphertext where Format == Coeff { +public extension Ciphertext where Format == Coeff { mutating func multiplyInversePowerOfX(power: Int) throws { precondition(power >= 0) for index in polys.indices { @@ -501,7 +501,7 @@ extension Ciphertext where Format == Coeff { } } -extension Ciphertext where Format == Scheme.CanonicalCiphertextFormat { +public extension Ciphertext where Format == Scheme.CanonicalCiphertextFormat { mutating func applyGalois(element: Int, using key: GaloisKey) throws { try Scheme.applyGalois(ciphertext: &self, element: element, using: key) } diff --git a/Sources/SwiftHe/NoOpScheme.swift b/Sources/SwiftHe/NoOpScheme.swift index d0ff50a0..0d63b1a6 100644 --- a/Sources/SwiftHe/NoOpScheme.swift +++ b/Sources/SwiftHe/NoOpScheme.swift @@ -9,22 +9,22 @@ import Foundation // This is a no-op scheme for development and testing. The scheme simply takes the plaintext as "ciphertext" and totally // ignores any ciphertext coefficient moduli -struct NoOpScheme: HeScheme { - typealias Scalar = UInt64 - typealias CanonicalCiphertextFormat = Coeff +public struct NoOpScheme: HeScheme { + public typealias Scalar = UInt64 + public typealias CanonicalCiphertextFormat = Coeff - static var freshCiphertextPolyCount: Int { + public static var freshCiphertextPolyCount: Int { 1 } - static func generateSecretKey(context: Context) throws -> SecretKey { + public static func generateSecretKey(context: Context) throws -> SecretKey { let poly = try PolyRq.zero(context: PolyContext( degree: context.parameter.polyDegree, moduli: [context.parameter.plaintextModulus])) return SecretKey(poly: poly) } - static func generateEvaluationKey( + public static func generateEvaluationKey( context: Context, using _: SecretKey, galoisElements _: [Int], @@ -35,49 +35,53 @@ struct NoOpScheme: HeScheme { relinearizationKey: RelinearizationKey(keySwitchKey: KeySwitchKey(context: context, ciphers: []))) } - static func encode(context: Context, values: [some ScalarType], - format: EncodeFormat) throws -> CoeffPlaintext + public static func encode(context: Context, values: [some ScalarType], + format: EncodeFormat) throws -> CoeffPlaintext { try context.encode(values: values, format: format) } - static func encode(context: Context, values: [some ScalarType], - format: EncodeFormat, moduliCount _: Int) throws -> EvalPlaintext + public static func encode(context: Context, values: [some ScalarType], + format: EncodeFormat, moduliCount _: Int) throws -> EvalPlaintext { try encode(context: context, values: values, format: format).forwardNtt() } - static func encode(context: Context, values: [some ScalarType], - format: EncodeFormat) throws -> EvalPlaintext + public static func encode(context: Context, values: [some ScalarType], + format: EncodeFormat) throws -> EvalPlaintext { try encode(context: context, values: values, format: format, moduliCount: 1) } - static func decode(plaintext: CoeffPlaintext, format: EncodeFormat) throws -> [T] where T: ScalarType { + public static func decode(plaintext: CoeffPlaintext, format: EncodeFormat) throws -> [T] where T: ScalarType { try plaintext.context.decode(plaintext: plaintext, format: format) } - static func decode(plaintext: EvalPlaintext, format: EncodeFormat) throws -> [T] where T: ScalarType { + public static func decode(plaintext: EvalPlaintext, format: EncodeFormat) throws -> [T] where T: ScalarType { try decode(plaintext: plaintext.inverseNtt(), format: format) } - static func encrypt(_ plaintext: CoeffPlaintext, using _: SecretKey) throws -> CanonicalCiphertext { + public static func encrypt(_ plaintext: CoeffPlaintext, + using _: SecretKey) throws -> CanonicalCiphertext + { NoOpScheme.CoeffCiphertext( context: plaintext.context, polys: [plaintext.poly], correctionFactor: 1) } - static func decrypt(_ ciphertext: CoeffCiphertext, using _: SecretKey) throws -> CoeffPlaintext { + public static func decrypt(_ ciphertext: CoeffCiphertext, using _: SecretKey) throws -> CoeffPlaintext { NoOpScheme.CoeffPlaintext( context: ciphertext.context, poly: ciphertext.polys[0]) } - static func decrypt(_ ciphertext: EvalCiphertext, using secretKey: SecretKey) throws -> CoeffPlaintext { + public static func decrypt(_ ciphertext: EvalCiphertext, + using secretKey: SecretKey) throws -> CoeffPlaintext + { try decrypt(ciphertext.inverseNtt(), using: secretKey) } - static func rotateRows( + public static func rotateRows( ciphertext: inout CanonicalCiphertext, step: Int, evaluationKey _: EvaluationKey) throws @@ -86,7 +90,7 @@ struct NoOpScheme: HeScheme { ciphertext.polys[0] = ciphertext.polys[0].applyGalois(galoisElement: element) } - static func swapColumns( + public static func swapColumns( ciphertext: inout CanonicalCiphertext, evaluationKey _: EvaluationKey) throws { @@ -96,24 +100,24 @@ struct NoOpScheme: HeScheme { // MARK: plaintext += plaintext - static func addAssign(_ lhs: inout CoeffPlaintext, _ rhs: CoeffPlaintext) throws { + public static func addAssign(_ lhs: inout CoeffPlaintext, _ rhs: CoeffPlaintext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.poly += rhs.poly } - static func addAssign(_ lhs: inout EvalPlaintext, _ rhs: EvalPlaintext) throws { + public static func addAssign(_ lhs: inout EvalPlaintext, _ rhs: EvalPlaintext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.poly += rhs.poly } // MARK: ciphertext += plaintext - static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffPlaintext) throws { + public static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffPlaintext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] += rhs.poly } - static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: EvalPlaintext) throws { + public static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: EvalPlaintext) throws { try addAssign(&lhs, rhs.inverseNtt()) } @@ -123,19 +127,19 @@ struct NoOpScheme: HeScheme { try addAssign(&lhs, evalRhs) } - static func addAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalPlaintext) throws { + public static func addAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalPlaintext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] += rhs.poly } // MARK: ciphertext -= plaintext - static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffPlaintext) throws { + public static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffPlaintext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] -= rhs.poly } - static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: EvalPlaintext) throws { + public static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: EvalPlaintext) throws { try subAssign(&lhs, rhs.inverseNtt()) } @@ -145,42 +149,42 @@ struct NoOpScheme: HeScheme { try subAssign(&lhs, evalRhs) } - static func subAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalPlaintext) throws { + public static func subAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalPlaintext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] -= rhs.poly } // MARK: ciphertext += ciphertext - static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws { + public static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] += rhs.polys[0] } - static func addAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws { + public static func addAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] += rhs.polys[0] } // MARK: ciphertext -= ciphertext - static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws { + public static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] -= rhs.polys[0] } - static func subAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws { + public static func subAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] -= rhs.polys[0] } // MARK: ciphertext =- ciphertext - static func negAssign(_ ciphertext: inout EvalCiphertext) { + public static func negAssign(_ ciphertext: inout EvalCiphertext) { ciphertext.polys[0] = -ciphertext.polys[0] } - static func negAssign(_ ciphertext: inout CoeffCiphertext) { + public static func negAssign(_ ciphertext: inout CoeffCiphertext) { ciphertext.polys[0] = -ciphertext.polys[0] } @@ -207,15 +211,15 @@ struct NoOpScheme: HeScheme { try mulAssign(&lhs, evalRhs) } - static func mulAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalPlaintext) throws { + public static func mulAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalPlaintext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] *= rhs.poly } // MARK: ciphertext *= ciphertext - static func mulAssign(_ lhs: inout NoOpScheme.CanonicalCiphertext, - _ rhs: NoOpScheme.CanonicalCiphertext) throws + public static func mulAssign(_ lhs: inout NoOpScheme.CanonicalCiphertext, + _ rhs: NoOpScheme.CanonicalCiphertext) throws { try checkContextConsistency(lhs.context, rhs.context) lhs.polys[0] = try (lhs.polys[0].forwardNtt() * rhs.polys[0].forwardNtt()).inverseNtt() @@ -223,11 +227,11 @@ struct NoOpScheme: HeScheme { // MARK: ciphertext =-ciphertext - static func modSwitchDown(ciphertext _: inout CanonicalCiphertext) throws { + public static func modSwitchDown(ciphertext _: inout CanonicalCiphertext) throws { // mod switch down is no op in no-op scheme } - static func applyGalois( + public static func applyGalois( ciphertext: inout CanonicalCiphertext, element: Int, using _: GaloisKey) throws @@ -237,5 +241,5 @@ struct NoOpScheme: HeScheme { } } - static func relinearize(ciphertext _: inout CanonicalCiphertext, using _: RelinearizationKey) throws {} + public static func relinearize(ciphertext _: inout CanonicalCiphertext, using _: RelinearizationKey) throws {} } diff --git a/Sources/SwiftHe/Scalar.swift b/Sources/SwiftHe/Scalar.swift index 453d4238..f7ea7a24 100644 --- a/Sources/SwiftHe/Scalar.swift +++ b/Sources/SwiftHe/Scalar.swift @@ -139,7 +139,7 @@ extension UInt32 { } } -extension FixedWidthInteger { +public extension FixedWidthInteger { /// Get the base-2 logarithm of `self` for `self > 0` /// - Returns: log2(`self`) rounded down @inlinable var log2: Int {