1package scram_test
2
3import (
4 "crypto/sha256"
5 "fmt"
6 "log"
7
8 "github.com/mjl-/mox/scram"
9)
10
11func Example() {
12 check := func(err error, msg string) {
13 if err != nil {
14 log.Fatalf("%s: %s", msg, err)
15 }
16 }
17
18 // Prepare credentials.
19 //
20 // The client normally remembers the password and uses it during authentication.
21 //
22 // The server sets the iteration count, generates a salt and uses the password once
23 // to generate salted password hash. The salted password hash is used to
24 // authenticate the client during authentication.
25 iterations := 4096
26 salt := scram.MakeRandom()
27 password := "test1234"
28 saltedPassword, err := scram.SaltPassword(sha256.New, password, salt, iterations)
29 check(err, "salt password")
30
31 // Make a new client for authenticating user mjl with SCRAM-SHA-256.
32 username := "mjl"
33 authz := ""
34 client := scram.NewClient(sha256.New, username, authz, false, nil)
35 clientFirst, err := client.ClientFirst()
36 check(err, "client.ClientFirst")
37
38 // Instantiate a new server with the initial message from the client.
39 server, err := scram.NewServer(sha256.New, []byte(clientFirst), nil, false)
40 check(err, "NewServer")
41
42 // Generate first message from server to client, with a challenge.
43 serverFirst, err := server.ServerFirst(iterations, salt)
44 check(err, "server.ServerFirst")
45
46 // Continue at client with first message from server, resulting in message from
47 // client to server.
48 clientFinal, err := client.ServerFirst([]byte(serverFirst), password)
49 check(err, "client.ServerFirst")
50
51 // Continue at server with message from client.
52 // The server authenticates the client in this step.
53 serverFinal, err := server.Finish([]byte(clientFinal), saltedPassword)
54 if err != nil {
55 fmt.Println("server does not accept client credentials")
56 } else {
57 fmt.Println("server has accepted client credentials")
58 }
59
60 // Finally, the client verifies that the server knows the salted password hash.
61 err = client.ServerFinal([]byte(serverFinal))
62 if err != nil {
63 fmt.Println("client does not accept server")
64 } else {
65 fmt.Println("client has accepted server")
66 }
67
68 // Output:
69 // server has accepted client credentials
70 // client has accepted server
71}
72