TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
ciphers::HillCipher Class Reference

Implementation of Hill Cipher algorithm. More...

Static Public Member Functions

static matrix< int > generate_encryption_key (size_t size, int limit1=0, int limit2=10)
 Generate encryption matrix of a given size. Larger size matrices are difficult to generate but provide more security. Important conditions are:
 
static matrix< int > generate_decryption_key (matrix< int > const &encrypt_key)
 Generate decryption matrix from an encryption matrix key.
 
static std::pair< matrix< int >, matrix< int > > generate_keys (size_t size, int limit1=0, int limit2=10)
 Generate encryption and decryption key pair.
 
static const std::string encrypt_text (const std::string &text, const matrix< int > &encrypt_key)
 Encrypt a given text using a given key.
 
static const std::string decrypt_text (const std::string &text, const matrix< int > &decrypt_key)
 Decrypt a given text using a given key.
 

Static Private Member Functions

template<typename T1 , typename T2 >
static const T2 rand_range (T1 a, T1 b)
 Function to generate a random integer in a given interval.
 
template<typename T1 , typename T2 >
static double rand_range (matrix< T2 > *M, T1 a, T1 b)
 Function overload to fill a matrix with random integers in a given interval.
 
template<typename T >
static const T gcd (T a, T b)
 Compute GCD of two integers using Euler's algorithm.
 
static const std::valarray< uint8_t > mat_mul (const std::valarray< uint8_t > &vector, const matrix< int > &key)
 helper function to perform vector multiplication with encryption or decryption matrix
 
static char get_idx_char (const uint8_t idx)
 Get the character at a given index in the STRKEY.
 
static uint8_t get_char_idx (const char ch)
 Get the index of a character in the STRKEY.
 
static const std::string codec (const std::string &text, const matrix< int > &key)
 Convenience function to perform block cipher operations. The operations are identical for both encryption and decryption.
 
template<typename T >
static matrix< double > get_inverse (matrix< T > const &A)
 
static int modulo (int a, int b)
 

Detailed Description

Implementation of Hill Cipher algorithm.

Definition at line 82 of file hill_cipher.cpp.

Member Function Documentation

◆ codec()

static const std::string ciphers::HillCipher::codec ( const std::string & text,
const matrix< int > & key )
inlinestaticprivate

Convenience function to perform block cipher operations. The operations are identical for both encryption and decryption.

Parameters
textinput text to encrypt or decrypt
keykey for encryption or decryption
Returns
encrypted/decrypted output

Definition at line 211 of file hill_cipher.cpp.

212 {
213 size_t text_len = text.length();
214 size_t key_len = key.size();
215
216 // length of output string must be a multiple of key_len
217 // create output string and initialize with '\0' character
218 size_t L2 = text_len % key_len == 0
219 ? text_len
220 : text_len + key_len - (text_len % key_len);
221 std::string coded_text(L2, '\0');
222
223 // temporary array for batch processing
224 int i;
225#ifdef _OPENMP
226#pragma parallel omp for private(i)
227#endif
228 for (i = 0; i < L2 - key_len + 1; i += key_len) {
229 std::valarray<uint8_t> batch_int(key_len);
230 for (size_t j = 0; j < key_len; j++) {
231 batch_int[j] = get_char_idx(text[i + j]);
232 }
233
234 batch_int = mat_mul(batch_int, key);
235
236 for (size_t j = 0; j < key_len; j++) {
237 coded_text[i + j] =
238 STRKEY[batch_int[j]]; // get character at key
239 }
240 }
241
242 return coded_text;
243 }
static const std::valarray< uint8_t > mat_mul(const std::valarray< uint8_t > &vector, const matrix< int > &key)
helper function to perform vector multiplication with encryption or decryption matrix
static uint8_t get_char_idx(const char ch)
Get the index of a character in the STRKEY.
static const char * STRKEY

◆ decrypt_text()

static const std::string ciphers::HillCipher::decrypt_text ( const std::string & text,
const matrix< int > & decrypt_key )
inlinestatic

Decrypt a given text using a given key.

Parameters
textstring to decrypt
decrypt_keykey for decryption
Returns
decrypted text

Definition at line 458 of file hill_cipher.cpp.

459 {
460 return codec(text, decrypt_key);
461 }
static const std::string codec(const std::string &text, const matrix< int > &key)
Convenience function to perform block cipher operations. The operations are identical for both encryp...

