Browse Source

in progress

0x4a52466c696e74 2 years ago
parent
commit
9345175b2d
8 changed files with 1 additions and 1505 deletions
  1. 0 90
      bigint.go
  2. 0 472
      curve.go
  3. 0 1
      dhellman/curve.go
  4. 0 277
      elgamal.go
  5. 1 1
      go.mod
  6. 0 280
      point.go
  7. 0 97
      tools.go
  8. 0 287
      z_test.go

+ 0 - 90
bigint.go

@@ -1,90 +0,0 @@
-package curve
-
-import (
-	"math/big"
-)
-
-var (
-	valMin = big.NewInt(1187)
-	//valMin  = big.NewInt(1)
-	maxTest = big.NewInt(111187000)
-	//maxTest = big.NewInt(87)
-	max = Exp64(big.NewInt(2), 63)
-)
-
-func And(a, b *big.Int) *big.Int {
-	return new(big.Int).And(a, b)
-}
-
-func Exp(a, b, mod *big.Int) *big.Int {
-	return new(big.Int).Exp(a, b, mod)
-}
-
-func Exp64(a *big.Int, b int64) *big.Int {
-	return new(big.Int).Exp(a, big.NewInt(b), nil)
-}
-
-func Mul(a, b *big.Int) *big.Int {
-	return new(big.Int).Mul(a, b)
-}
-
-func Add(a, b *big.Int) *big.Int {
-	return new(big.Int).Add(a, b)
-}
-
-func Add64(a *big.Int, b int64) *big.Int {
-	return Add(a, big.NewInt(b))
-}
-
-func Mod(a, b *big.Int) *big.Int {
-	return new(big.Int).Mod(a, b)
-}
-
-func Mod64(a *big.Int, b int64) *big.Int {
-	return Mod(a, big.NewInt(b))
-}
-
-func Neg(a *big.Int) *big.Int {
-	return new(big.Int).Neg(a)
-}
-
-func Sub(a, b *big.Int) *big.Int {
-	return new(big.Int).Sub(a, b)
-}
-
-func Sub64(a *big.Int, b int64) *big.Int {
-	return Sub(a, big.NewInt(b))
-}
-
-func Cmp(a, b *big.Int) bool {
-	return a.Cmp(b) == 0
-}
-
-func Div(a, b *big.Int) *big.Int {
-	return new(big.Int).Div(a, b)
-}
-
-func Div64(a *big.Int, b int64) *big.Int {
-	return Div(a, big.NewInt(b))
-}
-
-func Rem(a, b *big.Int) *big.Int {
-	return new(big.Int).Rem(a, b)
-}
-
-func Split(x *big.Int, parts int, firstOffset, lastOffset *big.Int) [][]*big.Int {
-	res := make([][]*big.Int, parts)
-	div := Div64(x, int64(parts))
-	var last []*big.Int
-	for i := 0; i < parts; i++ {
-		res[i] = []*big.Int{
-			Mul(big.NewInt(int64(i)), div),
-			Sub64(Add(Mul(big.NewInt(int64(i)), div), div), 1),
-		}
-		last = res[i]
-	}
-	last[1] = Add(last[1], Add64(Mod64(x, int64(parts)), 1))
-	res[0][0] = Add(res[0][0], firstOffset)
-	last[1] = Sub(last[1], lastOffset)
-	return res
-}

+ 0 - 472
curve.go

