github.com/pavlo67/common@v0.5.3/common/auth/auth_ecdsa/ecdsa.go (about) 1 package auth_ecdsa 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 r "math/rand" 8 "strings" 9 "time" 10 11 "github.com/btcsuite/btcutil/base58" 12 "github.com/pkg/errors" 13 14 "github.com/pavlo67/common/common/auth" 15 "github.com/pavlo67/common/common/encrlib" 16 ) 17 18 // const Cryptype encrlib.Cryptype = "ecdsa" 19 20 const Proto = "ecdsa" 21 22 var _ auth.Operator = &authECDSA{} 23 24 var errIPToCheckSignature = errors.New("wrong IP to check signature") 25 var errWrongSignature = errors.New("wrong signature") 26 var errWrongNumber = errors.New("wrong user's number") 27 var errEmptyPublicKeyAddress = errors.New("empty public key address") 28 var errEmptyPrivateKeyGenerated = errors.New("empty private key generated") 29 30 //var cnt uint32 31 //type Session struct { 32 // IP string 33 // StartedAt time.Time 34 //} 35 36 type authECDSA struct { 37 //sessions map[uint64]Session 38 //mutex *sync.Mutex 39 //maxSessionDuration time.Duration 40 //numbersLimit int 41 } 42 43 func New() (auth.Operator, error) { 44 r.Seed(time.Now().UnixNano()) 45 46 is := &authECDSA{ 47 //sessions: map[uint64]Session{}, 48 //mutex: &sync.Mutex{}, 49 //maxSessionDuration: maxSessionDuration, 50 //numbersLimit: numbersLimit, 51 } 52 53 return is, nil 54 } 55 56 // SetCreds creates either session-generated key or new "BTC identity" and returns it 57 func (is *authECDSA) SetCreds(actor auth.Actor, toSet auth.Creds) (*auth.Creds, error) { 58 59 //toSet := auth.CredsType(toSet[auth.CredsToSet]) 60 // 61 //if toSet == auth.CredsKeyToSignature { 62 // now := time.Now() 63 // 64 // is.mutex.Lock() // Lock() ----------------------------------------------------- 65 // 66 // if is.numbersLimit > 0 && len(is.sessions) >= is.numbersLimit { 67 // for n, s := range is.sessions { 68 // if now.Sub(s.StartedAt) >= is.maxSessionDuration { 69 // delete(is.sessions, n) 70 // } 71 // } 72 // } 73 // 74 // cnt++ 75 // numberToSend := uint64(cnt)<<32 + uint64(r.Uint32()) 76 // 77 // is.sessions[numberToSend] = Session{ 78 // IP: creds[auth.CredsIP], // TODO??? check if IP isn't empty 79 // StartedAt: now, 80 // } 81 // 82 // is.mutex.Unlock() // Unlock() ------------------------------------------------- 83 // 84 // return &auth.Creds{auth.CredsKeyToSignature: strconv.FormatUint(numberToSend, 10)}, nil 85 //} 86 87 // TODO: modify acceptableIDs if it's necessary 88 89 privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 90 if err != nil { 91 return nil, err 92 } else if privKey == nil { 93 return nil, errEmptyPrivateKeyGenerated 94 } 95 96 privKeyBytes, err := encrlib.ECDSASerialize(*privKey) 97 if err != nil { 98 return nil, err 99 } 100 101 publKeyBase58 := base58.Encode(encrlib.ECDSAPublicKey(*privKey)) 102 //nickname := publKeyBase58 103 //if toSet.StringDefault(auth.CredsNickname, "") != "" { 104 // nickname = toSet[auth.CredsNickname] 105 //} 106 107 credsNew := &auth.Creds{ 108 auth.CredsNickname: publKeyBase58, // nickname, 109 auth.CredsPrivateKey: string(privKeyBytes), 110 auth.CredsPublicKeyBase58: publKeyBase58, 111 auth.CredsPublicKeyEncoding: Proto, 112 } 113 114 return credsNew, nil 115 } 116 117 const onAuthorize = "on authECDSA.Authenticate(): " 118 119 func (is *authECDSA) Authenticate(toAuth auth.Creds) (*auth.Actor, error) { 120 if toAuth[auth.CredsPublicKeyEncoding] != Proto { 121 return nil, errors.Wrap(auth.ErrEncryptionType, onAuthorize) 122 } 123 124 keyToSignature := strings.TrimSpace(toAuth[auth.CredsIP]) 125 if keyToSignature == "" { 126 return nil, errors.Wrapf(errIPToCheckSignature, "toAuth: %#v", toAuth) 127 } 128 129 publKeyBase58 := toAuth[auth.CredsPublicKeyBase58] 130 if len(publKeyBase58) < 1 { 131 return nil, errEmptyPublicKeyAddress 132 } 133 publKey := base58.Decode(publKeyBase58) 134 135 //numberToSend, err := strconv.ParseUint(keyToSignature, 10, 64) 136 //if err != nil { 137 // return nil, errors.Wrap(auth.ErrSignaturedKey, "not a number!") 138 //} 139 //is.mutex.Lock() // Lock() ----------------------------------------------------- 140 // 141 //session, ok := is.sessions[numberToSend] 142 //if !ok { 143 // return nil, errors.Wrap(auth.ErrSignaturedKey, "no appropriate session") 144 // is.mutex.Unlock() // Unlock() --------------------------------------------- 145 //} 146 //delete(is.sessions, numberToSend) 147 // 148 //is.mutex.Unlock() // Unlock() ------------------------------------------------- 149 // 150 //if time.Now().Sub(session.StartedAt) > is.maxSessionDuration { 151 // return nil, errors.Wrap(auth.ErrAuthSession, "session is expired") 152 //} 153 // 154 //if session.IP != toAuth[auth.CredsIP] { 155 // return nil, auth.ErrIP 156 //} 157 158 signature := []byte(toAuth[auth.CredsSignature]) 159 if !encrlib.ECDSAVerify(keyToSignature, publKey, signature) { 160 return nil, errWrongSignature 161 } 162 163 var nickname = publKeyBase58 164 //if nicknameReceived := toAuth[auth.CredsNickname]; strings.TrimSpace(nicknameReceived) != "" { 165 // nickname = nicknameReceived 166 //} 167 168 return &auth.Actor{ 169 Identity: &auth.Identity{ 170 ID: auth.ID(Proto + "://" + publKeyBase58), 171 Nickname: nickname, 172 }, 173 }, nil 174 }