botan-low-0.0.1.0: Low-level Botan bindings
Copyright(c) Leo D 2023
LicenseBSD-3-Clause
Maintainerleo@apotheca.io
Stabilityexperimental
PortabilityPOSIX
Safe HaskellSafe-Inferred
LanguageHaskell2010

Botan.Low.SRP6

Description

The library contains an implementation of the SRP6-a password authenticated key exchange protocol.

Synopsis

Secure Random Password 6a

A SRP client provides what is called a SRP verifier to the server. This verifier is based on a password, but the password cannot be easily derived from the verifier (however brute force attacks are possible). Later, the client and server can perform an SRP exchange, which results in a shared secret key. This key can be used for mutual authentication and/or encryption.

SRP works in a discrete logarithm group. Special parameter sets for SRP6 are defined, denoted in the library as modp/srp/size, for example modp/srp/2048.

Warning

While knowledge of the verifier does not easily allow an attacker to get the raw password, they could still use the verifier to impersonate the server to the client, so verifiers should be protected as carefully as a plaintext password would be.

SRP6 may be used as part of SSLTLS: https:www.rfc-editor.orgrfc/rfc5054

Usage

On signup, the client generates a salt and verifier, and securely sends them to a server:

import Botan.Low.SRP6
import Botan.Low.Hash
import Botan.Low.RNG
import Botan.Low.MAC
rng <- rngInit UserRNG
group = MODP_SRP_4096
hash = SHA512
identifier = "alice"
password = "Fee fi fo fum!"
salt <- rngGet rng 12
verifier <- srp6GenerateVerifier identifier password salt group hash
-- signUpUserWithServer identifier verifier salt group hash

Later, on the server when the client request authentication, the server looks up the verfier, generates a server key (a SRP6 B value), and sends it back to the client:

-- rng <- rngInit UserRNG
session <- srp6ServerSessionInit 
-- (verifier, salt, group, hash) <- lookupUser identifier
serverKey <- srp6ServerSessionStep1 session verifier group hash rng

Once the client receives the server key, it generates a client key (SRP6 A value) and the session key, and sends the client key to the server:

-- serverKey <- didReceiveServerKey
(clientKey, clientSessionKey) <- srp6ClientAgree identifier password group hash salt serverKey rng
-- sendClientKey clientKey

The server then receives client key, and generates a matching session key:

-- clientKey <- didReceiveClientKey
serverSessionKey <- srp6ServerSessionStep2 session clientKey

At this point, clientSessionKey and serverSessionKey should be equal, but this should be confirmed by exchanging a hash digest to check for integrity, using the exchange's session key, identifier, salt, and client and server keys.

There are many ways to do this, but preferrably, an (h)mac digest should be used to also include authentication and avoid impersonation.

NOTE: Both sides could calculate 'identifier <> salt <> serverKey <> clientKey'
individually but then we need to prove that each side has calculated it without

relying on the copy received for validation, so we do this song and dance:

The client should first calculate and send the HMAC auth, using identifier + salt + clientKey:

mac <- macInit (hmac SHA3)
macSetKey mac clientSessionKey
macUpdate mac $ identifier <> salt <> clientKey
clientAuth <- macFinal mac
-- sendClientAuth clientAuth

The server should then verify the client auth, and send its own HMAC auth back to the client using serverKey + clientAuth:

-- clientAuth <- didReceiveClientAuth
mac <- macInit (hmac SHA3)
macSetKey mac serverSessionKey
macUpdate mac $ identifier <> salt <> clientKey
verifiedClientAuth <- macFinal mac
-- clientAuth == verifiedClientAuth
macClear mac
macSetKey mac serverSessionKey
macUpdate mac $ serverKey <> clientAuth
serverAuth <- macFinal mac
-- sendServerAuth serverAuth

The client then receives the server HMAC auth, and validates it

-- serverAuth <- didReceiveServerAuth
macClear mac
macSetKey mac clientSessionKey
macUpdate mac $ serverKey <> clientAuth
verifiedServerAuth <- macFinal mac
-- serverAuth == verifiedServerAuth

After this, the shared session key may be safely used.

newtype SRP6ServerSession Source #

Constructors

MkSRP6ServerSession 

Fields

withSRP6ServerSession :: SRP6ServerSession -> (BotanSRP6ServerSession -> IO a) -> IO a Source #

srp6ServerSessionInit Source #

Arguments

:: IO SRP6ServerSession

srp6: SRP-6 server session object

Initialize an SRP-6 server session object

srp6ServerSessionDestroy :: SRP6ServerSession -> IO () Source #

Destroy a SRP6 server session object immediately

srp6ServerSessionStep1 Source #

Arguments

:: SRP6ServerSession

srp6: SRP-6 server session object

-> SRP6Verifier

verifier[]: the verification value saved from client registration

-> DLGroupName

group_id: the SRP group id

-> HashName

hash_id: the SRP hash in use

-> RNG

rng_obj: a random number generator object

-> IO SRP6BValue

B_pub[]: out buffer to store the SRP-6 B value

SRP-6 Server side step 1: Generate a server B-value

srp6ServerSessionStep2 Source #

Arguments

:: SRP6ServerSession

srp6: SRP-6 server session object

-> SRP6AValue

A[]: the client's value

-> IO SRP6SharedSecret

key[]: out buffer to store the symmetric key value

SRP-6 Server side step 2: Generate the server shared key

srp6GenerateVerifier Source #

Arguments

:: Identifier

identifier: a username or other client identifier

-> Password

password: the secret used to authenticate user

-> Salt

salt[]: a randomly chosen value, at least 128 bits long

-> DLGroupName

group_id: specifies the shared SRP group

-> HashName

hash_id: specifies a secure hash function

-> IO SRP6Verifier

verifier[]: out buffer to store the SRP-6 verifier value

SRP-6 Client side step 1: Generate a new SRP-6 verifier

srp6ClientAgree Source #

Arguments

:: Identifier

username: the username we are attempting login for

-> Password

password: the password we are attempting to use

-> DLGroupName

group_id: specifies the shared SRP group

-> HashName

hash_id: specifies a secure hash function

-> Salt

salt[]: is the salt value sent by the server

-> SRP6BValue

uint8_t: B[] is the server's public value

-> RNG

rng_obj: is a random number generator object

-> IO (SRP6AValue, SRP6SharedSecret) 

SRP6a Client side step 2: Generate a client A-value and the client shared key

srp6GroupSize Source #

Arguments

:: DLGroupName

group_id

-> IO Int

group_p_bytes

Return the size, in bytes, of the prime associated with group_id

SRP6 Types

SRP discrete logarithm groups