Skip to content

Commit 6c8a5dd

Browse files
committed
Initial commit
0 parents  commit 6c8a5dd

File tree

11 files changed

+763
-0
lines changed

11 files changed

+763
-0
lines changed

.clang-format

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
Language: Cpp
3+
Standard: c++17
4+
BasedOnStyle: Microsoft
5+
6+
IndentExternBlock: NoIndent
7+
PointerAlignment: Left

.github/workflows/ci.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: CI
2+
on: [push, pull_request]
3+
jobs:
4+
build:
5+
runs-on: ${{ matrix.runner }}
6+
strategy:
7+
matrix:
8+
os: [linux, windows, macos]
9+
build_type: [Debug, RelWithDebInfo]
10+
arch: [x86, x64]
11+
cmake: [minimal, latest]
12+
exclude:
13+
- os: linux
14+
arch: x86
15+
- os: windows
16+
cmake: minimal
17+
- os: macos
18+
arch: x86
19+
- os: macos
20+
cmake: minimal
21+
include:
22+
- cmake: minimal
23+
cmake_url_part: v3.5/cmake-3.5.2
24+
- os: linux
25+
runner: ubuntu-latest
26+
- os: windows
27+
runner: windows-latest
28+
- os: windows
29+
arch: x86
30+
cmake_args: -A Win32
31+
- os: windows
32+
arch: x64
33+
cmake_args: -A x64
34+
- os: macos
35+
runner: macos-latest
36+
steps:
37+
- name: Checkout
38+
uses: actions/checkout@v1
39+
- name: Install dependencies (linux)
40+
if: matrix.os == 'linux'
41+
run: |
42+
set -ex
43+
cmake_url="https://cmake.org/files"
44+
cmake_url_part="${{ matrix.cmake_url_part }}"
45+
if [ -n "$cmake_url_part" ]; then
46+
cmake_url_part="${cmake_url_part}-Linux-x86_64.tar.gz"
47+
else
48+
cmake_url_part="LatestRelease/$(wget --quiet --no-check-certificate "${cmake_url}/LatestRelease/cmake-latest-files-v1.json" -O - | jq -r '[.files[] | select(.class == "archive" and (.os[] | contains("linux")) and (.architecture[] | contains("x86_64")))] | .[0] | .name')"
49+
fi
50+
wget --no-check-certificate "${cmake_url}/${cmake_url_part}" -O /tmp/cmake.tar.gz
51+
sudo tar xf /tmp/cmake.tar.gz -C /usr/local --strip-components 1
52+
- name: CMake version
53+
run: cmake --version
54+
- name: Configure
55+
run: cmake -E make_directory _build && cmake -E chdir _build cmake .. -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} ${{ matrix.cmake_args }}
56+
- name: Build
57+
run: cmake --build _build --config ${{ matrix.build_type }}
58+
- name: Test
59+
run: cmake -E chdir _build ctest --build-config ${{ matrix.build_type }} --output-on-failure

