upstream: https://github.com/mirage/mirage-crypto
at main 54 lines 1.5 kB view raw
1open Uncommon 2 3module type Stream = sig 4 type key 5 type result = { message : string; key : key } 6 7 val of_secret : string -> key 8 val encrypt : key:key -> string -> result 9 val decrypt : key:key -> string -> result 10end 11 12module ARC4 = struct 13 type key = int * int * int array 14 type result = { message : string; key : key } 15 16 let of_secret buf = 17 let len = String.length buf in 18 if len < 1 || len > 256 then invalid_arg "ARC4.of_secret: key size %d" len; 19 let s = Array.init 256 (fun x -> x) in 20 let rec loop j = function 21 | 256 -> () 22 | i -> 23 let x = String.get_uint8 buf (i mod len) in 24 let si = s.(i) in 25 let j = (j + si + x) land 0xff in 26 let sj = s.(j) in 27 s.(i) <- sj; 28 s.(j) <- si; 29 (loop [@tailcall]) j (succ i) 30 in 31 loop 0 0; 32 (0, 0, s) 33 34 let encrypt ~key:(i, j, s') buf = 35 let s = Array.copy s' and len = String.length buf in 36 let res = Bytes.create len in 37 let rec mix i j = function 38 | n when n = len -> (i, j, s) 39 | n -> 40 let i = succ i land 0xff in 41 let si = s.(i) in 42 let j = (j + si) land 0xff in 43 let sj = s.(j) in 44 s.(i) <- sj; 45 s.(j) <- si; 46 let k = s.((si + sj) land 0xff) in 47 Bytes.set_uint8 res n (k lxor String.get_uint8 buf n); 48 (mix [@tailcall]) i j (succ n) 49 in 50 let key' = mix i j 0 in 51 { key = key'; message = Bytes.unsafe_to_string res } 52 53 let decrypt = encrypt 54end