Browse Source

in progress

0x4a52466c696e74 2 years ago
parent
commit
42635c76ce

+ 0 - 0
dhellman/curve_key_pair.go → dhellman/key_pair.go


+ 0 - 0
dhellman/curve_key_private.go → dhellman/key_private.go


+ 1 - 1
dhellman/curve_key_public.go → dhellman/key_public.go

@@ -52,5 +52,5 @@ func (s *curveKeyPublic) attack(ctx context.Context) (*curveKeyPair, error) {
 			tmp = tools.Add64(tmp, 1)
 		}
 	}
-	return nil, errors.New("атака на метод диффи-хеллмана провалена: время вышло")
+	return nil, errors.New("атака на метод диффи-хеллмана провалена: ключ найти не удалось")
 }

+ 49 - 0
elgamal/curve.go

@@ -0,0 +1,49 @@
+package elgamal
+
+import (
+	"context"
+	"fmt"
+	"log"
+	"math/big"
+
+	"git.ali33.ru/fcg-xvii/curve/v2/tools"
+)
+
+func NewCurve(c *tools.Curve, ctx context.Context) (*Curve, error) {
+	cc := &Curve{
+		Curve: c,
+	}
+	return cc, cc.setupDataTable(ctx)
+}
+
+type Curve struct {
+	*tools.Curve
+	dTable map[byte]*tools.Point
+}
+
+func (s *Curve) bytePoint(p *tools.Point) (byte, error) {
+	for key, val := range s.dTable {
+		if val.IsEqual(p) {
+			return key, nil
+		}
+	}
+	return 0, fmt.Errorf("Не найден символ, соответствующий точке %v", p)
+}
+
+// Заполнение таблицы байт -> точка на кривой
+func (s *Curve) setupDataTable(ctx context.Context) error {
+	s.dTable = make(map[byte]*tools.Point)
+	dx := big.NewInt(1)
+	for i := byte(0); i <= 254; i++ {
+		// поиск точки
+		p, _, err := s.SearchClosePoints(dx, ctx)
+		if err != nil {
+			return err
+		}
+		// check already exists - todo
+		dx = tools.Add64(p.X(), 2)
+		s.dTable[i] = p
+		log.Println(i, p)
+	}
+	return nil
+}

+ 12 - 0
elgamal/elgamal.go

@@ -0,0 +1,12 @@
+package elgamal
+
+import (
+	"context"
+
+	"git.ali33.ru/fcg-xvii/curve/v2"
+)
+
+func CurveKeyPair(c *Curve, ctx context.Context) (curve.KeyPair, error) {
+	pair, err := randomKeyPair(c, ctx)
+	return pair, err
+}

+ 222 - 0
elgamal/key_pair.go