@@ -1,472 +0,0 @@
-package curve
-
-import (
-	"errors"
-	"fmt"
-	"log"
-	"math/big"
-)
-
-var (
-	MinP = big.NewInt(11)
-)
-
-// 4a³ + 27b² = 0 - проверка кривой на сингулярность
-
-func New(a, b *big.Int) (*Curve, error) {
-	c := &Curve{
-		a: new(big.Int).Set(a),
-		b: new(big.Int).Set(b),
-	}
-	return c, c.IsSingular()
-}
-
-type Curve struct {
-	a *big.Int // константа a
-	b *big.Int // константа b
-	p *big.Int // размер конечного поля
-	g *Point   // базовая точка подгруппы
-	n *big.Int // порядок подгруппы
-	h *big.Int // кофактор подгруппы
-}
-
-func (s *Curve) A() (res *big.Int) {
-	return intCopy(s.a)
-}
-
-func (s *Curve) B() (res *big.Int) {
-	return intCopy(s.b)
-}
-
-// Проверка, установлен ли размер конечного поля
-func (s *Curve) IsValidP() (err error) {
-	if err = s.IsValidConstants(); err == nil {
-		if s.p == nil {
-			err = errors.New("размер конечного поля не установлен")
-		}
-	}
-	return
-}
-
-func (s *Curve) IsValidG() (err error) {
-	if err = s.IsValidP(); err == nil {
-		if s.g == nil {
-			err = errors.New("базовая точка подгруппы g не определена")
-		}
-	}
-	return
-}
-
-func (s *Curve) IsValidN() (err error) {
-	if err = s.IsValidG(); err == nil {
-		if s.n == nil {
-			err = errors.New("порядок подгруппы не определен")
-		}
-	}
-	return
-}
-
-// Возвращает строку уравнения кривой
-func (s *Curve) FormulaString() string {
-	return fmt.Sprintf(
-		"y² = x³ + %sx + %s",
-		mustBigInt(s.a),
-		mustBigInt(s.b),
-	)
-}
-
-// Проверка кривой на сингулярность (4a³ + 27b² = 0)
-func (s *Curve) IsSingular() (err error) {
-	if err = s.IsValidConstants(); err != nil {
-		return
-	}
-	l := new(big.Int).Mul(new(big.Int).Exp(s.a, big.NewInt(3), nil), big.NewInt(4))
-	r := new(big.Int).Mul(new(big.Int).Exp(s.b, big.NewInt(2), nil), big.NewInt(27))
-	if l.Add(l, r).Cmp(big.NewInt(0)) == 0 {
-		err = fmt.Errorf("кривая [ %s ] сингулярна и не рекомендуется к использованию", s.FormulaString())
-	}
-	return
-}
-
-// Проверка констант уравнения на валидность
-func (s *Curve) IsValidConstants() error {
-	if s.a == nil {
-		return errors.New("константа [ a ] не определена")
-	}
-	if s.b == nil {
-		return errors.New("константа [ b ] не определена")
-	}
-	return nil
-}
-
-// Установка размера конечного поля
-func (s *Curve) SetP(p *big.Int) (err error) {
-	if s.p != nil {
-		return errors.New("резмер конечного поля уже определен")
-	}
-	if err = s.IsValidConstants(); err != nil {
-		return
-	}
-	if !IsPrime(p) {
-		err = fmt.Errorf("число [ %s ] не является простым. Размер конечного поля должен быть простым числом", p)
-		return
-	}
-	s.p = p
-	/*if !IsPrime(Div(Sub(p, 1), 2)) {
-
-	}*/
-	/*
-		if p.Cmp(MinP) < 0 {
-			err = fmt.Errorf("слишком маленький размер конечного поля [ %s ]", p)
-			return
-		}
-	*/
-	//s.p = new(big.Int).Set(p)
-	// сброс подгруппы
-	s.n = nil
-	s.h = nil
-	return
-}
-
-func (s *Curve) Point(x, y *big.Int) *Point {
-	return NewPoint(x, y, s)
-}
-
-func (s *Curve) InverseMod(k, p *big.Int) (res *big.Int, err error) {
-	if err = s.IsValidP(); err != nil {
-		return
-	}
-	if k == nil {
-		err = errors.New("[ k ] не определено")
-		return
-	} else if rk := k.Cmp(intZero); rk == 0 {
-		err = errors.New("[ k ] == 0. Деление на 0 невозможно")
-		return
-	} else if rk < 0 {
-		// k ** -1 = p - (-k) ** -1  (mod p)
-		// point - self.inverseMod(-k, point)
-		var iMod *big.Int
-		if iMod, err = s.InverseMod(Neg(k), p); err == nil {
-			res = Sub(p, iMod)
-		}
-	} else {
-		s, olds := big.NewInt(0), big.NewInt(1)
-		t, oldt := big.NewInt(1), big.NewInt(0)
-		r, oldr := intCopy(p), intCopy(k)
-
-		for r.Cmp(intZero) != 0 {
-			quot := Div(oldr, r)
-			oldr, r = r, Sub(oldr, Mul(quot, r))
-			olds, s = s, Sub(olds, Mul(quot, s))
-			oldt, t = t, Sub(oldt, Mul(quot, t))
-		}
-		// gcd, x, y = old_r, old_s, old_t
-		res = Mod(olds, p)
-	}
-	return
-}
-
-// Определение координат пары зеркальных точек по x
-func (s *Curve) points(dx *big.Int) (p1, p2 *Point, err error) {
-	dxx := intCopy(dx)
-	// Инициализируем результирующие точки пустыми
-	p1, p2 = s.Point(nil, nil), s.Point(nil, nil)
-	var dy *big.Int
-	// Операции, обратной делению по модулю, не существует, поэтому
-	// для определения координаты по y, необходимо, путем перебора с подстановкой y,
-	// проверить равенство левой части уравнения, разделенного по модулю на p с
-	// правой частью, так же разделенной по модулю на p
-	for i := big.NewInt(0); i.Cmp(s.p) < 0; i.Add(i, big.NewInt(1)) {
-		// i ** 2 % s.p == (dx ** 3 + s.a * dx + self.b) % self.p > 0
-		l := Mod(Exp64(i, 2), s.p)
-		r := Mod(
-			Add(
-				Exp64(dx, 3),
-				Add(
-					Mul(s.a, dx),
-					s.b,
-				),
-			),
-			s.p,
-		)
-		if l.Cmp(r) == 0 {
-			dy = i
-			break
-		}
-	}
-	if dy == nil {
-		err = fmt.Errorf("не удалось найти пару зеркальных точек на кривой после x [ %s ]", dxx)
-	} else {
-		p1.x, p1.y = dx, dy
-		p2.x = intCopy(p1.x)
-		p2.y = Mod(Neg(p1.y), s.p)
-	}
-	return
-}
-
-func (s *Curve) searhClosePoints(x *big.Int) (p1, p2 *Point, err error) {
-	cx := intCopy(x)
-	if x.Cmp(s.p) >= 0 {
-		x = Sub(s.p, big.NewInt(1))
-	} else if x.Cmp(intZero) < 0 {
-		x = big.NewInt(0)
-	}
-	//kx := Sub64(x, 1)
-	kx := intCopy(x)
-	for {
-		//log.Println("xkx", x, kx)
-		if x.Cmp(s.p) >= 0 && kx.Cmp(intZero) <= 0 {
-			err = fmt.Errorf("не удалось найти точки, близкие к [ %s ]", cx)
-			break
-		} else {
-			// Поиск вправо
-			if x.Cmp(s.p) <= 0 {
-				if p1, p2, err = s.points(x); err == nil {
-					if p1.IsInCurve() == nil {
-						return
-					}
-				}
-				x = Add64(x, 1)
-			}
-			// Поиск влево
-			if kx.Cmp(intZero) < 0 {
-				if p1, p2, err = s.points(kx); err == nil {
-					if p1.IsInCurve() == nil {
-						return
-					}
-				}
-				kx = Sub64(kx, 1)
-			}
-		}
-	}
-	return
-}
-
-func (s *Curve) SetG(g *Point) (err error) {
-	if s.g != nil {
-		err = errors.New("базовая точка подгруппы g уже определена")
-		return
-	}
-	if err = s.IsValidP(); err != nil {
-		return
-	}
-	if err = g.IsInCurve(); err == nil && g.curve == s {
-		s.g = g
-	}
-	return
-}
-
-func (s *Curve) SetGRandom() (err error) {
-	if s.g != nil {
-		err = errors.New("базовая точка подгруппы g уже определена")
-		return
-	}
-	if err = s.IsValidP(); err != nil {
-		return
-	}
-	x := Random(
-		Div(s.p, big.NewInt(2)),
-		Sub(s.p, big.NewInt(10)),
-	)
-	//log.Println(x)
-	p1, p2, err := s.searhClosePoints(x)
-	if err != nil {
-		return
-	}
-	if err = p1.IsInCurve(); err == nil {
-		s.g = p1
-	} else if err = p2.IsInCurve(); err == nil {
-		s.g = p2
-	} else {
-		err = errors.New("не удалось найти точку g, пренадлежащую кривой")
-	}
-	return
-}
-
-// Поиск порядка подгруппы
-func (s *Curve) SetN() (err error) {
-	if s.n != nil {
-		return errors.New("порядок подгруппы уже определен")
-	}
-	if err = s.IsValidP(); err != nil {
-		return
-	}
-	dx, dy := intCopy(s.g.x), Mod(Neg(s.g.y), s.p)
-	tmpG := s.g.Copy()
-	s.n = big.NewInt(1)
-	for {
-		s.n.Add(s.n, big.NewInt(1))
-		if tmpG, err = tmpG.Add(s.g); err != nil {
-			return
-		}
-		if tmpG.x.Cmp(dx) == 0 && tmpG.y.Cmp(dy) == 0 {
-			s.n.Add(s.n, big.NewInt(1))
-			return
-		}
-	}
-}
-
-func (s *Curve) KeyPub(priv *big.Int) (pub *Point, err error) {
-	if err = s.IsValidN(); err != nil {
-		return
-	}
-	pub, err = s.g.Mul(priv)
-	return
-}
-
-func (s *Curve) RandomKeyPair() (priv *big.Int, pub *Point, err error) {
-	if err = s.IsValidN(); err != nil {
-		return
-	}
-	priv = Random(big.NewInt(1), Sub64(s.n, 1))
-	pub, err = s.g.Mul(priv)
-	return
-}
-
-// Вычисление общего секрета
-func (s *Curve) PointSecret(mPriv *big.Int, fPub *Point) (res *Point, err error) {
-	if err = s.IsValidN(); err != nil {
-		return
-	}
-	res, err = fPub.Mul(mPriv)
-	return
-}
-
-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
-}
-
-func (s *ELKeyPair) setupDataTable() error {
-	if s.dTable != nil {
-		return nil
-	}
-	s.dTable = make(map[byte]*Point)
-	dx := big.NewInt(0)
-	//var points []*Point
-	//var p *Point
-	for i := byte(0); i <= 254; i++ {
-		p, _, err := s.curve.searhClosePoints(dx)
-		if err != nil {
-			return err
-		}
-		// check already exists - todo
-		dx = Add64(p.x, 1)
-		s.dTable[i] = p
-		log.Println(i, p)
-	}
-	return nil
-}
-
-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
-}
-
-// https://intuit.ru/studies/professional_retraining/940/courses/408/lecture/9373?page=6
-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 *Curve) HEncode(b byte, pub *Point) (cm1, cm2 *Point, err error) {
-	var p1 *Point
-	if p1, _, err = s.points(big.NewInt(int64(b))); err != nil {
-		return
-	}
-	c1 = pub.Add()
-}
-*/
-
-/*
-// 𝐶𝑚 = (𝑘 × 𝐺, 𝑃𝑚 + 𝑘 × 𝑃𝐵)
-func (s *Curve) HellmanEncode(b byte, pub *Point) (cm1, cm2 *Point, err error) {
-	k := Random(big.NewInt(1), Sub64(s.n, 1))
-	if cm1, err = s.g.Mul(k); err != nil {
-		return
-	}
-	cm2, err = pub.Mul(Add64(k, int64(b)))
-	return
-}
-*/
-
-/*
-func (s *Curve) HellmanDecode(cm1, cm2 *Point, priv *big.Int) {
-
-}
-*/

