Skip to content

Commit 816eff9

Browse files
committed
add option to encryption: XOR
1 parent 9ca3de3 commit 816eff9

File tree

9 files changed

+53
-24
lines changed

9 files changed

+53
-24
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ encryption_algorithm=AES-GCM
108108
| destination_port | 1 - 65535 ||以客户端运行时可以指定端口范围|
109109
| destination_address | IP地址、域名 ||填入 IPv6 地址时不需要中括号。多个地址请用逗号分隔|
110110
| dport_refresh | 20 - 65535 ||单位“秒”。预设值 60 秒,小于20秒按20秒算,大于65535时按65536秒算|
111-
| encryption_algorithm | AES-GCM<br>AES-OCB<br>chacha20<br>xchacha20 ||AES-256-GCM-AEAD<br>AES-256-OCB-AEAD<br>ChaCha20-Poly1305<br>XChaCha20-Poly1305 |
112-
| encryption_password | 任意字符 |视情况|设置了 encryption_algorithm 时必填|
111+
| encryption_algorithm | XOR<br>AES-GCM<br>AES-OCB<br>chacha20<br>xchacha20<br>none ||单纯异或运算<br>AES-256-GCM-AEAD<br>AES-256-OCB-AEAD<br>ChaCha20-Poly1305<br>XChaCha20-Poly1305<br>不加密 |
112+
| encryption_password | 任意字符 |视情况|设置了 encryption_algorithm 使用加密时必填,none与XOR除外|
113113
| timeout | 0 - 65535 ||单位“秒”。预设值为 1800,设为 0 则使用预设值<br>该选项表示的是,UDP 应用程序 ↔ udphop 之间的超时设置 |
114114
| keep_alive | 0 - 65535 ||预设值为 0,等于停用 Keep Alive |
115115
| stun_server | STUN 服务器地址 ||listen_port 为端口范围模式时不可使用|

README_EN.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ encryption_algorithm=AES-GCM
106106
| destination_port | 1 - 65535 | Yes | Specify the port range when running as a client |
107107
| destination_address | IP address, domain name | Yes | When inputting an IPv6 address, no need for square brackets. Multiple addresses should be comma-separated.|
108108
| dport_refresh | 20 - 65535 | No | Unit: seconds. Default value is 60 seconds. If less than 20 seconds, it will be considered as 20 seconds; if greater than 65535, it will be considered as 65536 seconds |
109-
| encryption_algorithm| AES-GCM<br>AES-OCB<br>chacha20<br>xchacha20 | No | Select from AES-256-GCM-AEAD, AES-256-OCB-AEAD, ChaCha20-Poly1305, XChaCha20-Poly1305 |
110-
| encryption_password | Any characters | Depending on situation | Required when setting encryption_algorithm |
109+
| encryption_algorithm | XOR<br>AES-GCM<br>AES-OCB<br>chacha20<br>xchacha20<br>none |No |XOR Only<br>AES-256-GCM-AEAD<br>AES-256-OCB-AEAD<br>ChaCha20-Poly1305<br>XChaCha20-Poly1305<br>No Encryption |
110+
| encryption_password | Any character |Depends…|…on the setting of encryption_algorithm, if the value is set and it is neither `none` nor `XOR`, it is required|
111111
| timeout | 0 - 65535 | No | Unit: seconds. Default value is 1800. Set to 0 to use the default value. Represents the timeout setting between the UDP application and udphop |
112112
| keep_alive | 0 - 65535 | No | Default value is 0, which means Keep Alive is disabled |
113113
| stun_server | STUN server address | No | Cannot be used when listen_port is in port range mode |