@@ -0,0 +1,222 @@
+package elgamal
+
+import (
+	"context"
+	"errors"
+	"math/big"
+
+	"git.ali33.ru/fcg-xvii/curve/v2"
+	"git.ali33.ru/fcg-xvii/curve/v2/tools"
+	"git.ali33.ru/fcg-xvii/go-tools/json"
+)
+
+func randomKeyPair(c *Curve, ctx context.Context) (*KeyPair, error) {
+	e1, _, err := c.SearchClosePoints(
+		tools.Random(big.NewInt(1), tools.Sub64(c.P(), 1)),
+		ctx,
+	)
+	if err != nil {
+		return nil, err
+	}
+	d := tools.Random(big.NewInt(1), tools.Sub64(c.P(), 1))
+	e2, err := e1.Mul(d)
+	if err != nil {
+		return nil, err
+	}
+	res := &KeyPair{
+		curve: c,
+		priv: &KeyPrivate{
+			d: d,
+		},
+		pub: &KeyPublic{
+			curve: c,
+			e1:    e1,
+			e2:    e2,
+		},
+	}
+	return res, nil
+}
+
+type KeyPair struct {
+	curve *Curve
+	priv  *KeyPrivate
+	pub   *KeyPublic
+}
+
+func (s *KeyPair) Map() json.Map {
+	return json.Map{
+		"private": s.priv.Map(),
+		"public":  s.pub.Map(),
+	}
+}
+
+func (s *KeyPair) MarshalJSON() ([]byte, error) {
+	return s.Map().JSON(), nil
+}
+
+func (s *KeyPair) KeyPrivate() curve.KeyPrivate {
+	return s.priv
+}
+
+func (s *KeyPair) KeyPublic() curve.KeyPublic {
+	return s.pub
+}
+
+func (s *KeyPair) MessageEncode(data []byte, args ...any) (curve.Message, error) {
+	if len(args) == 0 {
+		return nil, errors.New("Не найден публичный ключ принимающей стороны")
+	}
+	pub, check := args[0].(*KeyPublic)
+	if !check {
+		return nil, errors.New("Неверный тип аргумента - публичный ключ принимающей стороны")
+	}
+	return s.messageEncode(data, pub)
+}
+
+func (s *KeyPair) MessageDecode(mes curve.Message, args ...any) ([]byte, error) {
+	dMes, check := mes.(*Message)
+	if !check {
+		return nil, errors.New("Ожидается сообщение, зашифрованное методом эльгамаля")
+	}
+	return s.messageDecode(dMes)
+}
+
+// c1 = r x e1
+// c2 = P + r x e2
+func (s *KeyPair) messageEncode(data []byte, pub *KeyPublic) (mes *Message, err error) {
+	r := tools.Random(big.NewInt(1), tools.Sub64(s.curve.P(), 1))
+	c1, err := pub.e1.Mul(r)
+	if err != nil {
+		return nil, err
+	}
+	mes = &Message{
+		c1: c1,
+		cd: make([]*tools.Point, len(data)),
+	}
+	for i, d := range data {
+		p := s.curve.dTable[d]
+		c2, err := pub.e2.Mul(r)
+		if err != nil {
+			return nil, err
+		}
+		cd, err := p.Add(c2)
+		if err != nil {
+			return nil, err
+		}
+		mes.cd[i] = cd
+	}
+	return mes, nil
+}
+
+// p = c2 – (d x c1)
+func (s *KeyPair) messageDecode(mes *Message) ([]byte, error) {
+	res := make([]byte, len(mes.cd))
+	part, err := mes.c1.Mul(s.priv.d)
+	if err != nil {
+		return nil, err
+	}
+	part, _ = part.Neg()
+	for i, c2 := range mes.cd {
+		p, err := c2.Add(part)
+		if err != nil {
+			return nil, err
+		}
+		b, err := s.curve.bytePoint(p)
+		if err != nil {
+			return nil, err
+		}
+		res[i] = b
+	}
+	return res, nil
+}
+
+/*
+type ELKeyPriv struct {
+	d *big.Int
+}
+
+type ELKeyPub struct {
+	e1 *Point
+	e2 *Point
+}
+
+type ELKeyPair struct {
+	curve  *Curve
+	priv   *ELKeyPriv
+	pub    *ELKeyPub
+	dTable map[byte]*Point
+}
+
+type ELMessage struct {
+	c1 *Point
+	cd []*Point
+}
+
+// c1 = r x e1
+// c2 = P + r x e2
+func (s *ELKeyPair) EncodeMessage(data []byte) (mes *ELMessage, err error) {
+	r := Random(big.NewInt(1), Sub64(s.curve.p, 1))
+	c1, err := s.pub.e1.Mul(r)
+	if err != nil {
+		return nil, err
+	}
+	mes = &ELMessage{
+		c1: c1,
+		cd: make([]*Point, len(data)),
+	}
+	for i, d := range data {
+		p := s.dTable[d]
+		c2, err := s.pub.e2.Mul(r)
+		if err != nil {
+			return nil, err
+		}
+		cd, err := p.Add(c2)
+		if err != nil {
+			return nil, err
+		}
+		mes.cd[i] = cd
+	}
+	return mes, nil
+}
+
+// p = c2 – (d x c1)
+func (s *ELKeyPair) DecodeMessage(mes *ELMessage) ([]byte, error) {
+	res := make([]byte, len(mes.cd))
+	part, err := mes.c1.Mul(s.priv.d)
+	if err != nil {
+		return nil, err
+	}
+	part, _ = part.Neg()
+	for _, c2 := range mes.cd {
+		p, err := c2.Add(part)
+		if err != nil {
+			return nil, err
+		}
+		log.Println(p)
+	}
+	return res, nil
+}
+
+func (s *Curve) ELKeyPair() (*ELKeyPair, error) {
+	e1, _, err := s.searhClosePoints(Random(big.NewInt(1), Sub64(s.p, 1)))
+	if err != nil {
+		return nil, err
+	}
+	d := Random(big.NewInt(1), Sub64(s.n, 1))
+	e2, err := e1.Mul(d)
+	if err != nil {
+		return nil, err
+	}
+	res := &ELKeyPair{
+		curve: s,
+		priv: &ELKeyPriv{
+			d: d,
+		},
+		pub: &ELKeyPub{
+			e1: e1,
+			e2: e2,
+		},
+	}
+	return res, res.setupDataTable()
+}
+*/