◆ encrypt_text()

static const std::string ciphers::HillCipher::encrypt_text ( const std::string & text,
const matrix< int > & encrypt_key )
inlinestatic

Encrypt a given text using a given key.

Parameters
textstring to encrypt
encrypt_keykey for encryption
Returns
encrypted text

Definition at line 446 of file hill_cipher.cpp.

447 {
448 return codec(text, encrypt_key);
449 }

◆ gcd()

template<typename T >
static const T ciphers::HillCipher::gcd ( T a,
T b )
inlinestaticprivate

Compute GCD of two integers using Euler's algorithm.

Parameters
afirst number
bsecond number
Returns
GCD of \(a\) and \(b\)

Definition at line 139 of file hill_cipher.cpp.

139 {
140 if (b > a) // ensure always a < b
141 std::swap(a, b);
142
143 while (b != 0) {
144 T tmp = b;
145 b = a % b;
146 a = tmp;
147 }
148
149 return a;
150 }

◆ generate_decryption_key()

static matrix< int > ciphers::HillCipher::generate_decryption_key ( matrix< int > const & encrypt_key)
inlinestatic

Generate decryption matrix from an encryption matrix key.

Parameters
encrypt_keyencryption key for which to create a decrypt key
Returns
Decryption martix

Definition at line 372 of file hill_cipher.cpp.

372 {
373 size_t size = encrypt_key.size();
374 int L = std::strlen(STRKEY);
375
376 matrix<int> decrypt_key(size, std::valarray<int>(size));
377 int det_encrypt = static_cast<int>(determinant_lu(encrypt_key));
378
379 int mat_determinant = det_encrypt < 0 ? det_encrypt % L : det_encrypt;
380
381 matrix<double> tmp_inverse = get_inverse(encrypt_key);
382 double d2 = determinant_lu(decrypt_key);
383
384 // find co-prime factor for inversion
385 int det_inv = -1;
386 for (int i = 0; i < L; i++) {
387 if (modulo(mat_determinant * i, L) == 1) {
388 det_inv = i;
389 break;
390 }
391 }
392
393 if (det_inv == -1) {
394 std::cerr << "Could not find a co-prime for inversion\n";
395 std::exit(EXIT_FAILURE);
396 }
397
398 mat_determinant = det_inv * det_encrypt;
399
400 // perform modular inverse of encryption matrix
401 int i;
402#ifdef _OPENMP
403#pragma parallel omp for private(i)
404#endif
405 for (i = 0; i < size; i++) {
406 for (int j = 0; j < size; j++) {
407 int temp = std::round(tmp_inverse[i][j] * mat_determinant);
408 decrypt_key[i][j] = modulo(temp, L);
409 }
410 }
411 return decrypt_key;
412 }
static matrix< double > get_inverse(matrix< T > const &A)
double determinant_lu(const matrix< T > &A)
std::vector< std::valarray< T > > matrix

◆ generate_encryption_key()

static matrix< int > ciphers::HillCipher::generate_encryption_key ( size_t size,
int limit1 = 0,
int limit2 = 10 )
inlinestatic

Generate encryption matrix of a given size. Larger size matrices are difficult to generate but provide more security. Important conditions are:

  1. matrix should be invertible
  2. determinant must not have any common factors with the length of character key There is no head-fast way to generate hte matrix under the given numerical restrictions of the machine but the conditions added achieve the goals. Bigger the matrix, greater is the probability of the matrix being ill-defined.
Parameters
sizesize of matrix (typically \(\text{size}\le10\))
limit1lower limit of range of random elements (default=0)
limit2upper limit of range of random elements (default=10)
Returns
Encryption martix

Definition at line 340 of file hill_cipher.cpp.

341 {
342 matrix<int> encrypt_key(size, std::valarray<int>(size));
343 matrix<int> min_mat = encrypt_key;
344 int mat_determinant = -1; // because matrix has only ints, the
345 // determinant will also be an int
346 int L = std::strlen(STRKEY);
347
348 double dd;
349 do {
350 // keeping the random number range smaller generates better
351 // defined matrices with more ease of cracking
352 dd = rand_range(&encrypt_key, limit1, limit2);
353 mat_determinant = static_cast<int>(dd);
354
355 if (mat_determinant < 0)
356 mat_determinant = (mat_determinant % L);
357 } while (std::abs(dd) > 1e3 || // while ill-defined
358 dd < 0.1 || // while singular or negative determinant
359 !std::isfinite(dd) || // while determinant is not finite
360 gcd(mat_determinant, L) != 1); // while no common factors
361 // std::cout <<
362
363 return encrypt_key;
364 }
static const T2 rand_range(T1 a, T1 b)
Function to generate a random integer in a given interval.
static const T gcd(T a, T b)
Compute GCD of two integers using Euler's algorithm.