src/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
int main(int argc, char *argv[])
1717
{
1818
#ifdef __cpp_lib_format
19-
std::cout << std::format("{} version 20250112\n", app_name);
19+
std::cout << std::format("{} version 20250301\n", app_name);
2020
if (argc <= 1)
2121
{
2222
std::cout << std::format("Usage: {} config1.conf\n", app_name);
2323
std::cout << std::format(" {} config1.conf config2.conf...\n", (int)app_name.length(), app_name.data());
2424
return 0;
2525
}
2626
#else
27-
std::cout << app_name << " version 20250112\n";
27+
std::cout << app_name << " version 20250301\n";
2828
if (argc <= 1)
2929
{
3030
std::cout << "Usage: " << app_name << " config1.conf\n";

src/networks/client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,9 +463,9 @@ void client_mode::data_sender(std::shared_ptr<udp_mappings> udp_session_ptr, std
463463

464464
void client_mode::data_sender(std::shared_ptr<udp_mappings> udp_session_ptr)
465465
{
466-
udp_session_ptr->forwarder_encryption_task_count--;
467466
if (udp_session_ptr == nullptr)
468467
return;
468+
udp_session_ptr->forwarder_encryption_task_count--;
469469
std::unique_lock locker{ udp_session_ptr->mutex_encryptions_via_forwarder };
470470
if (udp_session_ptr->encryptions_via_forwarder.empty())
471471
return;

src/networks/relay.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,9 @@ void relay_mode::data_sender_via_listener(std::shared_ptr<udp_mappings> udp_sess
652652

653653
void relay_mode::data_sender_via_listener(std::shared_ptr<udp_mappings> udp_session_ptr)
654654
{
655-
udp_session_ptr->listener_encryption_task_count--;
656655
if (udp_session_ptr == nullptr)
657656
return;
657+
udp_session_ptr->listener_encryption_task_count--;
658658
std::unique_lock locker{ udp_session_ptr->mutex_encryptions_via_listener };
659659
if (udp_session_ptr->encryptions_via_listener.empty())
660660
return;

src/networks/server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,8 @@ void server_mode::data_sender(std::shared_ptr<udp_mappings> udp_session_ptr, con
473473

474474
void server_mode::data_sender(std::shared_ptr<udp_mappings> udp_session_ptr)
475475
{
476-
udp_session_ptr->listener_encryption_task_count--;
477476
if (udp_session_ptr == nullptr) return;
477+
udp_session_ptr->listener_encryption_task_count--;
478478
std::unique_lock locker{ udp_session_ptr->mutex_encryptions_via_listener };
479479
if (udp_session_ptr->encryptions_via_listener.empty())
480480
return;

src/shares/configurations.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ std::vector<std::string> parse_the_rest(const std::vector<std::string> &args, us
152152
case strhash("none"):
153153
current_settings->encryption = encryption_mode::none;
154154
break;
155+
case strhash("xor"):
156+
current_settings->encryption = encryption_mode::plain_xor;
157+
break;
155158
case strhash("aes-gcm"):
156159
current_settings->encryption = encryption_mode::aes_gcm;
157160
break;
@@ -328,6 +331,7 @@ void check_settings(user_settings &current_user_settings, std::vector<std::strin
328331
if (current_user_settings.encryption != encryption_mode::empty &&
329332
current_user_settings.encryption != encryption_mode::unknow &&
330333
current_user_settings.encryption != encryption_mode::none &&
334+
current_user_settings.encryption != encryption_mode::plain_xor &&
331335
current_user_settings.encryption_password.empty())
332336
error_msg.emplace_back("encryption_password is not set");
333337

src/shares/data_operations.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ std::pair<std::string, size_t> encrypt_data(const std::string &password, encrypt
173173
if (length <= 0)
174174
return { "empty data", 0 };
175175

176-
bool no_encryption = false;
176+
bool plain_xor = false;
177177
size_t cipher_length = 0;
178178
std::array<uint8_t, 2> iv_raw{};
179179
std::string error_message;
@@ -207,12 +207,16 @@ std::pair<std::string, size_t> encrypt_data(const std::string &password, encrypt
207207
error_message = xcc20.encrypt(password, data_ptr, length, data_ptr, cipher_length);
208208
break;
209209
}
210+
case encryption_mode::plain_xor:
211+
{
212+
plain_xor = true;
213+
[[fallthrough]];
214+
}
210215
default:
211216
{
212217
thread_local simple_hashing checksum_hash;
213218
iv_raw = checksum_hash.checksum16(data_ptr, length);
214219
cipher_length = length;
215-
no_encryption = true;
216220
break;
217221
}
218222
};
@@ -223,15 +227,15 @@ std::pair<std::string, size_t> encrypt_data(const std::string &password, encrypt
223227
cipher_length += constant_values::iv_checksum_block_size;
224228
}
225229

226-
if (no_encryption)
230+
if (plain_xor)
227231
xor_forward(data_ptr, cipher_length);
228232

229233
return { std::move(error_message), cipher_length };
230234
}
231235

232236
std::vector<uint8_t> encrypt_data(const std::string &password, encryption_mode mode, const void *data_ptr, int length, std::string &error_message)
233237
{
234-
bool no_encryption = false;
238+
bool plain_xor = false;
235239
size_t cipher_length = length;
236240
std::array<uint8_t, 2> iv_raw{};
237241
std::vector<uint8_t> cipher_cache(length + constant_values::encryption_block_reserve + constant_values::iv_checksum_block_size);
@@ -274,12 +278,16 @@ std::vector<uint8_t> encrypt_data(const std::string &password, encryption_mode m
274278
cipher_cache.resize(cipher_length + constant_values::iv_checksum_block_size);
275279
break;
276280
}
281+
case encryption_mode::plain_xor:
282+
{
283+
plain_xor = true;
284+
[[fallthrough]];
285+
}
277286
default:
278287
{
279288
thread_local simple_hashing checksum_hash;
280289
iv_raw = checksum_hash.checksum16(data_ptr, length);
281290
cipher_length = length;
282-
no_encryption = true;
283291
cipher_cache.resize(cipher_length + constant_values::iv_checksum_block_size);
284292
std::copy_n((const uint8_t *)data_ptr, length, cipher_cache.begin());
285293
break;
@@ -291,15 +299,15 @@ std::vector<uint8_t> encrypt_data(const std::string &password, encryption_mode m
291299
*(uint16_t*)(cipher_cache.data() + cipher_length) = *(uint16_t*)iv_raw.data();
292300
}
293301

294-
if (no_encryption)
302+
if (plain_xor)
295303
xor_forward(cipher_cache);
296304

297305
return cipher_cache;
298306
}
299307

300308
std::vector<uint8_t> encrypt_data(const std::string &password, encryption_mode mode, std::vector<uint8_t> &&input_data, std::string &error_message)
301309
{
302-
bool no_encryption = false;
310+
bool plain_xor = false;
303311
std::array<uint8_t, 2> iv_raw{};
304312
switch (mode)
305313
{
@@ -339,6 +347,11 @@ std::vector<uint8_t> encrypt_data(const std::string &password, encryption_mode m
339347
return input_data;
340348
break;
341349
}
350+
case encryption_mode::plain_xor:
351+
{
352+
plain_xor = true;
353+
[[fallthrough]];
354+
}
342355
default:
343356
{
344357
thread_local simple_hashing checksum_hash;
@@ -351,7 +364,7 @@ std::vector<uint8_t> encrypt_data(const std::string &password, encryption_mode m
351364
input_data.resize(cipher_length + constant_values::iv_checksum_block_size);
352365
*(uint16_t*)(input_data.data() + cipher_length) = *(uint16_t*)iv_raw.data();
353366

354-
if (no_encryption)
367+
if (plain_xor)
355368
xor_forward(input_data);
356369

357370
return input_data;
@@ -398,10 +411,14 @@ std::pair<std::string, size_t> decrypt_data(const std::string &password, encrypt
398411
error_message = xcc20.decrypt(password, data_ptr, input_length, data_ptr, data_length);
399412
break;
400413
}
401-
default:
414+
case encryption_mode::plain_xor:
402415
{
403416
xor_backward(data_ptr, length);
404-
*(uint16_t*)iv_raw.data() = *(uint16_t*)(data_ptr + input_length);
417+
*(uint16_t *)iv_raw.data() = *(uint16_t *)(data_ptr + input_length);
418+
[[fallthrough]];
419+
}
420+
default:
421+
{
405422
data_length = input_length;
406423
thread_local simple_hashing checksum_hash;
407424
std::array<uint8_t, 2> checksum16_value = checksum_hash.checksum16(data_ptr, data_length);
@@ -458,13 +475,17 @@ std::vector<uint8_t> decrypt_data(const std::string &password, encryption_mode m
458475
data_cache = xcc20.decrypt(password, std::move(data_cache), error_message);
459476
break;
460477
}
461-
default:
478+
case encryption_mode::plain_xor:
462479
{
463480
data_cache.resize(length);
464481
std::copy_n((const uint8_t *)data_ptr, length, data_cache.begin());
465482
xor_backward(data_cache);
466-
*(uint16_t*)iv_raw.data() = *(uint16_t*)(data_cache.data() + data_length);
483+
*(uint16_t *)iv_raw.data() = *(uint16_t *)(data_cache.data() + data_length);
467484
data_cache.resize(data_length);
485+
[[fallthrough]];
486+
}
487+
default:
488+
{
468489
thread_local simple_hashing checksum_hash;
469490
std::array<uint8_t, 2> checksum16_value = checksum_hash.checksum16(data_cache.data(), data_length);
470491
if (checksum16_value != iv_raw)
@@ -527,10 +548,14 @@ std::vector<uint8_t> decrypt_data(const std::string &password, encryption_mode m
527548
return input_data;
528549
break;
529550
}
530-
default:
551+
case encryption_mode::plain_xor:
531552
{
532553
xor_backward(input_data);
533-
*(uint16_t*)iv_raw.data() = *(uint16_t*)(input_data.data() + data_length);
554+
*(uint16_t *)iv_raw.data() = *(uint16_t *)(input_data.data() + data_length);
555+
[[fallthrough]];
556+
}
557+
default:
558+
{
534559
thread_local simple_hashing checksum_hash;
535560
std::array<uint8_t, 2> checksum16_value = checksum_hash.checksum16(input_data.data(), input_data.size());
536561
if (checksum16_value != iv_raw)

src/shares/share_defines.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
constexpr std::string_view app_name = "udphop";
2222

2323
enum class running_mode { unknow, empty, server, client, relay, relay_ingress, relay_egress };
24-
enum class encryption_mode { unknow, empty, none, aes_gcm, aes_ocb, chacha20, xchacha20 };
24+
enum class encryption_mode { unknow, empty, none, plain_xor, aes_gcm, aes_ocb, chacha20, xchacha20 };
2525
enum class ip_only_options : unsigned short { not_set = 0, ipv4 = 1, ipv6 = 2 };
2626

2727
namespace constant_values

0 commit comments

Comments
 (0)