CMakeLists.txt

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
project(arc4 VERSION 1.0 LANGUAGES C)
3+
4+
set(ARC4_STANDALONE_BUILD OFF)
5+
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
6+
set(ARC4_STANDALONE_BUILD ON)
7+
endif()
8+
9+
option(ARC4_ENABLE_INSTALL "${PROJECT_NAME}: Enable install" ${ARC4_STANDALONE_BUILD})
10+
option(ARC4_ENABLE_TESTS "${PROJECT_NAME}: Enable tests" ${ARC4_STANDALONE_BUILD})
11+
option(ARC4_ENABLE_WERROR "${PROJECT_NAME}: Treat warnings as errors" ${ARC4_STANDALONE_BUILD})
12+
13+
if(ARC4_ENABLE_INSTALL)
14+
include(GNUInstallDirs)
15+
include(CMakePackageConfigHelpers)
16+
endif()
17+
18+
if(ARC4_ENABLE_TESTS)
19+
enable_testing()
20+
endif()
21+
22+
if(ARC4_STANDALONE_BUILD)
23+
if(NOT CMAKE_C_STANDARD)
24+
set(CMAKE_C_STANDARD 99)
25+
set(CMAKE_C_STANDARD_REQUIRED ON)
26+
set(CMAKE_C_EXTENSIONS OFF)
27+
endif()
28+
29+
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
30+
add_compile_options(
31+
-Wall
32+
-Wextra
33+
-pedantic
34+
$<$<BOOL:${ARC4_ENABLE_WERROR}>:-Werror>)
35+
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
36+
add_compile_options(
37+
/W4
38+
$<$<BOOL:${ARC4_ENABLE_WERROR}>:/WX>)
39+
endif()
40+
endif()
41+
42+
add_subdirectory(src)
43+
44+
if(ARC4_ENABLE_TESTS)
45+
add_subdirectory(test)
46+
endif()
47+
48+
if(ARC4_ENABLE_INSTALL)
49+
write_basic_package_version_file(
50+
${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
51+
VERSION ${PROJECT_VERSION}
52+
COMPATIBILITY AnyNewerVersion)
53+
54+
configure_file(
55+
config.cmake.in
56+
${PROJECT_NAME}-config.cmake
57+
@ONLY)
58+
59+
install(
60+
EXPORT ${PROJECT_NAME}-targets
61+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
62+
NAMESPACE ${PROJECT_NAME}::)
63+
64+
install(
65+
FILES
66+
${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
67+
${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
68+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
69+
70+
install(
71+
FILES
72+
LICENSE
73+
README.md
74+
DESTINATION ${CMAKE_INSTALL_DOCDIR})
75+
endif()

LICENSE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2021, Mike Gelfand
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
3. Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# ARC4: Alleged RC4 implementation
2+
3+
This is a tiny and reusable implementation of [alleged RC4](https://en.wikipedia.org/wiki/RC4) cipher.
4+
5+
The use of RC4 is declining due to various security concerns.
6+
A number of popular cryptographic libraries have started to mark it as deprecated or remove it completely:
7+
* **OpenSSL**: not built by default in 1.1, moved to "legacy" provider in 3.0
8+
* **WolfSSL (CyaSSL)**: not built by default in 3.4.6
9+
* **MbedTLS (PolarSSL)**: removed in 3.0
10+
11+
Nonetheless, it's still used in e.g. BitTorrent software, and forcing people to do some more work to make RC4 available in the aforementioned libraries is not always possible or desirable.

config.cmake.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include(${CMAKE_CURRENT_LIST_DIR}/@[email protected])

src/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
add_library(arc4 STATIC
2+
arc4.c
3+
arc4.h)
4+
5+
if(NOT ARC4_STANDALONE_BUILD)
6+
add_library(${PROJECT_NAME}::arc4 ALIAS arc4)
7+
endif()
8+
9+
target_include_directories(arc4
10+
PUBLIC
11+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
12+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
13+
14+
if(ARC4_ENABLE_INSTALL)
15+
install(
16+
TARGETS arc4
17+
EXPORT ${PROJECT_NAME}-targets
18+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
19+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
20+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
21+
22+
install(
23+
FILES arc4.h
24+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
25+
endif()

src/arc4.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "arc4.h"
2+
3+
#include <assert.h>
4+
5+
#define ARC4_MAGIC 0x34637261 // 'arc4' (LE)
6+
7+
static inline void arc4_swap(struct arc4_context* ctx, size_t i, size_t j)
8+
{
9+
assert(ctx != NULL);
10+
assert(i < 256);
11+
assert(j < 256);
12+
13+
uint8_t const t = ctx->s[i];
14+
ctx->s[i] = ctx->s[j];
15+
ctx->s[j] = t;
16+
}
17+
18+
static inline uint8_t arc4_next(struct arc4_context* ctx)
19+
{
20+
assert(ctx != NULL);
21+
22+
ctx->i += 1;
23+
ctx->j += ctx->s[ctx->i];
24+
25+
arc4_swap(ctx, ctx->i, ctx->j);
26+
27+
return ctx->s[(uint8_t)(ctx->s[ctx->i] + ctx->s[ctx->j])];
28+
}
29+
30+
void arc4_init(struct arc4_context* ctx, void const* key, size_t key_length)
31+
{
32+
assert(ctx != NULL);
33+
assert(key != NULL);
34+
assert(key_length < 256);
35+
36+
#ifndef NDEBUG
37+
ctx->magic = ARC4_MAGIC;
38+
#endif
39+
40+
ctx->i = 0;
41+
ctx->j = 0;
42+
43+
for (size_t i = 0; i < 256; ++i)
44+
{
45+
ctx->s[i] = (uint8_t)i;
46+
}
47+
48+
for (size_t i = 0, j = 0; i < 256; ++i)
49+
{
50+
j = (uint8_t)(j + ctx->s[i] + ((uint8_t const*)key)[i % key_length]);
51+
arc4_swap(ctx, i, j);
52+
}
53+
}
54+
55+
void arc4_process(struct arc4_context* ctx, void const* src_data, void* dst_data, size_t data_length)
56+
{
57+
assert(ctx != NULL);
58+
assert(ctx->magic == ARC4_MAGIC);
59+
60+
if (data_length == 0)
61+
{
62+
return;
63+
}
64+
65+
assert(src_data != NULL);
66+
assert(dst_data != NULL);
67+
assert(data_length < SIZE_MAX);
68+
69+
for (size_t i = 0; i < data_length; ++i)
70+
{
71+
((uint8_t*)dst_data)[i] = ((uint8_t const*)src_data)[i] ^ arc4_next(ctx);
72+
}
73+
}
74+
75+
void arc4_discard(struct arc4_context* ctx, size_t length)
76+
{
77+
assert(ctx != NULL);
78+
assert(ctx->magic == ARC4_MAGIC);
79+
assert(length < SIZE_MAX);
80+
81+
for (size_t i = 0; i < length; ++i)
82+
{
83+
arc4_next(ctx);
84+
}
85+
}

src/arc4.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
struct arc4_context
11+
{
12+
#ifndef NDEBUG
13+
uint32_t magic;
14+
#endif
15+
uint8_t i;
16+
uint8_t j;
17+
uint8_t s[256];
18+
};
19+
20+
void arc4_init(struct arc4_context* ctx, void const* key, size_t key_length);
21+
void arc4_process(struct arc4_context* ctx, void const* src_data, void* dst_data, size_t data_length);
22+
void arc4_discard(struct arc4_context* ctx, size_t length);
23+
24+
#ifdef __cplusplus
25+
}
26+
#endif

test/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_executable(arc4_test
2+
test.c)
3+
4+
target_link_libraries(arc4_test
5+
PRIVATE
6+
arc4)
7+
8+
add_test(
9+
NAME arc4_test
10+
COMMAND arc4_test)

0 commit comments

Comments
 (0)