Skip to content

Instantly share code, notes, and snippets.

@tizoc

tizoc/auth.ml Secret

Created December 18, 2015 16:46
Show Gist options
  • Save tizoc/975bfac960d7e5c60232 to your computer and use it in GitHub Desktop.
Save tizoc/975bfac960d7e5c60232 to your computer and use it in GitHub Desktop.
open Core_kernel.Std
module Signer = struct
type t = {
secret : string;
salt : string;
}
let make ?(salt="salt.signer") secret =
{ secret; salt }
let constant_time_compare' a b init =
let len = String.length a in
let result = ref init in
for i=0 to len-1 do
result := !result lor Char.(compare a.[i] b.[i])
done;
!result = 0
let constant_time_compare a b =
if String.length a <> String.length b then
constant_time_compare' b b 1
else
constant_time_compare' a b 0
let derive_key t =
Nocrypto.Hash.mac `SHA1
~key:(Cstruct.of_string t.secret)
(Cstruct.of_string t.salt)
let get_signature t value =
value
|> Cstruct.of_string
|> Nocrypto.Hash.mac `SHA1 ~key:(derive_key t)
|> Nocrypto.Base64.encode
|> Cstruct.to_string
let sign t data =
String.concat ~sep:"." [data; get_signature t data]
let verified t value signature =
if constant_time_compare signature (get_signature t value)
then Some value
else None
let unsign t data =
match String.rsplit2 ~on:'.' data with
| Some (value, signature) -> verified t value signature
| None -> None
end
(* example *)
let default_signer = Signer.make "secret" (* read from env or some file *)
let generate_token ?(signer=default_signer) account =
let open Data.Account in
let data = [
Int.to_string account.account_id;
Data.string_of_account_type account.account_type ] in
data
|> String.concat ~sep:":"
|> Cstruct.of_string
|> Nocrypto.Base64.encode
|> Cstruct.to_string
|> Signer.sign signer
let unpack_token ?(signer=default_signer) token =
match Signer.unsign signer token with
| None -> None
| Some value ->
value
|> Cstruct.of_string
|> Nocrypto.Base64.decode
|> Cstruct.to_string
|> fun v -> Scanf.sscanf v "%d:%s" (fun account_id kind ->
Some (account_id, Data.account_type_of_string kind))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment