openGPMP
Open Source Mathematics Package
rc6.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file.
25  *
26  *
27  *
28  * This software is distributed on an AS IS basis, WITHOUT
29  * WARRANTY OF ANY KIND, either express or implied.
30  *
31  ************************************************************************/
32 #include <cmath>
33 #include <cstdint>
34 #include <openGPMP/nt/rc6.hpp>
35 #include <stdexcept>
36 
37 RC6::RC6(const std::vector<uint8_t> &key) {
38  key_schedule(key);
39 }
40 
41 void RC6::key_schedule(const std::vector<uint8_t> &key) {
42  std::vector<uint32_t> L = expand(key);
43  S.resize(2 * (r + 1));
44  const uint32_t P = 0xB7E15163;
45  const uint32_t Q = 0x9E3779B9;
46  S[0] = P;
47  for (int i = 1; i < 2 * (r + 1); ++i) {
48  S[i] = S[i - 1] + Q;
49  }
50  uint32_t A = 0, B = 0;
51  int i = 0, j = 0;
52  for (int k = 0; k < 3 * std::max(b, 2 * (r + 1)); ++k) {
53  A = S[i] = rotl((S[i] + A + B), 3);
54  B = L[j] = rotl((L[j] + A + B), (A + B));
55  i = (i + 1) % (2 * (r + 1));
56  j = (j + 1) % b;
57  }
58 }
59 
60 std::vector<uint32_t> RC6::expand(const std::vector<uint8_t> &key) {
61  std::vector<uint32_t> L(b / 4);
62  for (size_t i = 0; i < key.size(); i++) {
63  L[i / 4] |= (static_cast<uint32_t>(key[i]) << (8 * (i % 4)));
64  }
65  return L;
66 }
67 
68 uint32_t RC6::rotl(uint32_t val, int shift) {
69  return (val << shift) | (val >> (w - shift));
70 }
71 
72 uint32_t RC6::rotr(uint32_t val, int shift) {
73  return (val >> shift) | (val << (w - shift));
74 }
75 
76 void RC6::encrypt_block(const uint32_t plaintext[2], uint32_t ciphertext[2]) {
77  uint32_t A = plaintext[0], B = plaintext[1];
78  A += S[0];
79  B += S[1];
80  for (int i = 1; i <= r; ++i) {
81  A = rotl(A ^ B, B) + S[2 * i];
82  B = rotl(B ^ A, A) + S[2 * i + 1];
83  }
84  ciphertext[0] = A;
85  ciphertext[1] = B;
86 }
87 
88 void RC6::decrypt_block(const uint32_t ciphertext[2], uint32_t plaintext[2]) {
89  uint32_t A = ciphertext[0], B = ciphertext[1];
90  for (int i = r; i >= 1; --i) {
91  B = rotr(B - S[2 * i + 1], A) ^ A;
92  A = rotr(A - S[2 * i], B) ^ B;
93  }
94  B -= S[1];
95  A -= S[0];
96  plaintext[0] = A;
97  plaintext[1] = B;
98 }
99 
100 std::vector<uint8_t> RC6::encrypt(const std::vector<uint8_t> &plaintext) {
101  if (plaintext.size() % 8 != 0) {
102  throw std::invalid_argument(
103  "Plaintext length must be a multiple of 8 bytes");
104  }
105  std::vector<uint8_t> ciphertext;
106  ciphertext.reserve(plaintext.size());
107  for (size_t i = 0; i < plaintext.size(); i += 8) {
108  uint32_t block[2];
109  uint32_t encrypted_block[2];
110  for (int j = 0; j < 8; ++j) {
111  block[j / 4] |=
112  (static_cast<uint32_t>(plaintext[i + j]) << (8 * (j % 4)));
113  }
114  encrypt_block(block, encrypted_block);
115  for (int j = 0; j < 2; ++j) {
116  ciphertext.push_back((encrypted_block[j] >> 24) & 0xFF);
117  ciphertext.push_back((encrypted_block[j] >> 16) & 0xFF);
118  ciphertext.push_back((encrypted_block[j] >> 8) & 0xFF);
119  ciphertext.push_back(encrypted_block[j] & 0xFF);
120  }
121  }
122  return ciphertext;
123 }
124 
125 std::vector<uint8_t> RC6::decrypt(const std::vector<uint8_t> &ciphertext) {
126  if (ciphertext.size() % 8 != 0) {
127  throw std::invalid_argument(
128  "Ciphertext length must be a multiple of 8 bytes");
129  }
130  std::vector<uint8_t> plaintext;
131  plaintext.reserve(ciphertext.size());
132  for (size_t i = 0; i < ciphertext.size(); i += 8) {
133  uint32_t block[2];
134  uint32_t decrypted_block[2];
135  for (int j = 0; j < 2; ++j) {
136  block[j] =
137  (static_cast<uint32_t>(ciphertext[i + 4 * j]) << 24) |
138  (static_cast<uint32_t>(ciphertext[i + 4 * j + 1]) << 16) |
139  (static_cast<uint32_t>(ciphertext[i + 4 * j + 2]) << 8) |
140  static_cast<uint32_t>(ciphertext[i + 4 * j + 3]);
141  }
142  decrypt_block(block, decrypted_block);
143  for (int j = 0; j < 8; ++j) {
144  plaintext.push_back((decrypted_block[j / 4] >> (8 * (j % 4))) &
145  0xFF);
146  }
147  }
148  return plaintext;
149 }
std::vector< uint8_t > encrypt(const std::vector< uint8_t > &plaintext)
Encrypts plaintext using RC6 algorithm.
Definition: rc6.cpp:100
std::vector< uint32_t > expand(const std::vector< uint8_t > &key)
Performs key expansion.
Definition: rc6.cpp:60
std::vector< uint8_t > decrypt(const std::vector< uint8_t > &ciphertext)
Decrypts ciphertext using RC6 algorithm.
Definition: rc6.cpp:125
void key_schedule(const std::vector< uint8_t > &key)
Generates the key schedule from the given key.
Definition: rc6.cpp:41
const int r
Definition: rc6.hpp:68
const int b
Definition: rc6.hpp:69
std::vector< uint32_t > S
Definition: rc6.hpp:71
uint32_t rotl(uint32_t val, int shift)
Performs left rotation.
Definition: rc6.cpp:68
void decrypt_block(const uint32_t ciphertext[2], uint32_t plaintext[2])
Decrypts a single block of ciphertext.
Definition: rc6.cpp:88
void encrypt_block(const uint32_t plaintext[2], uint32_t ciphertext[2])
Encrypts a single block of plaintext.
Definition: rc6.cpp:76
RC6(const std::vector< uint8_t > &key)
Constructor for RC6 class.
Definition: rc6.cpp:37
const int w
Definition: rc6.hpp:67
uint32_t rotr(uint32_t val, int shift)
Performs right rotation.
Definition: rc6.cpp:72
list A
Definition: linalg.py:22
list B
Definition: linalg.py:23