Doma somewhat-soverign-authentication prototype
Problem: I forgot to push some files
Problem: There is no way to register PK <-> user
Problem: README.md is outdated


browse  log 



You can also use your local clone with git send-email.


A DID-inspired implementation of authentication and fact verification, supporting KDF-based self-soverign identities.


#KDF keypair generation and regeneration

  • PKC record is "Public Key Cryptography". It's just for signing. It holds some relevant functions, including KDF.
  • Module DoAuth.Crypto exports functions with libsodium backend under short, convenient names, including kdf.
    • It uses deriveKeypair function with moderate parameters.
    • Use-case example of deriveKeypair can be found here (NB! it uses unsafe parameters).
  • Same module provides facility to regenerate key with rekdf function. It requires slip and is pure.

Implementation notes:

For debugging and forwards-compatibility purposes it's good to have a wrapper over KDF wrapper, allowing us to parametrise cryptography used and substitute the cryptographic solution with debugging solution that merely tags plaintext. To achieve that, in @DoAuth.Crypto@ module, we're having all the functions that execute DoAuth protocol take CryptoConf as the first argument. Versions that are specifed to use libsodium via haskell-crypto are then exported separately, also plaintext-preserving debug versions of every function is exported separately.


Now let's consider the cryptographic part of the protocol:

  • "Register" aka "Make identity" :: Name -> Password -> (SK, PK, Slip) =TLS (Name, PK, Slip)=> 200 | 409 "User with this name already exists"
  • "Authenticate" aka "Identify self" :: Name -> Password =TLS(Name)=> (Slip, Challenge) => (SK, PK) =TLS (Signed Challenge)=> 200 | 403 "Invalid signature"
  • "State fact" aka "Attach signed bytes to a document, identified by a public key" :: Document (PK, [Signed Claim]) -> SK -> Claim -> Document (PK, [Signed Claim])
  • "Get fact" aka "Get signed bytes from a document, identified by a public key" :: Document (PK, [Signed Claim]) -> (Claim -> Boolean) -> Maybe ((Signed Claim), Bool)
#Cryptography helpers
  • "Get slip" aka "Find slip in local storage (block device / browser) or request it from a data registry server" :: (Name) =(FS (Slip Name) | TLS (Slip Name))=> Either (200 (Slip Name)) | 404) (Slip Name)
  • "Make keypair" :: Slip -> Password -> (SK, PK)
  • "Verify fact"[2] aka "Verify signature of a claim" :: PK -> Signed Claim -> Bool
#Other ways to sign-in
  • "Authenticate with keypair" aka "Identify self, but just get challenge, not the slip" :: (SK, PK) -> Name -> Password =TLS (Name)=> Challenge -> =TLS (Signed Challenge)=> 200 (Signed Claim) | 403 "Invalid signature"
  • "Authenticate with keypair" aka "Identify self, but without regenerating keypair" :: (SK, PK) -> Name =TLS(Name)=> Challenge ->
  • "Authorise with keypair" aka "Send a token together with authentication procedure" :: Name -> SK -> PK -> Signed Claim =TLS (Signed (Signed Claim))=> ...

Since the communication is assumed to be done over an encrypted channel and public[1] claims

#Data registry server

See VC Model to see where we drew inspiration from for this part.

Not implemented.

#Doma identity tracker

Identity tracker is just a specification of Claims that establish mapping between names to public keys as attested by VC.

Uses Data registry server, not implemented.

#Doma SSO

Not implemented.

#Global implementation notes

  • We don't use JWT because we don't need its flexibility (JOSE, for example is not needed for us at the moment).


1: "public" here means "everyone who has access to Documents also have access to each Claim within the document". For instance, in a centralised setup, only the data registry itself will have access to Claims. 2: This is a poor person's JWT. The client can store fact about their PK signed by a service provider and then send it to the service or to another service to get authorised.