cipherUtils

package
v0.0.0-...-9e2d205 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2023 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package contains the logic for all operations between ciphertext and plaintexts

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecInput

func DecInput(XEnc *EncInput, Box CkksBox) [][]float64

Given a block input matrix, decrypts and returns the underlying original matrix The sub-matrices are also transposed (remember that they are in form flatten(A.T))

func DecodeInput

func DecodeInput(XEnc *PlainInput, Box CkksBox) [][]float64

Given a block input matrix, decrypts and returns the underlying original matrix The sub-matrices are also transposed (remember that they are in form flatten(A.T))

func DiagMulCt

func DiagMulCt(input *ckks.Ciphertext, dimIn, dimMid, dimOut int, weights DiagMat, prepack bool, Box CkksBox) (res *ckks.Ciphertext)

Multiplies a ciphertext with a weight matrix in diagonal form: W x A.T

func DiagMulPt

func DiagMulPt(input *ckks.Plaintext, dimIn int, weights DiagMat, Box CkksBox) (res *ckks.Ciphertext)

Multiplies a plaintext with a weight matrix in diagonal form: W x A.T

func EncodeInput

func EncodeInput(level int, scale float64, w [][]float64, Box CkksBox) *ckks.Plaintext

func EncryptInput

func EncryptInput(level int, scale float64, w [][]float64, Box CkksBox) *ckks.Ciphertext

func FormatInput

func FormatInput(w [][]float64) (v []float64)

Transposes and flattens input

func FormatWeights

func FormatWeights(w [][]float64, leftdim int) (m map[int][]complex128)

Format weights in diagonal form for multiplication algorithm Additionally use the complex trick to effectively divide by half the size of the matrix to be multiplied refer to page 3: https://www.biorxiv.org/content/biorxiv/early/2022/01/11/2022.01.10.475610/DC1/embed/media-1.pdf?download=true

func GenRotationsForRepackCols

func GenRotationsForRepackCols(innerR, currCols, innerC, newColP int) []int

func GetAvgComplexity

func GetAvgComplexity(s *Split) float64

Compute tha average multiplication complexity of a series of splits

func GetComplexity

func GetComplexity(s *Split) float64

Compute tha total multiplication complexity of a series of splits

func GetFillRatio

func GetFillRatio(rows, cols, replicaFactor int, slotsAvailable float64) float64

func GetOptimalInnerRows

func GetOptimalInnerRows(inputInnerCols int, maxInnerCols int, params ckks.Parameters) int

Computes the optimal number of rows for input sub-matrices. Takes the innerCols of the Input and the maxInnerCols of all the weights in the pipeline

func GetReplicaFactor

func GetReplicaFactor(dimMid, dimOut int) int

Gets the replication factor used for the multipication algorithm given the inner rows and cols of the weight block-matrix

func Mask

func Mask(ct *ckks.Ciphertext, Box CkksBox) *ring.Poly

Masks ct = Enc(msg, sk_server) = (ct0, ct1) as (ct0 + Enc(0, sk_client), ct1)

func Prepack

func Prepack(input *ckks.Ciphertext, dimIn, dimMid, dimOut int, eval ckks.Evaluator)

Prepacking cipher

func PrepackBlocks

func PrepackBlocks(X BlocksOperand, dimOut int, Box CkksBox)

Applies complex packing to Blocks. dimOut should be the innerCols of the first weight in the layers

func PrepackClearText

func PrepackClearText(input *ckks.Plaintext, dimIn, dimMid, dimOut int, Box CkksBox) *ckks.Plaintext

Prepacking plain

func PrintDebugBlocks

func PrintDebugBlocks(Xenc *EncInput, Pt *plainUtils.BMatrix, thresh float64, Box CkksBox)

Debug stats for block matrix

func RepackCols

func RepackCols(X *EncInput, colP int, Box CkksBox)

Repacks block matrix column partitions to have newColP = colP. Does not involve multiplication or rescaling

func RotatePlaintext

func RotatePlaintext(pt *ckks.Plaintext, rotations []int, box CkksBox) map[int]*ckks.Plaintext