+ 21 - 0
elgamal/key_private.go

@@ -0,0 +1,21 @@
+package elgamal
+
+import (
+	"math/big"
+
+	"git.ali33.ru/fcg-xvii/go-tools/json"
+)
+
+type KeyPrivate struct {
+	d *big.Int
+}
+
+func (s *KeyPrivate) Map() json.Map {
+	return json.Map{
+		"d": s.d,
+	}
+}
+
+func (s *KeyPrivate) MarshalJSON() ([]byte, error) {
+	return s.Map().JSON(), nil
+}

+ 89 - 0
elgamal/key_public.go

@@ -0,0 +1,89 @@
+package elgamal
+
+import (
+	"context"
+	"errors"
+	"math/big"
+
+	"git.ali33.ru/fcg-xvii/curve/v2"
+	"git.ali33.ru/fcg-xvii/curve/v2/tools"
+	"git.ali33.ru/fcg-xvii/go-tools/json"
+)
+
+type KeyPublic struct {
+	curve *Curve
+	e1    *tools.Point
+	e2    *tools.Point
+}
+
+func (s *KeyPublic) Map() json.Map {
+	return json.Map{
+		"e1": s.e1,
+		"e2": s.e2,
+	}
+}
+
+func (s *KeyPublic) MarshalJSON() ([]byte, error) {
+	return s.Map().JSON(), nil
+}
+
+func (s *KeyPublic) Attack(ctx context.Context) (curve.KeyPair, error) {
+	return s.attack(ctx)
+}
+
+/*
+func (s *Curve) ELKeyPair() (*ELKeyPair, error) {
+	e1, _, err := s.searhClosePoints(Random(big.NewInt(1), Sub64(s.p, 1)))
+	if err != nil {
+		return nil, err
+	}
+	d := Random(big.NewInt(1), Sub64(s.n, 1))
+	e2, err := e1.Mul(d)
+	if err != nil {
+		return nil, err
+	}
+	res := &ELKeyPair{
+		curve: s,
+		priv: &ELKeyPriv{
+			d: d,
+		},
+		pub: &ELKeyPub{
+			e1: e1,
+			e2: e2,
+		},
+	}
+	return res, res.setupDataTable()
+}
+*/
+func (s *KeyPublic) attack(ctx context.Context) (*KeyPair, error) {
+	c := s.curve
+	tmp := big.NewInt(1)
+	for {
+		if tmp.Cmp(tools.Add64(c.P(), -1)) == 0 {
+			break
+		}
+		//log.Println(tmp)
+		//e2, _ := s.e1.Mul(tmp)
+		//log.Println(e2, s.e2)
+		if e2, err := s.e1.Mul(tmp); err == nil && s.e2.IsEqual(e2) {
+			pair := &KeyPair{
+				curve: s.curve,
+				priv: &KeyPrivate{
+					d: tmp,
+				},
+				pub: &KeyPublic{
+					e1: s.e1.Copy(),
+					e2: s.e2.Copy(),
+				},
+			}
+			return pair, nil
+		}
+		select {
+		case <-ctx.Done():
+			return nil, errors.New("атака на метод диффи-хеллмана провалена: время вышло")
+		default:
+			tmp = tools.Add64(tmp, 1)
+		}
+	}
+	return nil, errors.New("атака на метод диффи-хеллмана провалена: ключ найти не удалось")
+}

