How do I get the common secret for numbers that are less than modulo in the modulo function?

50 views Asked by At

I am trying to implement something similar to the Diffie-Hellman encryption algorithm on elliptic curves, my curve has parameters a = 0, b = 7, p = 115792089237316195423570985008687907853269984665640564039457584007908834671663.

my code consists of three files:

package operations

import (
    "Signature/hash"
    "Signature/structs"
    "crypto/rand"
    "fmt"
    "github.com/tyler-smith/go-bip39"
    "log"
    "math/big"
)

func CreatePoint(x, y *big.Int) (*structs.Point, error) {
    config := DefaultConfig()

    ySquaredModP := new(big.Int).Mod(new(big.Int).Exp(y, big.NewInt(2), &config.P), &config.P)

    // (x^3 + a*x + b) % p
    rightSide := new(big.Int).Mod(new(big.Int).Add(
        new(big.Int).Exp(x, big.NewInt(3), &config.P),
        new(big.Int).Add(new(big.Int).Mul(&config.A, x), &config.B),
    ), &config.P)

    if ySquaredModP.Cmp(rightSide) != 0 {
        return nil, fmt.Errorf("The point is not on the curve")
    }

    return &structs.Point{
        X: x,
        Y: y,
    }, nil
}

func DefaultConfig() *structs.Config {

    numberString := "115792089237316195423570985008687907853269984665640564039457584007908834671663"
    bigNumber := new(big.Int)
    bigNumber.SetString(numberString, 10)

    return &structs.Config{
        A: *big.NewInt(0),
        B: *big.NewInt(7),
        P: *bigNumber,
    }
}

func CreateSignature(part1, part2 *big.Int) *structs.Signature {
    return &structs.Signature{
        R: part1,
        S: part2,
    }
}

func CreateMnemonic() string { //Dech-Wallet закинуть туда
    entropy, err := bip39.NewEntropy(128)
    if err != nil {
        log.Panicf("Error %s", err)
    }
    mnemonic, err := bip39.NewMnemonic(entropy)
    if err != nil {
        log.Panicf("Error %s", err)
    }
    return mnemonic
}

func IsEqualTo(point1, point2 structs.Point) bool {
    return point1.X.Cmp(point2.X) == 0 && point1.Y.Cmp(point2.Y) == 0
}

func FindInverse(number, modulus *big.Int) *big.Int {
    inverse := new(big.Int).ModInverse(number, modulus)

    return inverse
}

func DoublePoint(point *structs.Point) *structs.Point {
    config := DefaultConfig()

    // s = (3 * x^2 + A) / (2 * y)
    numerator := new(big.Int).Mul(big.NewInt(3), new(big.Int).Exp(point.X, big.NewInt(2), &config.P))
    numerator.Add(numerator, &config.A)
    denominator := new(big.Int).Mul(big.NewInt(2), point.Y)
    inverse := FindInverse(denominator, &config.P)
    slope := new(big.Int).Mul(numerator, inverse)
    slope.Mod(slope, &config.P)

    // x' = s^2 - 2 * x
    xPrime := new(big.Int).Exp(slope, big.NewInt(2), &config.P)
    xPrime.Sub(xPrime, new(big.Int).Mul(big.NewInt(2), point.X))
    xPrime.Mod(xPrime, &config.P)

    // y' = s * (x - x') - y
    yPrime := new(big.Int).Mul(slope, new(big.Int).Sub(point.X, xPrime))
    yPrime.Sub(yPrime, point.Y)
    yPrime.Mod(yPrime, &config.P)

    return &structs.Point{X: xPrime, Y: yPrime}
}

