Skip to content

Commit

Permalink
refine comments
Browse files Browse the repository at this point in the history
  • Loading branch information
xtaci committed Jul 8, 2024
1 parent 628c6d6 commit f48fa69
Showing 1 changed file with 40 additions and 30 deletions.
70 changes: 40 additions & 30 deletions dppk.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,31 @@ import (
// PRIME is the prime number used in the DPPK protocol.
const PRIME = "32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596231637"

//const PRIME = "997"

// PrivateKey
// PrivateKey represents a private key in the DPPK protocol.
type PrivateKey struct {
s0 *big.Int
a0, a1, b0, b1 *big.Int
s0a0, s0b0 *big.Int // the constant term of the polynomial
s0 *big.Int // Initial secret value
a0, a1, b0, b1 *big.Int // Coefficients for the polynomials
s0a0, s0b0 *big.Int // Precomputed constant terms of the polynomials
PublicKey
}

// PublicKey represents a public key in the DPPK protocol.
type PublicKey struct {
prime *big.Int
vecU []*big.Int
vecQ []*big.Int
prime *big.Int // Prime number used in the protocol
vecU []*big.Int // Coefficients for polynomial U
vecQ []*big.Int // Coefficients for polynomial Q
}

// NewDPPK creates a new DPPK instance with the given order.
// GenerateKey generates a new DPPK private key with the given order.
func GenerateKey(order int) (*PrivateKey, error) {
// Ensure the order is at least 5
if order < 5 {
return nil, errors.New("order must be at least 5")
}
prime, _ := big.NewInt(0).SetString(PRIME, 10)

RETRY:
// Generate random coefficients for the polynomials
a0, err := rand.Int(rand.Reader, prime)
if err != nil {
return nil, err
Expand All @@ -53,13 +54,12 @@ RETRY:
return nil, err
}

// make sure they're different
// Ensure all coefficients are distinct
if a0.Cmp(a1) == 0 || a0.Cmp(b0) == 0 || a0.Cmp(b1) == 0 || a1.Cmp(b0) == 0 || a1.Cmp(b1) == 0 || b0.Cmp(b1) == 0 {
goto RETRY
}

// Bn(X)
// coefficients s^0 --> s^N
// Generate random coefficients for the polynomial Bn(x)
Bn := make([]*big.Int, order)
for i := 0; i < len(Bn); i++ {
r, err := rand.Int(rand.Reader, prime)
Expand All @@ -68,10 +68,10 @@ RETRY:
}
Bn[i] = r
}
// the coefficient of x^n is 1
// Ensure the coefficient of x^n is 1
Bn = append(Bn, big.NewInt(1))

// compute coefficients of vector U and V
// Initialize vectors for polynomials U(x) and Q(x)
vecU := make([]*big.Int, order+3)
vecV := make([]*big.Int, order+3)
for i := 0; i < order+3; i++ {
Expand All @@ -81,9 +81,9 @@ RETRY:

bigInt := new(big.Int)

// x^2 + a1x + a0
// Compute the coefficients for the polynomials U(x) and Q(x) using Vieta's formulas
for i := 0; i < order+1; i++ {
// vector P
// Vector U
vecU[i].Add(vecU[i], bigInt.Mul(a0, Bn[i]))
vecU[i].Mod(vecU[i], prime)

Expand All @@ -93,7 +93,7 @@ RETRY:
vecU[i+2].Add(vecU[i+2], Bn[i])
vecU[i+2].Mod(vecU[i+2], prime)

// vector Q
// Vector Q
vecV[i].Add(vecV[i], bigInt.Mul(b0, Bn[i]))
vecV[i].Mod(vecV[i], prime)

Expand All @@ -104,7 +104,7 @@ RETRY:
vecV[i+2].Mod(vecV[i+2], prime)
}

//fmt.Println(vecP[0], bigInt.Mod(bigInt.Mul(a0, coeff_base[0]), prime))
// Create the private key
priv := &PrivateKey{
s0: Bn[0],
a0: a0,
Expand All @@ -115,31 +115,37 @@ RETRY:
s0b0: vecV[0],
}

// remove v0 and v(N+2)
// Set the public key vectors, excluding the first and last elements
priv.PublicKey.vecU = vecU[1 : order+2]
priv.PublicKey.vecQ = vecV[1 : order+2]
priv.PublicKey.prime = prime
return priv, nil
}

// Encrypt encrypts a message using the given public key.
func (dppk *PrivateKey) Encrypt(pk *PublicKey, msg []byte) (Ps *big.Int, Qs *big.Int, err error) {
// Convert the message to a big integer
secret := new(big.Int).SetBytes(msg)
if secret.Cmp(dppk.PublicKey.prime) >= 0 {
return nil, nil, errors.New("data is too large")
}

// Extend the vectors U and Q with a constant term of 1
vecUExt := make([]*big.Int, len(dppk.PublicKey.vecU)+1)
vecQExt := make([]*big.Int, len(dppk.PublicKey.vecQ)+1)
copy(vecUExt, pk.vecU)
copy(vecQExt, pk.vecQ)
vecUExt[len(vecUExt)-1] = big.NewInt(1)
vecQExt[len(vecQExt)-1] = big.NewInt(1)

// Initialize variables for the encryption process
Ps = big.NewInt(0)
Qs = big.NewInt(0)
Si := new(big.Int).Set(secret)
UiSi := new(big.Int)
ViSi := new(big.Int)

// Compute the encrypted values Ps and Qs
for i := range vecUExt {
UiSi.Mul(Si, vecUExt[i])
UiSi.Mod(UiSi, pk.prime)
Expand All @@ -158,7 +164,9 @@ func (dppk *PrivateKey) Encrypt(pk *PublicKey, msg []byte) (Ps *big.Int, Qs *big
return Ps, Qs, nil
}

// Decrypt decrypts the encrypted values Ps and Qs using the private key.
func (dppk *PrivateKey) Decrypt(Ps *big.Int, Qs *big.Int) (x1, x2 *big.Int, err error) {
// Adjust Ps and Qs with precomputed constant terms
_Ps := new(big.Int).Set(Ps)
_Qs := new(big.Int).Set(Qs)
_Ps.Add(_Ps, dppk.s0a0)
Expand All @@ -167,22 +175,22 @@ func (dppk *PrivateKey) Decrypt(Ps *big.Int, Qs *big.Int) (x1, x2 *big.Int, err
_Qs.Mod(_Qs, dppk.PublicKey.prime)

// As:
// Ps := Bn * (x^2 + a1x + a0) mod p
// Qs := Bn * (x^2 + b1x + b0) mod p
// Ps := Bn * (x^2 + a1x + a0) mod p
// Qs := Bn * (x^2 + b1x + b0) mod p
//
// We have:
// Ps*revBn(s):= (x^2 + a1x + a0) mod p
// Qs*revBn(s):= (x^2 + b1x + b0) mod p
// Ps*revBn(s):= (x^2 + a1x + a0) mod p
// Qs*revBn(s):= (x^2 + b1x + b0) mod p
//
// Then:
// Ps* Qs * revBn(s):= (x^2 + a1x + a0) * Qs mod p
// Ps* Qs * revBn(s):= (x^2 + b1x + b0) * Ps mod p
// Ps* Qs * revBn(s):= (x^2 + a1x + a0) * Qs mod p
// Ps* Qs * revBn(s):= (x^2 + b1x + b0) * Ps mod p
//
// Solve this equation to get x
// (x^2 + a1x + a0) * Qs == (x^2 + b1x + b0) * Ps modp

// (x^2 + a1x + a0) * Qs == (x^2 + b1x + b0) * Ps modp
// the following procedure will be formalized to :
// ax^2 + bx + c = 0

a := new(big.Int)
revPs := new(big.Int).Sub(dppk.PublicKey.prime, _Ps)
a.Add(_Qs, revPs)
Expand All @@ -204,6 +212,8 @@ func (dppk *PrivateKey) Decrypt(Ps *big.Int, Qs *big.Int) (x1, x2 *big.Int, err
c.Add(a0Qs, revb0Ps)
c.Mod(c, dppk.PublicKey.prime)

// Solve the quadratic equation derived from Ps and Qs
// Compute the discriminant of the quadratic equation
bsquared := new(big.Int).Mul(b, b)
bsquared.Mod(bsquared, dppk.PublicKey.prime)

Expand All @@ -214,10 +224,10 @@ func (dppk *PrivateKey) Decrypt(Ps *big.Int, Qs *big.Int) (x1, x2 *big.Int, err
squared := big.NewInt(0).Add(bsquared, invFourac)
squared.Mod(squared, dppk.PublicKey.prime)

// solve quadratic equation
// Solve the quadratic equation
root := new(big.Int).ModSqrt(squared, dppk.PublicKey.prime)

// div 2a
// Calculate the roots of the equation
inv2a := big.NewInt(2)
inv2a.Mul(inv2a, a)
inv2a.Mod(inv2a, dppk.PublicKey.prime)
Expand Down

0 comments on commit f48fa69

Please sign in to comment.