+ 0 - 1
dhellman/curve.go

@@ -1 +0,0 @@
-package dhellman

+ 0 - 277
elgamal.go

@@ -1,277 +0,0 @@
-package curve
-
-import (
-	"context"
-	"errors"
-	"math/big"
-
-	"git.ali33.ru/fcg-xvii/go-tools/json"
-)
-
-func NewCrypt(conf json.Map, ctx context.Context) (res *Crypt, err error) {
-	var p *big.Int
-	var check bool
-	if conf.KeyExists("p") {
-		p, check = big.NewInt(0).SetString(conf.String("p", ""), 10)
-		if !check {
-			return nil, errors.New(`ожидается строка числового значения p > 0 в поле [ p ], например "1234"`)
-		}
-		if p.Cmp(intZero) <= 0 {
-			return nil, errors.New(`ожидается строка числового значения p > 0 в поле [ p ], например "1234"`)
-		}
-	}
-	res = new(Crypt)
-	err = res.Init(p, ctx)
-	return
-}
-
-type Crypt struct {
-	p *big.Int
-	g *big.Int
-}
-
-func (s *Crypt) IsValid() bool {
-	return s.p != nil
-}
-
-func (s *Crypt) Init(p *big.Int, ctx context.Context) (err error) {
-	if s.p != nil {
-		return errors.New("параметры криптографии инициированы были инициализированы ранее")
-	}
-	if p == nil {
-		//p = Random(valMin, max)
-		p = Random(valMin, maxTest)
-	}
-	s.p, s.g, err = SearchP(p, ctx)
-	return
-}
-
-func (s *Crypt) Keys(key *big.Int, ctx context.Context) *KeyPair {
-	if !s.IsValid() {
-		s.Init(nil, ctx)
-	}
-	priv := &KeyPrivate{
-		key: key,
-		c:   s,
-	}
-	pub := &KeyPublic{
-		key: Exp(s.g, priv.key, s.p),
-		c:   s,
-	}
-	res := &KeyPair{
-		priv: priv,
-		pub:  pub,
-	}
-	return res
-}
-
-func (s *Crypt) KeysGenerate(ctx context.Context) *KeyPair {
-	return s.Keys(Random(big.NewInt(1), Sub64(s.p, 1)), ctx)
-}
-
-func (s *Crypt) BrutforceKey(pub *KeyPublic, threads int, ctx context.Context) (res *KeyPair, err error) {
-	if threads < 0 {
-		threads = 1
-	} else if threads > 5 {
-		threads = 5
-	}
-	ch := make(chan *KeyPair)
-	cctx, cancel := context.WithCancel(ctx)
-	parts := Split(s.p, threads, big.NewInt(1), big.NewInt(1))
-	for i := 0; i < threads; i++ {
-		go func(part []*big.Int) {
-			cur, finish := intCopy(part[0]), part[1]
-			for {
-				select {
-				case <-cctx.Done():
-					return
-				case <-ctx.Done():
-					return
-				default:
-					if cur.Cmp(finish) <= 0 {
-						pair := s.Keys(cur, ctx)
-						if pair.pub.IsEqual(pub) {
-							ch <- pair
-							return
-						}
-						cur = Add64(cur, 1)
-					} else {
-						return
-					}
-				}
-			}
-		}(parts[i])
-	}
-	defer cancel()
-	select {
-	case res = <-ch:
-	case <-ctx.Done():
-		err = errors.New("Атака грубой силы не удалась - время вышло")
-	}
-	return
-}
-
-//////////////////////////////
-
-type KeyPair struct {
-	priv *KeyPrivate
-	pub  *KeyPublic
-}
-
-type KeyPrivate struct {
-	key *big.Int
-	c   *Crypt
-}
-
-func (s *KeyPrivate) MessageDecode(mes *Message) ([]byte, error) {
-	sl := Exp(mes.a, s.key, s.c.p)
-	if sl.ModInverse(sl, s.c.p) == nil {
-		return nil, errors.New("Ощиюбка расшифровки сообщения: некорректный приватный ключ")
-	}
-	data := make([]byte, len(mes.encrypted))
-	for i, e := range mes.encrypted {
-		part := Mul(sl, e)
-		data[i] = Mod(part, s.c.p).Bytes()[0]
-	}
-	return data, nil
-
-}
-
-type KeyPublic struct {
-	key *big.Int
-	c   *Crypt
-}
-
-func (s *KeyPublic) IsEqual(c *KeyPublic) bool {
-	return s.key.Cmp(c.key) == 0
-}
-
-func (s *KeyPublic) MessageEncode(data []byte) (res *Message) {
-	k := Random(big.NewInt(1), Sub64(s.c.p, 20))
-	k = SearchPrime(k)
-	//k := big.NewInt(2)
-	res = &Message{
-		a:         Exp(s.c.g, k, s.c.p),
-		encrypted: make([]*big.Int, len(data)),
-	}
-	sl := Exp(s.key, k, s.c.p)
-	for i, b := range data {
-		part := Mul(sl, big.NewInt(int64(b)))
-		res.encrypted[i] = Mod(part, s.c.p)
-	}
-	return
-}
-
-//////////////////////////////
-
-type Message struct {
-	a         *big.Int
-	encrypted []*big.Int
-}
-
-/*
-// PublicKey represents an ElGamal public key.
-type PublicKey struct {
-	G, P, Y *big.Int
-}
-
-// PrivateKey represents an ElGamal private key.
-type PrivateKey struct {
-	PublicKey
-	X *big.Int
-}
-
-// Encrypt encrypts the given message to the given public key. The result is a
-// pair of integers. Errors can result from reading random, or because msg is
-// too large to be encrypted to the public key.
-func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
-	pLen := (pub.P.BitLen() + 7) / 8
-	log.Println(pLen, len(msg))
-	if len(msg) > pLen-11 {
-		err = errors.New("elgamal: message too long")
-		return
-	}
-
-	// EM = 0x02 || PS || 0x00 || M
-	em := make([]byte, pLen-1)
-	em[0] = 2
-	ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
-	err = nonZeroRandomBytes(ps, random)
-	if err != nil {
-		return
-	}
-	em[len(em)-len(msg)-1] = 0
-	copy(mm, msg)
-
-	m := new(big.Int).SetBytes(em)
-
-	k, err := rand.Int(random, pub.P)
-	if err != nil {
-		return
-	}
-
-	log.Println("Y", pub.Y)
-	c1 = new(big.Int).Exp(pub.G, k, pub.P)
-	s := new(big.Int).Exp(pub.Y, k, pub.P)
-	c2 = s.Mul(s, m)
-	c2.Mod(c2, pub.P)
-
-	return
-}
-
-// Decrypt takes two integers, resulting from an ElGamal encryption, and
-// returns the plaintext of the message. An error can result only if the
-// ciphertext is invalid. Users should keep in mind that this is a padding
-// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
-// be used to break the cryptosystem.  See “Chosen Ciphertext Attacks
-// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel
-// Bleichenbacher, Advances in Cryptology (Crypto '98),
-func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
-	s := new(big.Int).Exp(c1, priv.X, priv.P)
-	if s.ModInverse(s, priv.P) == nil {
-		return nil, errors.New("elgamal: invalid private key")
-	}
-	s.Mul(s, c2)
-	s.Mod(s, priv.P)
-	em := s.Bytes()
-
-	firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
-
-	// The remainder of the plaintext must be a string of non-zero random
-	// octets, followed by a 0, followed by the message.
-	//   lookingForIndex: 1 iff we are still looking for the zero.
-	//   index: the offset of the first zero byte.
-	var lookingForIndex, index int
-	lookingForIndex = 1
-
-	for i := 1; i < len(em); i++ {
-		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
-		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
-		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
-	}
-
-	if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
-		return nil, errors.New("elgamal: decryption error")
-	}
-	return em[index+1:], nil
-}
-
-// nonZeroRandomBytes fills the given slice with non-zero random octets.
-func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
-	_, err = io.ReadFull(rand, s)
-	if err != nil {
-		return
-	}
-
-	for i := 0; i < len(s); i++ {
-		for s[i] == 0 {
-			_, err = io.ReadFull(rand, s[i:i+1])
-			if err != nil {
-				return
-			}
-		}
-	}
-
-	return
-}
-*/