func Add(point1, point2 *structs.Point) *structs.Point {
    config := DefaultConfig()

    if IsEqualTo(*point1, *point2) {
        return DoublePoint(point1)
    }

    deltaX := new(big.Int).Sub(point2.X, point1.X)
    deltaY := new(big.Int).Sub(point2.Y, point1.Y)
    inverse := FindInverse(deltaX, &config.P)

    slope := new(big.Int).Mul(deltaY, inverse)
    slope.Mod(slope, &config.P)

    x := new(big.Int).Exp(slope, big.NewInt(2), &config.P)
    x.Sub(x, point2.X)
    x.Sub(x, point1.X)
    x.Mod(x, &config.P)

    y := new(big.Int).Mul(slope, new(big.Int).Sub(point1.X, x))
    y.Sub(y, point1.Y)
    y.Mod(y, &config.P)

    return &structs.Point{X: x, Y: y}
}

func Multiply(point *structs.Point, times *big.Int) *structs.Point {
    result, _ := CreateGPoint()
    binTimes := fmt.Sprintf("%b", times)

    for i := 1; i < len(binTimes); i++ {
        result = DoublePoint(result)

        if binTimes[i] == '1' {
            result = Add(point, result)
        }
    }

    return result
}

func CreateGPoint() (*structs.Point, error) {
    x1 := "55066263022277343669578718895168534326250603453777594175500187360389116729240"
    x, successX := new(big.Int).SetString(x1, 10)
    if !successX {
        panic("Error setting x value")
    }

    y1 := "32670510020758816978083085130507043184471273380659243275938904335757337482424"
    y, successY := new(big.Int).SetString(y1, 10)
    if !successY {
        panic("Error setting y value")
    }

    return &structs.Point{
        X: x,
        Y: y,
    }, nil
}

func GenerateRandomNumber() (*big.Int, error) {

    n1 := "115792089237316195423570985008687907852837564279074904382605163141518161494337" //115792089237316195423570985008687907852837564279074904382605163141518161494337 value from GP
    n, successN := new(big.Int).SetString(n1, 10)
    n.Sub(n, big.NewInt(1))
    if !successN {
        panic("Error setting y value")
    }

    random, err := rand.Int(rand.Reader, n)
    if err != nil {
        return nil, err
    }

    return random, nil
}
package structs

import "math/big"

type Config struct {
    A big.Int
    B big.Int
    P big.Int
}

type Point struct {
    X *big.Int
    Y *big.Int
}

type Signature struct {
    R *big.Int
    S *big.Int
}
package main

import (
    "Signature/operations"
    "fmt"
)

func main() {
    // Elliptic Curve Setup
    gPoint, err := operations.CreateGPoint()
    if err != nil {
        fmt.Printf("Error creating GPoint: %s\n", err)
        return
    }

    // Common Parameters
    dConfig := operations.DefaultConfig()

    // Key Generation
    alicePrivateKey, err := operations.GenerateRandomNumber()
    if err != nil {
        fmt.Printf("Error generating random number for Alice: %s\n", err)
        return
    }
    alicePublicKey := operations.Multiply(gPoint, alicePrivateKey)

    bobPrivateKey, err := operations.GenerateRandomNumber()
    if err != nil {
        fmt.Printf("Error generating random number for Bob: %s\n", err)
        return
    }
    bobPublicKey := operations.Multiply(gPoint, bobPrivateKey)

    // Shared Secret Calculation
    sharedSecretAlice := operations.Multiply(bobPublicKey, alicePrivateKey)
    fmt.Println("Alice X: ", sharedSecretAlice.X)
    sharedSecretAlice.X.Mod(sharedSecretAlice.X, &dConfig.P)
    fmt.Println("Alice X after modulo: ", sharedSecretAlice.X)

    sharedSecretBob := operations.Multiply(alicePublicKey, bobPrivateKey)
    fmt.Println("Bob X: ", sharedSecretBob.X)
    sharedSecretBob.X.Mod(sharedSecretBob.X, &dConfig.P)
    fmt.Println("Bob X after modulo: \n", sharedSecretBob.X)

    // Print Results
    fmt.Println("Shared Secret (Alice):", sharedSecretAlice.X)
    fmt.Println("Shared Secret (Bob):", sharedSecretBob.X)
}

in the output I get values that are the same before and after MOD

How do I get a shared secret for two pairs of keys?

Checked the multiplication and point addition functions, they are correct

0

There are 0 answers