◆ generate_keys()

static std::pair< matrix< int >, matrix< int > > ciphers::HillCipher::generate_keys ( size_t size,
int limit1 = 0,
int limit2 = 10 )
inlinestatic

Generate encryption and decryption key pair.

Parameters
sizesize of matrix key (typically \(\text{size}\le10\))
limit1lower limit of range of random elements (default=0)
limit2upper limit of range of random elements (default=10)
Returns
std::pair<matrix<int>, matrix<int>> encryption and decryption keys as a pair
See also
generate_encryption_key

Definition at line 425 of file hill_cipher.cpp.

427 {
428 matrix<int> encrypt_key = generate_encryption_key(size);
429 matrix<int> decrypt_key = generate_decryption_key(encrypt_key);
430 double det2 = determinant_lu(decrypt_key);
431 while (std::abs(det2) < 0.1 || std::abs(det2) > 1e3) {
432 encrypt_key = generate_encryption_key(size, limit1, limit2);
433 decrypt_key = generate_decryption_key(encrypt_key);
434 det2 = determinant_lu(decrypt_key);
435 }
436 return std::make_pair(encrypt_key, decrypt_key);
437 }
static matrix< int > generate_encryption_key(size_t size, int limit1=0, int limit2=10)
Generate encryption matrix of a given size. Larger size matrices are difficult to generate but provid...
static matrix< int > generate_decryption_key(matrix< int > const &encrypt_key)
Generate decryption matrix from an encryption matrix key.

◆ get_char_idx()

static uint8_t ciphers::HillCipher::get_char_idx ( const char ch)
inlinestaticprivate

Get the index of a character in the STRKEY.

Parameters
chcharacter to search
Returns
index of character

Definition at line 191 of file hill_cipher.cpp.

191 {
192 size_t L = std::strlen(STRKEY);
193
194 for (size_t idx = 0; idx <= L; idx++)
195 if (STRKEY[idx] == ch)
196 return idx;
197
198 std::cerr << __func__ << ":" << __LINE__ << ": (" << ch
199 << ") Should not reach here!\n";
200 return 0;
201 }

◆ get_idx_char()

static char ciphers::HillCipher::get_idx_char ( const uint8_t idx)
inlinestaticprivate

Get the character at a given index in the STRKEY.

Parameters
idxindex value
Returns
character at the index

Definition at line 183 of file hill_cipher.cpp.

183{ return STRKEY[idx]; }

◆ get_inverse()

template<typename T >
static matrix< double > ciphers::HillCipher::get_inverse ( matrix< T > const & A)
inlinestaticprivate

Get matrix inverse using Row-transformations. Given matrix must be a square and non-singular.

Returns
inverse matrix

Definition at line 251 of file hill_cipher.cpp.

