package tools 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 }