diff options
Diffstat (limited to 'lib/srp.go')
-rw-r--r-- | lib/srp.go | 149 |
1 files changed, 111 insertions, 38 deletions
@@ -1,4 +1,4 @@ -// Copyright © 2022 siddharth <s@ricketyspace.net> +// Copyright © 2022 siddharth ravikumar <s@ricketyspace.net> // SPDX-License-Identifier: ISC package lib @@ -8,26 +8,6 @@ import "math/big" // SRP - implementation. // Reference http://srp.stanford.edu/design.html -// SRP Client UI - Spec -// -// > register s@ricketyspace.net -// Enter password -// > ****** -// Registering with server...registered! -// > login s@ricketyspace.net -// Enter password -// > ****** -// Logging in...in! -// s@ricketyspace.net> -// s@ricketyspace.net> login s@ricketyspace.net -// login command not allowed when logged in -// s@ricketyspace.net> register rsd@gnu.org -// register command not allowed when logged in -// s@ricketyspace.net> logout -// Logging out..out! -// > register s@ricketyspace.net -// Already registered! - // SRP Server. type SRPServer struct { users []*SRPUser @@ -144,17 +124,26 @@ func NewSRPUser(n, g, k, ident, pass string) (*SRPUser, error) { return nil, err } + // Compute verifier. + user.ComputeVerifier(pass) + + return user, nil +} + +func (user *SRPUser) Ident() string { + return user.ident +} + +func (u *SRPUser) ComputeVerifier(pass string) { // Generate private key `x` from salt+pass m := make([]byte, 0) - copy(m, user.salt) + copy(m, u.salt) m = append(m, StrToBytes(pass)...) - user.h.Message(m) - user.x.SetBytes(user.h.Hash()) + u.h.Message(m) + u.x.SetBytes(u.h.Hash()) // Generate password verifier `v` - user.v.Exp(user.g, user.x, user.n) - - return user, nil + u.v.Exp(u.g, u.x, u.n) } func (u *SRPUser) EphemeralKeyGen() { @@ -193,6 +182,21 @@ func (u *SRPUser) EphemeralKeyPub() (*big.Int, error) { return pub, nil } +func (u *SRPUser) EphemeralKeyPubSimple() (*big.Int, error) { + if u.g == nil || u.g.Cmp(big.NewInt(0)) != 1 { + return nil, CPError{"g is not initialized"} + } + if u.b == nil || u.b.Cmp(big.NewInt(0)) != 1 { + return nil, CPError{"b is not initialized"} + } + + // pub is 'B' + pub := new(big.Int) + pub.Exp(u.g, u.b, u.n) + + return pub, nil +} + func (u *SRPUser) SetScramblingParam(a *big.Int) error { b, err := u.EphemeralKeyPub() if err != nil { @@ -222,11 +226,27 @@ func (u *SRPUser) SetScramblingParam(a *big.Int) error { return nil } -func (u *SRPUser) ComputeSessionKey(a *big.Int) error { - if a.Cmp(big.NewInt(0)) != 1 { - return CPError{"a is invalid"} +func (u *SRPUser) SetScramblingParamSimple() error { + // random 128-bits + r, err := RandomBytes(16) + if err != nil { + return err } + // Set scrambling paramter u + u.u = new(big.Int) + u.u.SetBytes(r) + if u.u.Cmp(big.NewInt(0)) != 1 { + return CPError{"u is invalid"} + } + return nil +} + +func (u *SRPUser) GetScramblingParam() []byte { + return u.u.Bytes() +} + +func (u *SRPUser) ComputeSessionKey(a *big.Int) error { // v^u vu := new(big.Int) vu.Exp(u.v, u.u, u.n) @@ -247,7 +267,10 @@ func (u *SRPUser) ComputeSessionKey(a *big.Int) error { } func (u *SRPUser) SessionKeyMacVerify(mac []byte) bool { - return u.h.MacVerify(u.salt, u.sk, mac) + if BytesEqual(HmacSha256(u.sk, u.salt), mac) { + return true + } + return false } func (u *SRPUser) LoggedIn() bool { @@ -370,14 +393,25 @@ func (s *SRPClientSession) SetScramblingParam(b *big.Int) error { return nil } +func (s *SRPClientSession) SetScramblingParamSimple(u []byte) error { + if len(u) < 16 { + return CPError{"server u is invalid"} + } + + // Set scrambling paramter u + s.u = new(big.Int) + s.u.SetBytes(u) + if s.u.Cmp(big.NewInt(0)) != 1 { + return CPError{"u is invalid"} + } + return nil +} + func (s *SRPClientSession) ComputeSessionKey(salt []byte, pass string, b *big.Int) error { if len(salt) < 1 { return CPError{"salt invalid"} } - if len(pass) < 1 { - return CPError{"pass invalid"} - } // salt+pass sp := make([]byte, 0) @@ -423,12 +457,51 @@ func (s *SRPClientSession) ComputeSessionKey(salt []byte, return nil } -func (s *SRPClientSession) SessionKeyMac(salt []byte) ([]byte, error) { - if len(s.sk) < 1 { - return nil, CPError{"sk is invalid"} +func (s *SRPClientSession) ComputeSessionKeySimple(salt []byte, + pass string, b *big.Int) error { + if len(salt) < 1 { + return CPError{"salt invalid"} } + + // salt+pass + sp := make([]byte, 0) + copy(sp, salt) + sp = append(sp, StrToBytes(pass)...) + + // x = H(salt+pass) + x := new(big.Int) + s.h.Message(sp) + x.SetBytes(s.h.Hash()) + + // u * x + ux := new(big.Int) + ux.Mul(s.u, x) + + // a + u*x + aux := new(big.Int) + aux.Add(s.a, ux) + + // S = (B) ^ (a + u*x) + sec := new(big.Int) + sec.Exp(b, aux, s.n) + sb := sec.Bytes() + + // K = H(S) + m := make([]byte, 0) + m = append(m, sb...) + s.h.Message(m) + s.sk = s.h.Hash() + + return nil +} + +func (s *SRPClientSession) SetSessionKey(key []byte) { + s.sk = key +} + +func (s *SRPClientSession) SessionKeyMac(salt []byte) ([]byte, error) { if len(salt) < 1 { return nil, CPError{"salt is invalid"} } - return s.h.Mac(salt, s.sk), nil + return HmacSha256(s.sk, salt), nil } |