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