A fast, portable, and easy-to-use implementation of the classic RC cryptographic ciphers (RC2, RC4, RC5, RC6) provided in both C and C++ header-only libraries.
- Overview
- RC Cipher Family: History
- Supported Ciphers & Algorithms
- Library Versions
- Installation
- Usage Examples
- Detailed Cipher Documentation
- Performance Notes
- License
- References
This repository provides implementations of Ronald Rivest’s RC (Rivest Cipher, or Ron’s Code) family of encryption algorithms: RC2, RC4, RC5, and RC6, in both C and modern C++ (header-only) styles. The C version prioritizes maximum performance and bare-metal efficiency, while the C++ version offers a user-friendly, object-oriented API with std::string
support for rapid prototyping, education, and ease of use.
The RC (Rivest Cipher or Ron’s Code) algorithms were developed by Ronald L. Rivest between the 1980s and 1990s:
- RC2 (1987): Designed as a block cipher to replace DES, with variable key sizes, and optimized for software.
- RC4 (1987): A stream cipher used widely in protocols like SSL/TLS and WEP/WPA for wireless security due to its speed and simplicity.
- RC5 (1994): Introduces variable block sizes, variable key sizes, and variable rounds, along with heavy use of data-dependent rotations.
- RC6 (1998): An evolution of RC5, designed as a candidate for the AES competition, featuring 128-bit blocks and more complex operations.
Each RC algorithm improved upon its predecessor, introducing new cryptographic principles and optimizations for hardware and software platforms.
- Block cipher with 8-byte (64-bit) blocks.
- Variable key size (up to 128 bits typically).
- 16 rounds of complex mixing and mashing operations.
- Notable for its use in legacy applications and backward compatibility.
- Stream cipher, not a block cipher.
- Variable key size (1 to 256 bytes).
- Simple and fast, but now deprecated in secure applications due to vulnerabilities.
- Used in SSL, WEP, and other protocols (now considered obsolete).
- Block cipher with variable block size (32, 64, or 128 bits; library uses 64-bit blocks).
- Variable number of rounds (default: 12).
- Variable key sizes.
- Features heavy use of data-dependent rotations and modular addition.
- Block cipher, always 128-bit blocks.
- Uses four 32-bit words per block.
- Variable key size and rounds (default: 20).
- Uses integer multiplication and additional mixing for improved security.
- AES finalist.
Version | Filename | Language | API Style | Use Case | Notes |
---|---|---|---|---|---|
C | rc.h |
C | Procedural | Maximum speed, embedded | Fastest, low-level |
C++ | rc.hpp |
C++17+ | OOP, STL | User-friendly, modern | Easy for beginners, flexible |
- Prefer the C version (
rc.h
) for performance-critical or embedded use. - Use the C++ version (
rc.hpp
) for rapid development, education, or if you want a higher-level API.
-
Add the header file you want:
- For C: Copy
rc.h
into your project. - For C++: Copy
rc.hpp
into your project.
- For C: Copy
-
No library build step required: Both versions are header-only.
#include "rc.h"
#include <stdio.h>
#include <string.h>
int main() {
char key[] = "mykey";
char plaintext[] = "Secret message!";
unsigned char ciphertext[128];
unsigned char decrypted[128];
// RC2 Encrypt
size_t ctlen = RC2_Encrypt(key, plaintext, ciphertext);
// RC2 Decrypt
size_t ptlen = RC2_Decrypt(key, ciphertext, ctlen, decrypted);
printf("Original: %s\n", plaintext);
printf("Encrypted (hex): ");
char hex[256];
to_hex(ciphertext, ctlen, hex);
printf("%s\n", hex);
printf("Decrypted: %.*s\n", (int)ptlen, decrypted);
return 0;
}
#include "rc.hpp"
#include <iostream>
int main() {
RC2 rc2;
std::string key = "mykey";
std::string plaintext = "Secret message!";
std::string ciphertext = rc2.Encrypt(plaintext, key);
std::string decrypted = rc2.Decrypt(ciphertext, key);
std::cout << "Original: " << plaintext << std::endl;
std::cout << "Encrypted (hex): " << RCUtils::ToHex(ciphertext) << std::endl;
std::cout << "Decrypted: " << decrypted << std::endl;
return 0;
}
- Block cipher with 64-bit blocks and variable key size (typically up to 128 bits).
- Rounds: 16, divided into MIX and MASH phases.
- Key Expansion: The user key is expanded into 64 16-bit words using a fixed permutation table (PI_SUBST).
- Encryption Process:
- Input block split into 4 16-bit words.
- 16 rounds: Each round, words are mixed using modular addition, bitwise operations, and key words.
- After rounds 5 and 11, special key mixing ("mash") occurs using key words indexed by earlier state.
- Each word is rotated left by a different amount after mixing.
- Security: Designed as a DES replacement; considered safe for legacy but not for new systems.
- Stream cipher with variable key size (1–256 bytes).
- Key Scheduling: Initializes a 256-byte state array, then permutes it based on the key.
- Keystream Generation: For each byte, two indexes are updated, S-box is swapped, and the output byte is selected.
- Encryption: XORs the keystream with the plaintext.
- Security: Once dominant but now considered broken due to biases in the keystream and weak key scheduling; not recommended for new applications.
- Block cipher with variable block size (32, 64, or 128 bits), key size (0–2040 bits), and number of rounds (0–255).
- Library default: 64-bit blocks, 12 rounds.
- Key Expansion: User key is expanded into a set of round keys (S array) using modular arithmetic.
- Encryption:
- Input split into two words (A, B).
- Initial key mixing (A += S[0], B += S[1]).
- For each round:
- A = ((A ^ B) <<< B) + S[2i]
- B = ((B ^ A) <<< A) + S[2i+1]
- Output is (A, B).
- Features: Data-dependent rotations provide "avalanche" effect and resistance to differential cryptanalysis.
- Security: Flexible and strong if configured with enough rounds and a good key.
- Block cipher with 128-bit (16-byte) blocks and variable key size (up to 256 bits).
- Rounds: Default 20 rounds.
- Key Expansion: Similar to RC5 but generates more subkeys (44 for 20 rounds).
- Encryption:
- Block split into four 32-bit words (A, B, C, D).
- Initial key mixing: B += S[0], D += S[1].
- For each round:
- t = (B * (2B + 1)) <<< 5
- u = (D * (2D + 1)) <<< 5
- A = ((A ^ t) <<< u) + S[2i]
- C = ((C ^ u) <<< t) + S[2i+1]
- (A, B, C, D) = (B, C, D, A) (rotate variables)
- Final key mixing: A += S[2r+2], C += S[2r+3].
- Security: Designed as an AES finalist, more complex round function than RC5, and highly secure with a sufficient number of rounds.
- C version (
rc.h
): Optimized for speed, with minimal abstraction and maximum portability. Recommended for high-performance applications, embedded systems, or cryptographic research. - C++ version (
rc.hpp
): Designed for ease of use, with a modern C++ interface, automatic block handling, andstd::string
support. Ideal for education, application prototyping, and high-level use.