From cdb98133c282ee2fb51430001ad0bd8ee8328f7e Mon Sep 17 00:00:00 2001 From: siddharth ravikumar Date: Sun, 12 Jun 2022 16:48:58 -0400 Subject: lib: add handling for simplified srp --- lib/srp.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/srp_test.go | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) (limited to 'lib') diff --git a/lib/srp.go b/lib/srp.go index aa3a956..892ba8c 100644 --- a/lib/srp.go +++ b/lib/srp.go @@ -173,6 +173,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 { @@ -202,6 +217,22 @@ func (u *SRPUser) SetScramblingParam(a *big.Int) error { return nil } +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) ComputeSessionKey(a *big.Int) error { // v^u vu := new(big.Int) @@ -346,6 +377,20 @@ 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 { @@ -396,6 +441,44 @@ func (s *SRPClientSession) ComputeSessionKey(salt []byte, return nil } +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 } diff --git a/lib/srp_test.go b/lib/srp_test.go index 1fd9ec1..9d34eeb 100644 --- a/lib/srp_test.go +++ b/lib/srp_test.go @@ -397,3 +397,96 @@ func TestSRPSessionKey(t *testing.T) { return } } + +func TestSimplifiedSRP(t *testing.T) { + n := StripSpaceChars( + `ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024 + e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd + 3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec + 6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f + 24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361 + c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552 + bb9ed529077096966d670c354e4abc9804f1746c08ca237327fff + fffffffffffff`) + g := "2" + k := "3" + ident := "s@ricketyspace.net" + pass := "d59d6c93af0f37f272d924979" + + // Init srp server user. + user, err := NewSRPUser(n, g, k, ident, pass) + if err != nil { + t.Errorf("unable to create user on server: %v\n", err) + return + } + + // Get server's pub for user. + user.EphemeralKeyGen() + pubB, err := user.EphemeralKeyPubSimple() + if err != nil { + t.Errorf("server ephemeral pub error: %v\n", err) + return + } + + // Init srp client session. + session, err := NewSRPClientSession(n, g, k, ident) + if err != nil { + t.Errorf("unable to create client session: %v\n", err) + return + } + + // Get client's pub for user. + pubA, err := session.EphemeralKeyPub() + if err != nil { + t.Errorf("client ephemeral pub error: %v\n", err) + return + } + + // Compute server's scrambling parameter for user. + err = user.SetScramblingParamSimple() + if err != nil { + t.Errorf("unable generate server scrambling parameter: %v\n", err) + return + } + + // Compute client's scrambling paramter for user. + err = session.SetScramblingParamSimple(user.u.Bytes()) + if err != nil { + t.Errorf("unable generate client scrambling parameter: %v\n", err) + return + } + + // Compute server's session key for user. + err = user.ComputeSessionKey(pubA) + if err != nil { + t.Errorf("unable to compute server's session key: %v", err) + return + } + + // Compute client's session key for for user. + err = session.ComputeSessionKeySimple(user.salt, pass, pubB) + if err != nil { + t.Errorf("unable to compute client's session key: %v", err) + return + } + + // Verify that the session key is the same. + if !BytesEqual(user.sk, session.sk) { + t.Errorf("server's and client's session key not equal:"+ + " server_sk(%v): client_sk(%v)", user.sk, session.sk) + return + } + + // Generate MAC of client session's session key + sMac, err := session.SessionKeyMac(user.salt) + if err != nil { + t.Errorf("unable to generate client session's mac: %v", err) + return + } + + // Verify MAC with server. + if !user.SessionKeyMacVerify(sMac) { + t.Errorf("client session mac verify failed: %v", err) + return + } +} -- cgit v1.2.3