+11
-5
bin/interop_test.ml
+11
-5
bin/interop_test.ml
···
2
2
3
3
external env_cast : 'a -> 'b = "%identity"
4
4
5
+
let test_key =
6
+
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
7
+
5
8
let () =
9
+
let use_encryption =
10
+
Array.length Sys.argv > 1 && Sys.argv.(1) = "--encrypt"
11
+
in
6
12
Eio_main.run @@ fun env ->
7
13
let env = env_cast env in
8
14
Eio.Switch.run @@ fun sw ->
···
14
20
node_name = Some "ocaml-node";
15
21
protocol_interval = 1.0;
16
22
probe_timeout = 0.5;
17
-
secret_key = String.make 16 '\x00';
23
+
secret_key = test_key;
18
24
cluster_name = "";
19
-
(* Empty for memberlist compatibility - it uses Label instead *)
20
-
encryption_enabled = false;
25
+
encryption_enabled = use_encryption;
21
26
}
22
27
in
23
28
let env_wrap = { stdenv = env; sw } in
···
26
31
Printf.eprintf "Error: Invalid encryption key\n";
27
32
exit 1
28
33
| Ok cluster ->
29
-
Printf.printf "OCaml SWIM node started on 127.0.0.1:%d\n%!"
30
-
config.bind_port;
34
+
Printf.printf
35
+
"OCaml SWIM node started on 127.0.0.1:%d (encryption=%b)\n%!"
36
+
config.bind_port config.encryption_enabled;
31
37
Swim.Cluster.start cluster;
32
38
33
39
let go_node =
+16
-3
lib/crypto.ml
+16
-3
lib/crypto.ml
···
1
1
let nonce_size = 12
2
2
let tag_size = 16
3
3
let version_size = 1
4
-
let encryption_version = 0
4
+
let encryption_version = 1
5
5
let key_size = 16
6
6
let overhead = version_size + nonce_size + tag_size
7
7
···
32
32
(String.length ciphertext);
33
33
result
34
34
35
+
let pkcs7_unpad data block_size =
36
+
let len = String.length data in
37
+
if len = 0 then data
38
+
else
39
+
let padding = Char.code data.[len - 1] in
40
+
if padding > 0 && padding <= block_size && padding <= len then
41
+
String.sub data 0 (len - padding)
42
+
else data
43
+
35
44
let decrypt ~key data =
36
45
if Cstruct.length data < overhead then Error `Too_short
37
46
else
38
47
let version = Cstruct.get_uint8 data 0 in
39
-
if version <> encryption_version then Error `Unsupported_version
48
+
if version > 1 then Error `Unsupported_version
40
49
else
41
50
let nonce =
42
51
Cstruct.to_string (Cstruct.sub data version_size nonce_size)
···
50
59
match
51
60
Mirage_crypto.AES.GCM.authenticate_decrypt ~key ~nonce ciphertext
52
61
with
53
-
| Some plaintext -> Ok (Cstruct.of_string plaintext)
62
+
| Some plaintext ->
63
+
let plaintext =
64
+
if version = 0 then pkcs7_unpad plaintext 16 else plaintext
65
+
in
66
+
Ok (Cstruct.of_string plaintext)
54
67
| None -> Error `Decryption_failed
+21
test_interop_encrypted.sh
+21
test_interop_encrypted.sh
···
1
+
#!/bin/bash
2
+
set -e
3
+
4
+
# Test key: 16 bytes (0x00-0x0f) in hex
5
+
TEST_KEY="000102030405060708090a0b0c0d0e0f"
6
+
7
+
echo "Starting Go memberlist server WITH encryption..."
8
+
cd /home/gdiazlo/data/src/swim/interop
9
+
./memberlist-server -name go-node -port 7946 -key "$TEST_KEY" &
10
+
GO_PID=$!
11
+
sleep 2
12
+
13
+
echo "Starting OCaml SWIM client WITH encryption..."
14
+
cd /home/gdiazlo/data/src/swim
15
+
timeout 25 ./_build/default/bin/interop_test.exe --encrypt || true
16
+
17
+
echo "Killing Go server..."
18
+
kill $GO_PID 2>/dev/null || true
19
+
wait $GO_PID 2>/dev/null || true
20
+
21
+
echo "Done"