+ 14 - 0
elgamal/message.go

@@ -0,0 +1,14 @@
+package elgamal
+
+import "git.ali33.ru/fcg-xvii/curve/v2/tools"
+
+type Message struct {
+	c       *Curve
+	c1      *tools.Point
+	cd      []*tools.Point
+	encoded []byte
+}
+
+func (s *Message) Encoded() []byte {
+	return s.encoded
+}

+ 55 - 0
elgamal/z_test.go

@@ -0,0 +1,55 @@
+package elgamal
+
+import (
+	"context"
+	"log"
+	"math/big"
+	"testing"
+
+	"git.ali33.ru/fcg-xvii/curve/v2/tools"
+)
+
+func TestMessage(t *testing.T) {
+	// curve init
+	c, err := tools.NewCurve(
+		big.NewInt(2),
+		big.NewInt(4),
+	)
+	if err != nil {
+		t.Fatal(err)
+	}
+	p := tools.SearchPrime(big.NewInt(100000))
+	if err = c.SetP(p); err != nil {
+		t.Fatal(err)
+	}
+	if err = c.SetGRandom(context.Background()); err != nil {
+		t.Fatal(err)
+	}
+	log.Println("CURVE NORM")
+	ce, _ := NewCurve(c, context.Background())
+	log.Println("CURVE2 NORM")
+	p1, _ := CurveKeyPair(ce, context.Background())
+	p2, _ := CurveKeyPair(ce, context.Background())
+	p1.Map().LogPretty()
+	p2.Map().LogPretty()
+	message := "Привет, мир ;)"
+	mes, err := p1.MessageEncode([]byte(message), p2.KeyPublic())
+	if err != nil {
+		t.Fatal(err)
+	}
+	src, err := p2.MessageDecode(mes)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Log(string(src))
+	aPair, err := p2.KeyPublic().Attack(context.Background())
+	if err != nil {
+		t.Fatal(err)
+	}
+	aPair.Map().LogPretty()
+	src, err = aPair.MessageDecode(mes)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Log(string(src))
+}

+ 3 - 0
key_pair.go

@@ -1,8 +1,11 @@
 package curve
 
+import "git.ali33.ru/fcg-xvii/go-tools/json"
+
 type KeyPair interface {
 	KeyPrivate() KeyPrivate
 	KeyPublic() KeyPublic
 	MessageEncode(data []byte, args ...any) (Message, error)
 	MessageDecode(mes Message, args ...any) ([]byte, error)
+	Map() json.Map
 }

+ 3 - 41
tools/point.go

@@ -261,44 +261,6 @@ func (s *Point) MarshalJSON() ([]byte, error) {
 	return s.Map().JSON(), nil
 }
 
-/*
-    # Умножение
-   def __mul__(self, k):
-       if self.isNone() or k % self.curve.n == 0:
-           return self.pointNull()
-
-       if k < 0:
-           # k * point = -k * (-point)
-           return -self * -k
-
-       res = self.pointNull()
-       addend = self.copy()
-
-       while k:
-           if k & 1:
-               # Add.
-               res = res + addend
-           # Double.
-           addend = addend + addend
-           k >>= 1
-       return res
-
-   # Вычисление хэша точки (числовая строка суммы координат)
-   def md5(self):
-       src = str(self.x + self.y)
-       return hashlib.md5(src.encode('utf-8')).digest()
-
-   # Вычисление хэша по оси x
-   def md5X(self):
-       return hashlib.md5(str(self.x).encode('utf-8')).digest()
-
-   # Вычисление хэша по оси y
-   def md5Y(self):
-       return hashlib.md5(str(self.y).encode('utf-8')).digest()
-
-   # Проверка совпадения координат 2х точек по осям x и y
-   def isEqual(self, point):
-       x1, y1 = self.coords()
-       x2, y2 = point.coords()
-       return x1 == x2 and y1 == y2
-*/
+func (s *Point) IsEqual(p *Point) bool {
+	return s.curve == p.curve && s.x.Cmp(p.x) == 0 && s.y.Cmp(p.y) == 0
+}