Skip to content

Commit 15f04a5

Browse files
committed
WIP: runnable example for SRP6
1 parent e2b8e89 commit 15f04a5

File tree

3 files changed

+80
-29
lines changed

3 files changed

+80
-29
lines changed

botan-low/botan-low.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ test-suite test
136136
main-is: Main.hs
137137
hs-source-dirs: test/
138138
build-depends:
139+
, async
139140
, base
140141
, botan-low
141142
, bytestring
@@ -147,6 +148,7 @@ test-suite test
147148

148149
other-modules:
149150
Test.Botan.Low.PwdHash
151+
Test.Botan.Low.SRP6
150152
Test.Prelude
151153

152154
--

botan-low/src/Botan/Low/SRP6.hs

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -52,38 +52,84 @@ import Botan.Low.PubKey
5252
import Botan.Low.Remake
5353
import Botan.Low.RNG
5454

55-
{- $introduction
56-
57-
A SRP client provides what is called a SRP verifier to the server.
58-
This verifier is based on a password, but the password cannot be
59-
easily derived from the verifier (however brute force attacks are
60-
possible). Later, the client and server can perform an SRP exchange,
61-
which results in a shared secret key. This key can be used for
62-
mutual authentication and/or encryption.
63-
64-
SRP works in a discrete logarithm group. Special parameter sets for
65-
SRP6 are defined, denoted in the library as @modp\/srp\/<size>@, for
66-
example @modp\/srp\/2048@.
67-
68-
Warning
69-
70-
While knowledge of the verifier does not easily allow an attacker to
71-
get the raw password, they could still use the verifier to impersonate
72-
the server to the client, so verifiers should be protected as carefully
73-
as a plaintext password would be.
74-
75-
SRP6 may be used as part of SSL/TLS: https://www.rfc-editor.org/rfc/rfc5054
76-
77-
-}
78-
7955
{- $usage
8056
81-
On signup, the client generates a salt and verifier, and securely sends them to a server:
57+
On signup, the client generates a salt and verifier, and securely sends them to
58+
a server:
59+
60+
>>> :{
61+
{-# OPTIONS_GHC -threaded -Wall #-}
62+
import Botan.Low.Hash
63+
import Botan.Low.MAC
64+
import Botan.Low.PubKey
65+
import Botan.Low.RNG
66+
import Botan.Low.SRP6
67+
import Control.Concurrent
68+
import Control.Concurrent.Async
69+
import Control.Concurrent.MVar
70+
import Control.Exception
71+
import Control.Monad
72+
import Data.ByteString hiding (group)
73+
import Text.Printf
74+
:}
75+
76+
>>> :{
77+
type Identifier = ByteString
78+
data Msg =
79+
SendVerifier SRP6Verifier DLGroupName HashName
80+
| SendServerKey SRP6BValue
81+
| SendClientKey SRP6AValue
82+
| SendSharedSecret SRP6SharedSecret
83+
:}
84+
85+
>>> :{
86+
client :: MVar Msg -> IO ()
87+
client msgVar = do
88+
rng <- rngInit UserRNG
89+
let group = MODP_SRP_4096
90+
hash = SHA512
91+
identifier = "alice"
92+
password = "Fee fi fo fum!"
93+
salt <- rngGet rng 12
94+
verifier <- srp6GenerateVerifier identifier password salt group hash
95+
putMVar msgVar $ SendVerifier verifier group hash
96+
SendServerKey serverKey <- takeMVar msgVar
97+
(clientKey, clientSessionKey) <- srp6ClientAgree identifier password group hash salt serverKey rng
98+
putMVar msgVar $ SendClientKey clientKey
99+
SendSharedSecret serverSessionKey <- takeMVar msgVar
100+
let match = clientSessionKey == serverSessionKey
101+
if match then
102+
print @String "client secret == server secret"
103+
else
104+
error $
105+
printf "%s /= %s"
106+
(show clientSessionKey)
107+
(show serverSessionKey)
108+
:}
109+
110+
>>> :{
111+
server :: MVar Msg -> IO ()
112+
server msgVar = do
113+
rng <- rngInit UserRNG
114+
session <- srp6ServerSessionInit
115+
SendVerifier verifier group hash <- takeMVar msgVar
116+
serverKey <- srp6ServerSessionStep1 session verifier group hash rng
117+
putMVar msgVar $ SendServerKey serverKey
118+
SendClientKey clientKey <- takeMVar msgVar
119+
serverSessionKey <- srp6ServerSessionStep2 session clientKey
120+
putMVar msgVar $ SendSharedSecret serverSessionKey
121+
:}
122+
123+
>>> :{
124+
main :: IO ()
125+
main = do
126+
msgVar <- newEmptyMVar
127+
void $ concurrently (client msgVar) (server msgVar)
128+
:}
129+
130+
>>> main
131+
"client secret == server secret"
82132
83-
> import Botan.Low.SRP6
84-
> import Botan.Low.Hash
85-
> import Botan.Low.RNG
86-
> import Botan.Low.MAC
87133
> rng <- rngInit UserRNG
88134
> group = MODP_SRP_4096
89135
> hash = SHA512
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module Test.Botan.Low.SRP6 () where
2+
3+
import Control.Concurrent.Async ()

0 commit comments

Comments
 (0)