returns map of Plaintexts, where rot[i] plaintext is rotated by rot[i] to the left

func SerializeBox

func SerializeBox(path string, Box CkksBox)

serializes keys to disk

func UnMask

func UnMask(pt *ckks.Plaintext, mask_c1 *ring.Poly, Box CkksBox)

Removes mask from pt = (msg + Enc(0,sk_client) -> msg

Types

type Activator

type Activator struct {
	NumOfActivations int
	// contains filtered or unexported fields
}

Handles an activation layer with a polynomial function on an EncInput

func NewActivator

func NewActivator(numOfActivations int, poolSize int) (*Activator, error)

Creates a new Activator. Takes lavel, scale, as well as the blocks and sub-matrices dimentions, of the output of the previous linear layer Identity is not considered an activation, so don't count it for numOfActivations

func (*Activator) ActivateBlocks

func (Act *Activator) ActivateBlocks(X *EncInput, layer int, Box CkksBox)

Evaluates a polynomial on the ciphertext. If no activation is at layer, applies identity

func (*Activator) AddActivation

func (Act *Activator) AddActivation(activation utils.ChebyPolyApprox, layer, level int, scale float64, innerRows, innerCols int, Box CkksBox)

Add activation functions at layer. Takes level and scale of ct to activate at layer, as well its inner dimention You don't have to add identity activations

func (*Activator) LevelsOfAct

func (Act *Activator) LevelsOfAct(layer int) int

returns levels needed for activation at layer

type Adder

type Adder struct {
	// contains filtered or unexported fields
}

Deals with addition between encrypted or plaintext encoded block matrices

func NewAdder

func NewAdder(poolSize int) *Adder

func (*Adder) AddBias

func (Ad *Adder) AddBias(X *EncInput, B BlocksOperand, Box CkksBox)

Addition between encrypted input and bias. This modifies X

type BlockSplit

type BlockSplit struct {
	Rows, Cols, InnerRows, InnerCols, RowP, ColP int
}

Describes how to split a matrix

type BlocksOperand

type BlocksOperand interface {
	GetBlock(i, j int) interface{}
	//Returns RowP and ColP. Note that, if this is a weight, actually RowP will represent column partition
	//and viceversa since weights are block transposed
	GetPartitions() (int, int)
	GetInnerDims() (int, int)
	GetRealDims() (int, int)
	GetRotations(params ckks.Parameters) []int
	Level() int
	Scale() float64
}

Interface for generic block matrix. In can be a plaintext or ciphertext matrix

type Bootstrapper

type Bootstrapper struct {
	// contains filtered or unexported fields
}

Centralized bootstrapper. Homomorphically evaluates decryption circuit

func NewBootstrapper

func NewBootstrapper(poolSize int) *Bootstrapper

func (*Bootstrapper) Bootstrap

func (Btp *Bootstrapper) Bootstrap(X *EncInput, Box CkksBox)

Centralized Bootstrapping

type CkksBox

type CkksBox struct {
	Params       ckks.Parameters
	BtpParams    *bootstrapping.Parameters
	Encoder      ckks.Encoder
	Evaluator    ckks.Evaluator
	Encryptor    ckks.Encryptor
	Decryptor    ckks.Decryptor
	BootStrapper *bootstrapping.Bootstrapper
	Sk           *rlwe.SecretKey
	// contains filtered or unexported fields
}

wrapper for the classes needed to perform encrypted operations, like a crypto-ToolBox

func BoxShallowCopy

func BoxShallowCopy(Box CkksBox) CkksBox

func BoxWithRotations

func BoxWithRotations(Box CkksBox, rotations []int, withBtp bool, btpParams *bootstrapping.Parameters) CkksBox

returns Box with Evaluator and Bootstrapper if needed

func DeserealizeBox

func DeserealizeBox(path string, params ckks.Parameters, btpParams *bootstrapping.Parameters, withBtp bool) CkksBox

loads serialized keys from disk into a fresh box

func NewBox

func NewBox(params ckks.Parameters) CkksBox

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config from splitter

type DebugStats

type DebugStats struct {
	MinPrec  float64
	AvgPrec  float64
	MaxPrec  float64
	MaxValue float64
	L2Dist   float64
}

Statistics for debug

func PrintDebug

func PrintDebug(ciphertext *ckks.Ciphertext, valuesWant []complex128, thresh float64, Box CkksBox) DebugStats

Debug stats for one ciphertext

type DiagMat

type DiagMat interface {
	GetDiags() map[int]ckks.Operand
	GetRotations(parameters ckks.Parameters) []int
	IsEncrypted() bool
}

A matrix in diagonal form

type EncDiagMat

type EncDiagMat struct {
	//store an encrypted weight matrix in diagonal form
	Diags        map[int]*ckks.Ciphertext //enc diagonals
	InnerRows    int                      //rows of sub-matrix
	InnerCols    int
	LeftR, LeftC int //rows cols of left matrix
	Encrypted    bool
}

Encrypted matrix in diagonal form

func EncryptWeights

func EncryptWeights(level int, w [][]float64, leftR, leftC int, Box CkksBox) *EncDiagMat

takes level, weight matrix, rows of input matrix to be multiplied, and box. Returns encrypted weight in diagonal form

func (*EncDiagMat) GetDiags

func (W *EncDiagMat) GetDiags() map[int]ckks.Operand

func (*EncDiagMat) GetRotations

func (W *EncDiagMat) GetRotations(params ckks.Parameters) []int

func (*EncDiagMat) IsEncrypted

func (W *EncDiagMat) IsEncrypted() bool

type EncInput

type EncInput struct {
	Blocks             [][]*ckks.Ciphertext //all the sub-matrixes, encrypted as flatten(A.T)
	RowP, ColP         int                  //num of partitions
	InnerRows          int                  //rows of sub-matrix
	InnerCols          int
	RealRows, RealCols int
}

Encrypted block matrix, to be used for input or bias layer

func DummyBootStrapBlocks

func DummyBootStrapBlocks(X *EncInput, Box CkksBox) *EncInput

Dummy Bootstrap where cipher is freshly encrypted

func NewEncInput

func NewEncInput(Xm *mat.Dense, rowP, colP int, level int, scale float64, Box CkksBox) (*EncInput, error)

func (*EncInput) GetBlock

func (X *EncInput) GetBlock(i, j int) interface{}

func (*EncInput) GetInnerDims

func (X *EncInput) GetInnerDims() (int, int)

func (*EncInput) GetPartitions

func (X *EncInput) GetPartitions() (int, int)

func (*EncInput) GetRealDims

func (X *EncInput) GetRealDims() (int, int)

func (*EncInput) GetRotations

func (X *EncInput) GetRotations(params ckks.Parameters) []int

func (*EncInput) Level

func (X *EncInput) Level() int

func (*EncInput) Scale

func (X *EncInput) Scale() float64

type EncWeightDiag

type EncWeightDiag struct {
	Blocks             [][]*EncDiagMat //blocks of the matrix, each is a sub-matrix in diag form
	RowP, ColP         int
	LeftR, LeftC       int //rows cols of left matrix
	InnerRows          int //rows of matrix
	InnerCols          int
	RealRows, RealCols int
}

Encrypted block matrix, weight of dense or convolutional layer

func NewEncWeightDiag

func NewEncWeightDiag(Wm *mat.Dense, rowP, colP, leftR, leftC int, level int, Box CkksBox) (*EncWeightDiag, error)

Return encrypted weight in block matrix form. The matrix is also block-transposed i.e the first column of block is stored as row for cache efficiency must provide the partitions and the rows and cols of the input inner sumbatrices (as when it will be multiplied)

func (*EncWeightDiag) GetBlock

func (W *EncWeightDiag) GetBlock(i, j int) interface{}

func (*EncWeightDiag) GetInnerDims

func (W *EncWeightDiag) GetInnerDims() (int, int)

func (*EncWeightDiag) GetPartitions

func (W *EncWeightDiag) GetPartitions() (int, int)

colP, rowP

func (*EncWeightDiag) GetRealDims

func (W *EncWeightDiag) GetRealDims() (int, int)

func (*EncWeightDiag) GetRotations

func (W *EncWeightDiag) GetRotations(params ckks.Parameters) []int

func (*EncWeightDiag) Level

func (W *EncWeightDiag) Level() int

func (*EncWeightDiag) Scale

func (W *EncWeightDiag) Scale() float64

type EvalFunc

type EvalFunc func(X *EncInput, i, j int, poly activationPoly, Box CkksBox)

type IBootstrapper

type IBootstrapper interface {
	Bootstrap(input *EncInput, Box CkksBox)
}

Interface for bootstrappers

type MulTask

type MulTask struct {
	// contains filtered or unexported fields
}

feeded to the workers to tell them what to do

type Multiplier

type Multiplier struct {
	// contains filtered or unexported fields
}

Deals with multipication between encrypted or plaintext encoded block matrices

func NewMultiplier

func NewMultiplier(poolSize int) *Multiplier

func (*Multiplier) Multiply

func (Mul *Multiplier) Multiply(X BlocksOperand, W BlocksOperand, prepack bool, Box CkksBox) *EncInput

Multiplication between encrypted input and plaintext weight

func (*Multiplier) RemoveImagFromBlocks

func (Mul *Multiplier) RemoveImagFromBlocks(X *EncInput, Box CkksBox)

To be called after multiply. Applies the rescaling and removes garbage from imaginary part of slots (from multiplication algo with complex packing)

type PlainDiagMat

type PlainDiagMat struct {
	//store a plaintext weight matrix in diagonal form
	Diags                map[int]*ckks.Plaintext //diagonals
	InnerRows, InnerCols int
	LeftR, LeftC         int //rows cols of left matrix
	Encrypted            bool
}

Plaintext matrix in diagonal form

func EncodeWeights

func EncodeWeights(level int, w [][]float64, leftR, leftC int, Box CkksBox) *PlainDiagMat

takes level, weight matrix (square) rows of input matrix to be multiplied, and box. Returns plaintext weight in diagonal form

func (*PlainDiagMat) GetDiags

func (W *PlainDiagMat) GetDiags() map[int]ckks.Operand

func (*PlainDiagMat) GetRotations

func (W *PlainDiagMat) GetRotations(params ckks.Parameters) []int

func (*PlainDiagMat) IsEncrypted

func (W *PlainDiagMat) IsEncrypted() bool

type PlainInput

type PlainInput struct {
	Blocks             [][]*ckks.Plaintext //all the sub-matrixes, encrypted as flatten(A.T)
	RowP, ColP         int                 //num of partitions
	InnerRows          int                 //rows of sub-matrix
	InnerCols          int
	RealRows, RealCols int
}

Plaintext block matrix, to be used for input or bias layer

func DecInputNoDecode

func DecInputNoDecode(XEnc *EncInput, Box CkksBox) *PlainInput

Decrypts input without decoding nor further transformation, i.e applies transformation: Block_ct(i,j) --> Block_pt(i,j)

func MaskInputEcdMask

func MaskInputEcdMask(Xenc *EncInput, Box CkksBox) *PlainInput

Deprecated Masks input by adding a random encoded mask as a random ckks plaintext

func NewPlainInput

func NewPlainInput(Xm *mat.Dense, rowP, colP int, level int, scale float64, Box CkksBox) (*PlainInput, error)

func (*PlainInput) GetBlock

func (X *PlainInput) GetBlock(i, j int) interface{}

func (*PlainInput) GetInnerDims

func (X *PlainInput) GetInnerDims() (int, int)

func (*PlainInput) GetPartitions

func (X *PlainInput) GetPartitions() (int, int)

func (*PlainInput) GetRealDims

func (X *PlainInput) GetRealDims() (int, int)

func (*PlainInput) GetRotations

func (X *PlainInput) GetRotations(params ckks.Parameters) []int

func (*PlainInput) Level

func (X *PlainInput) Level() int

func (*PlainInput) Scale

func (X *PlainInput) Scale() float64

type PlainWeightDiag

type PlainWeightDiag struct {
	Blocks             [][]*PlainDiagMat //blocks of the matrix, each is a sub-matrix in diag form
	RowP, ColP         int
	LeftR, LeftC       int //rows of left matrix
	InnerRows          int //rows of matrix
	InnerCols          int
	RealRows, RealCols int
}

Plaintext block matrix, weight of dense or convolutional layer

func NewPlainWeightDiag

func NewPlainWeightDiag(Wm *mat.Dense, rowP, colP, leftR, leftC int, level int, Box CkksBox) (*PlainWeightDiag, error)

Return plaintex weight in block matrix form. The matrix is also block-transposed i.e the first column of block is stored as row for cache efficiency takes block partions, rows of input inner submatrices, level, whether to use the complex trick, and box

func (*PlainWeightDiag) GetBlock

func (W *PlainWeightDiag) GetBlock(i, j int) interface{}

func (*PlainWeightDiag) GetInnerDims

func (W *PlainWeightDiag) GetInnerDims() (int, int)

func (*PlainWeightDiag) GetPartitions

func (W *PlainWeightDiag) GetPartitions() (int, int)

colP, rowP

func (*PlainWeightDiag) GetRealDims

func (W *PlainWeightDiag) GetRealDims() (int, int)

func (*PlainWeightDiag) GetRotations

func (W *PlainWeightDiag) GetRotations(params ckks.Parameters) []int

func (*PlainWeightDiag) Level

func (W *PlainWeightDiag) Level() int

func (*PlainWeightDiag) Scale

func (W *PlainWeightDiag) Scale() float64

type RotationsSet

type RotationsSet struct {
	Set map[int]struct{}
}

func NewRotationsSet

func NewRotationsSet() *RotationsSet

func (*RotationsSet) Add

func (rs *RotationsSet) Add(rots []int)

func (*RotationsSet) Rotations

func (rs *RotationsSet) Rotations() []int

type Split

type Split struct {
	S []BlockSplit
}

Splits for a model

func NewSplit

func NewSplit(splits []BlockSplit) *Split

func (*Split) ExctractInfo

func (s *Split) ExctractInfo() (SplitsInfo, string)

Exctract info useful for splitting input and weights, plus a hashcode for serialization

func (*Split) ExctractInfoAt

func (s *Split) ExctractInfoAt(i int) []int

Exctract info for blocksplit at i: inner rows, inner cols, rowp, colp, original rows and cols

func (*Split) GetRotations

func (s *Split) GetRotations(params ckks.Parameters) []int

Generate the rotations needed to evaluate a network with this Split

func (*Split) Print

func (s *Split) Print()

type SplitsInfo

type SplitsInfo struct {
	Features          int   `json:"features,omitempty"`
	InputRows         int   `json:"input_rows,omitempty"`
	InputCols         int   `json:"input_cols,omitempty"` //inner dims of input
	InputRowP         int   `json:"input_row_p,omitempty"`
	InputColP         int   `json:"input_col_p,omitempty"` //partition of input
	BatchSize         int   `json:"batch_size,omitempty"`
	NumWeights        int   `json:"num_weights,omitempty"`
	RowsOfWeights     []int `json:"rows_of_weights,omitempty"` //inner rows of weights
	ColsOfWeights     []int `json:"cols_of_weights,omitempty"`
	RowPOfWeights     []int `json:"row_p_of_weights,omitempty"` //row partition of weights
	ColPOfWeights     []int `json:"col_p_of_weights,omitempty"`
	RealRowsOfWeights []int `json:"real_rows_of_weights,omitempty"` //rows of weights before block partition
	RealColsOfWeights []int `json:"real_cols_of_weights,omitempty"`
}

Information on the current split

type Splitter

type Splitter struct {
	// contains filtered or unexported fields
}

func NewSplitter

func NewSplitter(inputRows, inputFeatures int, weightRows, weightCols []int, params ckks.Parameters) *Splitter

func (*Splitter) FindSplits

func (s *Splitter) FindSplits() *Split

Finds all possible splits for the current model, given the number of input features (e.g 784 in case of MNIST) and the dimentions of all the weights of the model expressed as matrices. You can also provide the inputRows in case of testing where the number of rows is given, or set to -1 to let the splitter decide FindSplits will follow an heuristic approach, trying to find the best trade-off between throughput and complexity

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL