summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/srp.go83
-rw-r--r--lib/srp_test.go93
2 files changed, 176 insertions, 0 deletions
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
+ }
+}