+ 1 - 1
go.mod

@@ -1,4 +1,4 @@
-module git.ali33.ru/fcg-xvii/curve
+module git.ali33.ru/fcg-xvii/curve/v2
 
 go 1.18
 

+ 0 - 280
point.go

@@ -1,280 +0,0 @@
-package curve
-
-import (
-	"errors"
-	"fmt"
-	"math/big"
-)
-
-func NewPoint(x, y *big.Int, curve *Curve) *Point {
-	return &Point{
-		curve: curve,
-		x:     intCopy(x),
-		y:     intCopy(y),
-	}
-}
-
-type Point struct {
-	x     *big.Int
-	y     *big.Int
-	curve *Curve
-}
-
-func (s *Point) String() string {
-	return fmt.Sprintf("(%v, %v)", s.x, s.y)
-}
-
-func (s *Point) PointNull() *Point {
-	return &Point{
-		curve: s.curve,
-	}
-}
-
-// Проверка, валидна ли точка.
-// Точка считается валидной, если определены x, y и объект кривой
-func (s *Point) IsValid() (err error) {
-	if s.x == nil {
-		err = errors.New("координата [ x ] точки не определена")
-	} else if s.y == nil {
-		err = errors.New("координата [ y ] точки не определена")
-	} else if s.curve == nil {
-		err = errors.New("кривая точки не определена")
-	} else {
-		err = s.curve.IsValidP()
-	}
-	return
-}
-
-func (s *Point) InitXY(x, y *big.Int) *Point {
-	return &Point{
-		x:     intCopy(x),
-		y:     intCopy(y),
-		curve: s.curve,
-	}
-}
-
-// Копирование точки
-func (s *Point) Copy() *Point {
-	res := &Point{
-		curve: s.curve,
-	}
-	if s.x != nil {
-		res.x = new(big.Int).Set(s.x)
-	}
-	if s.y != nil {
-		res.y = new(big.Int).Set(s.y)
-	}
-	return res
-}
-
-func (s *Point) ShowHex() string {
-	return fmt.Sprintf(
-		"0x%x, 0x%x",
-		mustBigInt(s.x),
-		mustBigInt(s.y),
-	)
-}
-
-func (s *Point) Show() string {
-	return fmt.Sprintf(
-		"%s, %s",
-		mustBigInt(s.x),
-		mustBigInt(s.y),
-	)
-}
-
-func (s *Point) Coords() (x, y *big.Int) {
-	if s.x != nil {
-		x = new(big.Int).Set(s.x)
-	}
-	if s.y != nil {
-		y = new(big.Int).Set(s.y)
-	}
-	return
-}
-
-// Проверка принадлежности точки кривой.
-// Точка должна удовлетворять уровнению (y * y - x * x * x - c.a * x - c.b) % c.p == 0
-func (s *Point) IsInCurve() error {
-	if err := s.IsValid(); err != nil {
-		return err
-	}
-	if err := s.curve.IsValidP(); err != nil {
-		return err
-	}
-	x, y := s.Coords()
-	c := s.curve
-	y2 := Exp64(y, 2)
-	x3 := Exp64(x, 3)
-	cax := Mul(c.a, x)
-	res := Sub(Sub(Sub(y2, x3), cax), c.b)
-	res = Rem(res, c.p)
-	if res.Cmp(big.NewInt(0)) != 0 {
-		return fmt.Errorf("точка [ %s ] не пренадлежит кривой", s.Show())
-	}
-	return nil
-}
-
-// Вычисление наклона прямой, проходящей через 2 точки эллиптической кривой
-func (s *Point) GetIncline(pt *Point) (m *big.Int, err error) {
-	if err = s.IsValid(); err != nil {
-		return
-	}
-	if err = pt.IsValid(); err != nil {
-		return
-	}
-	m, cur := intCopy(intZero), s.curve
-	x1, y1 := s.Coords()
-	x2, y2 := pt.Coords()
-	var iMod *big.Int
-	if Cmp(x1, x2) { // !!! (points compare)
-		// m = (3 * x1 * x1 + cur.a) * cur.inverseMod(2 * y1, cur.p)
-		if iMod, err = cur.InverseMod(Mul(big.NewInt(2), y1), cur.p); err != nil {
-			return
-		}
-		m = Mul(
-			Add(
-				Mul(big.NewInt(3), Exp64(x1, 2)),
-				cur.a,
-			),
-			iMod,
-		)
-	} else {
-		// m = (y1 - y2) * cur.inverseMod(x1 - x2, cur.p)
-		if iMod, err = cur.InverseMod(Sub(x1, x2), cur.p); err != nil {
-			return
-		}
-		//log.Println("imod", iMod)
-		m = Mul(
-			Sub(y1, y2),
-			iMod,
-		)
-	}
-	return
-}
-
-func (s *Point) Add(pt *Point) (rpt *Point, err error) {
-	if err = s.IsValid(); err != nil {
-		err, rpt = nil, pt.Copy()
-	} else if err = pt.IsValid(); err != nil {
-		err, rpt = nil, s.Copy()
-	} else if s.x.Cmp(pt.x) == 0 && s.y.Cmp(pt.y) != 0 {
-		rpt = s.PointNull()
-	} else {
-		var m *big.Int
-		if m, err = s.GetIncline(pt); err != nil {
-			return
-		}
-		// rx = m * m - s.x - pt.x
-		//rxry 567678238 13525501245905
-		//log.Println("MMMMMMM", m, s.x, s.y, pt.x, pt.y)
-		rx := Sub(Sub(Mul(m, m), s.x), pt.x)
-		// ry = s.y + m * (rx - s.x)
-		ry := Add(s.y, Mul(m, Sub(rx, s.x)))
-		//log.Println("rxry", rx, ry)
-		rpt = s.InitXY(
-			//x = rx % s.curve.p,
-			Mod(rx, s.curve.p),
-			//y = -ry % s.curve.p,
-			Mod(Neg(ry), s.curve.p),
-		)
-	}
-	return
-}
-
-// Унарный минус
-func (s *Point) Neg() (pt *Point, err error) {
-	if err = s.IsValid(); err != nil {
-		return
-	}
-	pt = s.InitXY(
-		intCopy(s.x),
-		Mod(Neg(s.y), s.curve.p),
-	)
-	return
-}
-
-func (s *Point) Compare(pt *Point) (check bool, err error) {
-	if err = s.IsValid(); err != nil {
-		return
-	}
-	if err = pt.IsValid(); err != nil {
-		return
-	}
-	check = s.x.Cmp(pt.x) == 0
-	return
-}
-
-func (s *Point) Mul(k *big.Int) (pt *Point, err error) {
-
-	if err = s.IsValid(); err == nil {
-		if err = s.curve.IsValidN(); err != nil {
-			return
-		}
-	}
-	if k.Cmp(big.NewInt(0)) < 0 {
-		// k * point = -k * (-point)
-		if pt, err = s.Neg(); err == nil {
-			pt, err = pt.Mul(Neg(k))
-		}
-	} else {
-		pt = s.PointNull()
-		addend := s.Copy()
-		k = intCopy(k)
-		for k.Cmp(intZero) != 0 {
-			if And(k, big.NewInt(1)).Cmp(intZero) > 0 {
-				if pt, err = pt.Add(addend); err != nil {
-					return
-				}
-			}
-			if addend, err = addend.Add(addend); err != nil {
-				return
-			}
-			// k >>= 1
-			k.Rsh(k, 1)
-		}
-	}
-	return
-}
-
-/*
-    # Умножение
-   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
-*/

+ 0 - 97
tools.go

@@ -1,97 +0,0 @@
-package curve
-
-import (
-	"context"
-	"errors"
-	"math/big"
-	"math/rand"
-	"time"
-)
-
-var (
-	rnd       = rand.New(rand.NewSource(time.Now().UnixNano())) // Генератор случайных чисел
-	intZero   = big.NewInt(0)
-	intMax, _ = new(big.Int).SetString("9223372036854775807", 10)
-)
-
-func intCopy(val *big.Int) (res *big.Int) {
-	if val != nil {
-		res = new(big.Int).Set(val)
-	}
-	return
-}
-
-// Возвращает число или 0 при пустом указателе
-func mustBigInt(val *big.Int) (res *big.Int) {
-	res = val
-	if res == nil {
-		res = big.NewInt(0)
-	}
-	return res
-}
-
-func IsPrime(val *big.Int) bool {
-	return val.ProbablyPrime(100)
-}
-
-func SearchP(min *big.Int, ctx context.Context) (p *big.Int, g *big.Int, err error) {
-	ch := make(chan struct{})
-	go func() {
-		defer func() {
-			close(ch)
-		}()
-		p = intCopy(min)
-		var check bool
-		for {
-			select {
-			case <-ctx.Done():
-				err = errors.New("Поиск поля и первообразного корня - время вышло")
-				return
-			default:
-				if g, check = CheckP(p); check {
-					ch <- struct{}{}
-					return
-				}
-				p = Add64(p, 1)
-			}
-		}
-	}()
-	<-ch
-	return
-}
-
-func CheckP(val *big.Int) (res *big.Int, check bool) {
-	if IsPrime(val) {
-		//log.Println("PRIME", val, Div64(Sub64(val, 1), 2))
-		res = Div64(Sub64(val, 1), 2)
-		check = IsPrime(res)
-	}
-	return
-}
-
-func SearchPrime(val *big.Int) *big.Int {
-	rVal := new(big.Int).Set(val)
-	//log.Println(rVal)
-	for {
-		if rVal.ProbablyPrime(100) {
-			break
-		}
-		rVal.Add(rVal, big.NewInt(1))
-		//log.Println(rVal)
-	}
-	return rVal
-}
-
-func Random(min, max *big.Int) *big.Int {
-	if min == nil {
-		min = intZero
-	}
-	if max == nil {
-		max = intMax
-	}
-	res := new(big.Int).Rand(rnd, max)
-	for res.Cmp(min) == -1 {
-		res = new(big.Int).Rand(rnd, max)
-	}
-	return res
-}

+ 0 - 287
z_test.go

@@ -1,287 +0,0 @@
-package curve
-
-import (
-	"context"
-	"log"
-	"math"
-	"math/big"
-	"testing"
-	"time"
-
-	"git.ali33.ru/fcg-xvii/go-tools/json"
-)
-
-func TestSearchP(t *testing.T) {
-	min := big.NewInt(1)
-	var g *big.Int
-	var err error
-	mmin := big.NewInt(0)
-	mg := big.NewInt(0)
-	for {
-		ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Millisecond*50))
-		if min, g, err = SearchP(min, ctx); err != nil {
-			log.Println(mmin, mg)
-			t.Fatal(err)
-		}
-		mmin, mg = min, g
-		cancel()
-		//log.Println(min, g)
-		min = Add64(min, 1)
-	}
-}
-
-func TestFormula(t *testing.T) {
-	a, _ := big.NewInt(0).SetString("10", 10)
-	b, _ := big.NewInt(0).SetString("15", 10)
-	c, err := New(a, b)
-	if err != nil {
-		t.Fatal(err)
-	}
-	t.Log(c.FormulaString())
-}
-
-func TestSingular(t *testing.T) {
-	a := big.NewInt(0)
-	b := big.NewInt(0)
-	c, err := New(a, b)
-	if err == nil {
-		t.Fatal(c.FormulaString(), ", не сингулярна")
-	}
-	t.Log(err)
-}
-
-func TestSearchPrime(t *testing.T) {
-	a := big.NewInt(101010101010)
-	b := SearchPrime(a)
-	t.Log(a, b)
-}
-
-func TestBigRandom(t *testing.T) {
-	for i := 0; i < 10; i++ {
-		t.Log(Random(big.NewInt(15), big.NewInt(20)))
-	}
-}
-
-func TestPointShow(t *testing.T) {
-	p := &Point{
-		y: big.NewInt(105465465463543),
-	}
-	t.Log(p.Show())
-	t.Log(p.ShowHex())
-}
-
-func TestCurveG(t *testing.T) {
-	curve, err := New(
-		big.NewInt(2),
-		big.NewInt(4),
-	)
-	if err != nil {
-		t.Fatal(err)
-	}
-	p := SearchPrime(big.NewInt(2000000))
-	log.Println("P", p)
-	if err = curve.SetP(p); err != nil {
-		t.Fatal(err)
-	}
-	//log.Println(curve.a, curve.b, curve.p)
-	//p1, _, err := curve.searhClosePoints(big.NewInt(1000000))
-	//log.Println("==============================")
-	//log.Println(p1.Show())
-	//log.Println(p2.Show())
-	//log.Println("==============================")
-	//return
-	//log.Println(p1.Show(), p2.Show(), err)
-	if err = curve.SetGRandom(); err != nil {
-		t.Fatal(err)
-	}
-	t.Log("G", curve.g.Show())
-	if err = curve.SetN(); err != nil {
-		t.Fatal(err)
-	}
-	t.Log(curve.n)
-}
-
-func TestKeyPairs(t *testing.T) {
-	curve, err := New(
-		big.NewInt(2),
-		big.NewInt(4),
-	)
-	if err != nil {
-		t.Fatal(err)
-	}
-	p := SearchPrime(big.NewInt(int64(math.Pow(2, 10))))
-	log.Println("P", p)
-	if err = curve.SetP(p); err != nil {
-		t.Fatal(err)
-	}
-	if err = curve.SetGRandom(); err != nil {
-		t.Fatal(err)
-	}
-	t.Log("G", curve.g.Show())
-	if err = curve.SetN(); err != nil {
-		t.Fatal(err)
-	}
-	t.Log("N", curve.n)
-	priv1, pub1, err := curve.RandomKeyPair()
-	if err != nil {
-		t.Fatal(err)
-	}
-	t.Log(priv1, pub1)
-	priv2, pub2, err := curve.RandomKeyPair()
-	if err != nil {
-		t.Fatal(err)
-	}
-	t.Log(priv2, pub2)
-	log.Println(curve.PointSecret(priv1, pub2))
-	log.Println(curve.PointSecret(priv2, pub1))
-
-	p1, err := curve.ELKeyPair()
-	if err != nil {
-		t.Fatal(err)
-	}
-	t.Log(p1.priv.d)
-	t.Log(p1.pub.e1, p1.pub.e2)
-
-	mes, err := p1.EncodeMessage([]byte{5})
-	if err != nil {
-		t.Fatal(err)
-	}
-	log.Println(mes.c1)
-	log.Println(mes.cd)
-	p1.DecodeMessage(mes)
-}
-
-/*
-func TestGe(t *testing.T) {
-	curve, err := New(
-		big.NewInt(2),
-		big.NewInt(4),
-	)
-	if err != nil {
-		t.Fatal(err)
-	}
-	p := SearchPrime(big.NewInt(int64(math.Pow(2, 10))))
-	log.Println("P", p)
-	if err = curve.SetP(p); err != nil {
-		t.Fatal(err)
-	}
-	if err = curve.SetGRandom(); err != nil {
-		t.Fatal(err)
-	}
-	t.Log("G", curve.g.Show())
-	if err = curve.SetN(); err != nil {
-		t.Fatal(err)
-	}
-	t.Log("N", curve.n)
-	v1, vp1 := curve.GKeyPair()
-	v2, vp2 := curve.GKeyPair()
-	t.Log(v1, vp1)
-	t.Log(v2, vp2)
-	e1, e2 := curve.GEncode(5, vp2)
-	t.Log(e1, e2)
-	curve.GDecode(e1, e2, v2)
-}
-*/
-
-/*
-func TestEncryptDecrypt(t *testing.T) {
-	p := SearchPrime(big.NewInt(int64(math.Pow(2, 10))))
-	g := Div64(Sub64(p, 1), 2)
-	priv := &PrivateKey{
-		PublicKey: PublicKey{
-			G: g,
-			P: p,
-		},
-		X: big.NewInt(20),
-	}
-	priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
-
-	message := []byte{5}
-	c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
-	if err != nil {
-		t.Errorf("error encrypting: %s", err)
-	}
-	message2, err := Decrypt(priv, c1, c2)
-	if err != nil {
-		t.Errorf("error decrypting: %s", err)
-	}
-	if !bytes.Equal(message2, message) {
-		t.Errorf("decryption failed, got: %x, want: %x", message2, message)
-	}
-	log.Println(message, message2)
-}
-*/
-
-func TestJSON(t *testing.T) {
-	p := big.NewInt(0).SetBytes([]byte{10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10})
-	t.Log(p)
-	jm := json.Map{
-		"p": p,
-	}
-	jm.LogPretty()
-	pl := jm.Value("p", big.NewInt(0))
-	log.Printf("%T %s", pl, pl)
-	src := []byte(`{
-        "p": "13"
-	}`)
-	var jjm json.Map
-	json.Unmarshal(src, &jjm)
-	//pll := jjm.Value("p", big.NewInt(0))
-	pll, _ := big.NewInt(0).SetString(jjm.StringVal("p", ""), 10)
-	log.Printf("%T %s", pll, pll)
-}
-
-func TestCrypt(t *testing.T) {
-	jm := json.Map{}
-	ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(time.Millisecond*1000))
-	cr, err := NewCrypt(jm, ctx)
-	if err != nil {
-		t.Fatal(err)
-	}
-	c1 := cr.KeysGenerate(context.Background())
-	c2 := cr.KeysGenerate(context.Background())
-	log.Println(c1.priv.key, c1.pub.key)
-	log.Println(c2.priv.key, c2.pub.key)
-	text := "Hello, World!!! ;)"
-	log.Println(text)
-	log.Println([]byte(text))
-	mes := c2.pub.MessageEncode([]byte(text))
-	//mes := c2.pub.MessageEncode([]byte{15, 10})
-	log.Println(mes.a, mes.encrypted)
-	dData, err := c2.priv.MessageDecode(mes)
-	if err != nil {
-		t.Fatal(err)
-	}
-	t.Log(string(dData))
-}
-
-func TestCryptBrutforceKey(t *testing.T) {
-	ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Millisecond*1000))
-	defer cancel()
-	cr, err := NewCrypt(json.Map{}, ctx)
-	if err != nil {
-		t.Fatal(err)
-	}
-	k1 := cr.KeysGenerate(context.Background())
-	mes := k1.pub.MessageEncode([]byte("Hello, WORLD!!! ;)"))
-	log.Println(k1.priv.key, k1.pub.key)
-	cctx, _ := context.WithDeadline(context.Background(), time.Now().Add(time.Second*10))
-	pair, err := cr.BrutforceKey(k1.pub, 4, cctx)
-	if err != nil {
-		t.Fatal(err)
-	}
-	log.Println(pair.priv.key, pair.pub.key)
-	dec, err := pair.priv.MessageDecode(mes)
-	if err != nil {
-		t.Fatal(err)
-	}
-	t.Log(string(dec))
-}
-
-func TestSplit(t *testing.T) {
-	x := big.NewInt(1000)
-	parts := 2
-	firstOffset, lastOffset := big.NewInt(1), big.NewInt(2)
-	res := Split(x, parts, firstOffset, lastOffset)
-	log.Println(res)
-}