package shared-secret

  1. Overview
  2. Docs

Source file shared_secret.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
module type IMessage = sig
  type t
  type a

  module Encoder : sig val encode : a -> t end;;
  module Decoder : sig val decode : t -> a end;;
end;;

module Message (Type : sig type t end) ( ) : (IMessage with type a := Type.t) = struct
  type t = Type.t

  module Encoder = struct let encode msg = msg end;;
  module Decoder = struct let decode msg = msg end;;
end;;

module type IToken = sig
  type t
  type revoker

  exception RevokedToken
  exception AlreadyRevoked

  val create  : unit -> t * revoker
  val revoke  : revoker -> unit
  val revoked : t -> bool
  val (=)     : t -> t -> bool
end;;

module Token : IToken = struct
  exception RevokedToken
  exception AlreadyRevoked

  class token ( ) = object
    val mutable revoked = false

    method rescind ( ) =
      if revoked then raise AlreadyRevoked
      else revoked <- true

    method rescinded ( ) =
      revoked
  end;;

  type t       = token
  type revoker = token

  let create ( ) =
    let instance = new token ( ) in
    (instance, instance)

    let revoke instance =
      instance # rescind ( )

    let revoked instance =
      instance # rescinded ( )

    let (=) = (=)
end;;

module type IBox = sig
  type 'value t

  exception InvalidToken

  module Sealer   : sig val seal   : Token.t -> 'value   -> 'value t end;;
  module Unsealer : sig val unseal : Token.t -> 'value t -> 'value   end;;
end;;

module Box : IBox = struct
  type 'value t = Token.t * 'value

  exception InvalidToken

  module Sealer = struct
    let seal token value =
      if Token.revoked token then
        raise Token.RevokedToken
      else
        (token, value)
  end;;

  module Unsealer = struct
    let unseal token (token', value) =
      if Token.(token = token') then
       (if Token.revoked token' then
          raise Token.RevokedToken
        else
          value)
      else
        raise InvalidToken
  end;;
end;;

module type IException = sig
  type t

  module Raiser  : sig val raise  : t -> 'a end;;
  module Handler : sig val handle : (unit -> 'a) -> (t -> 'a) -> 'a end;;
end;;

module Exception (Type : sig type t end) : (IException with type t := Type.t) = struct
  exception Class of Type.t

  module Raiser = struct
    let raise value = raise (Class value)
  end;;
  
  module Handler = struct
    let handle unsafe handler = try unsafe ( ) with Class value -> handler value
  end;;
end;;

module Revocable ( ) = struct
  exception RevokedReference
  exception AlreadyRevoked

  let revoked = ref false

  let revocable lambda value =
    if !revoked then raise RevokedReference else lambda value

  let revoke ( ) =
    if !revoked then raise AlreadyRevoked else revoked := true
end;;

module Pair = struct
  let exceptional (type a) ( ) =
    let module Module = Exception (struct type t = a end) in
    let raiser  = Module.Raiser.raise in
    let handler = Module.Handler.handle in
    (raiser, handler)

  let sealing ( ) =
    let (token, _) = Token.create ( ) in
    let sealer     = Box.Sealer.seal token in
    let unsealer   = Box.Unsealer.unseal token in
    (sealer, unsealer)
end;;

(* END *)