123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- 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
- }
|