251 {
252 // Assuming A is square matrix
253 size_t N = A.size();
254
255 matrix<double> inverse(N, std::valarray<double>(N));
256 for (size_t row = 0; row < N; row++) {
257 for (size_t col = 0; col < N; col++) {
258 // create identity matrix
259 inverse[row][col] = (row == col) ? 1.f : 0.f;
260 }
261 }
262
263 if (A.size() != A[0].size()) {
264 std::cerr << "A must be a square matrix!" << std::endl;
265 return inverse;
266 }
267
268 // preallocate a temporary matrix identical to A
269 matrix<double> temp(N, std::valarray<double>(N));
270 for (size_t row = 0; row < N; row++) {
271 for (size_t col = 0; col < N; col++)
272 temp[row][col] = static_cast<double>(A[row][col]);
273 }
274
275 // start transformations
276 for (size_t row = 0; row < N; row++) {
277 for (size_t row2 = row; row2 < N && temp[row][row] == 0; row2++) {
278 // this to ensure diagonal elements are not 0
279 temp[row] = temp[row] + temp[row2];
280 inverse[row] = inverse[row] + inverse[row2];
281 }
282
283 for (size_t col2 = row; col2 < N && temp[row][row] == 0; col2++) {
284 // this to further ensure diagonal elements are not 0
285 for (size_t row2 = 0; row2 < N; row2++) {
286 temp[row2][row] = temp[row2][row] + temp[row2][col2];
287 inverse[row2][row] =
288 inverse[row2][row] + inverse[row2][col2];
289 }
290 }
291
292 if (temp[row][row] == 0) {
293 // Probably a low-rank matrix and hence singular
294 std::cerr << "Low-rank matrix, no inverse!" << std::endl;
295 return inverse;
296 }
297
298 // set diagonal to 1
299 double divisor = temp[row][row];
300 temp[row] = temp[row] / divisor;
301 inverse[row] = inverse[row] / divisor;
302 // Row transformations
303 for (size_t row2 = 0; row2 < N; row2++) {
304 if (row2 == row)
305 continue;
306 double factor = temp[row2][row];
307 temp[row2] = temp[row2] - factor * temp[row];
308 inverse[row2] = inverse[row2] - factor * inverse[row];
309 }
310 }
311
312 return inverse;
313 }
constexpr uint32_t N
A struct to represent sparse table for min() as their invariant function, for the given array A....

◆ mat_mul()

static const std::valarray< uint8_t > ciphers::HillCipher::mat_mul ( const std::valarray< uint8_t > & vector,
const matrix< int > & key )
inlinestaticprivate

helper function to perform vector multiplication with encryption or decryption matrix

Parameters
vectorvector to multiply
keyencryption or decryption key matrix
Returns
corresponding encrypted or decrypted text

Definition at line 160 of file hill_cipher.cpp.

161 {
162 std::valarray<uint8_t> out(vector); // make a copy
163
164 size_t L = std::strlen(STRKEY);
165
166 for (size_t i = 0; i < key.size(); i++) {
167 int tmp = 0;
168 for (size_t j = 0; j < vector.size(); j++) {
169 tmp += key[i][j] * vector[j];
170 }
171 out[i] = static_cast<uint8_t>(tmp % L);
172 }
173
174 return out;
175 }

◆ modulo()

static int ciphers::HillCipher::modulo ( int a,
int b )
inlinestaticprivate

Definition at line 315 of file hill_cipher.cpp.

315 {
316 int ret = a % b;
317 if (ret < 0)
318 ret += b;
319 return ret;
320 }

◆ rand_range() [1/2]

template<typename T1 , typename T2 >
static double ciphers::HillCipher::rand_range ( matrix< T2 > * M,
T1 a,
T1 b )
inlinestaticprivate

Function overload to fill a matrix with random integers in a given interval.

Parameters
Mpointer to matrix to be filled with random numbers
alower limit of interval
bupper limit of interval
Template Parameters
T1type of input range
T2type of matrix
Returns
determinant of generated random matrix
Warning
There will need to be a balance between the matrix size and the range of random numbers. If the matrix is large, the range of random numbers must be small to have a well defined keys. Or if the matrix is smaller, the random numbers range can be larger. For an 8x8 matrix, range should be no more than \([0,10]\)

Definition at line 119 of file hill_cipher.cpp.

119 {
120 for (size_t i = 0; i < M->size(); i++) {
121 for (size_t j = 0; j < M[0][0].size(); j++) {
122 M[0][i][j] = rand_range<T1, T2>(a, b);
123 }
124 }
125
126 return determinant_lu(*M);
127 }
constexpr uint8_t M
ceil(log2(N)).

◆ rand_range() [2/2]

template<typename T1 , typename T2 >
static const T2 ciphers::HillCipher::rand_range ( T1 a,
T1 b )
inlinestaticprivate

Function to generate a random integer in a given interval.

Parameters
alower limit of interval
bupper limit of interval
Template Parameters
Ttype of output
Returns
random integer in the interval \([a,b)\)

Definition at line 93 of file hill_cipher.cpp.

93 {
94 // generate random number between 0 and 1
95 long double r = static_cast<long double>(std::rand()) / RAND_MAX;
96
97 // scale and return random number as integer
98 return static_cast<T2>(r * (b - a) + a);
99 }

The documentation for this class was generated from the following file: