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() } */