Нашёл в инете 2 реализации:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360. 361. 362. 363. 364. 365. 366. 367. 368. 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391. 392. 393. 394. 395. 396. 397. 398. 399. 400. 401. 402. 403. 404. 405. 406. 407. 408. 409. 410. 411. 412. 413. 414.
/*
* The GOST 28147-89 cipher
*
* This is based on the 25 Movember 1993 draft translation
* by Aleksandr Malchik, with Whitfield Diffie, of the Government
* Standard of the U.S.S.R. GOST 28149-89, "Cryptographic Transformation
* Algorithm", effective 1 July 1990. (Whitfield.Diffie@eng.sun.com)
*
* That is a draft, and may contain errors, which will be faithfully
* reflected here, along with possible exciting new bugs.
*
* Some details have been cleared up by the paper "Soviet Encryption
* Algorithm" by Josef Pieprzyk and Leonid Tombak of the University
* of Wollongong, New South Wales. (josef/leo@cs.adfa.oz.au)
*
* The standard is written by A. Zabotin (project leader), G.P. Glazkov,
* and V.B. Isaeva. It was accepted and introduced into use by the
* action of the State Standards Committee of the USSR on 2 June 89 as
* No. 1409. It was to be reviewed in 1993, but whether anyone wishes
* to take on this obligation from the USSR is questionable.
*
* This code is placed in the public domain.
*/
/*
* If you read the standard, it belabors the point of copying corresponding
* bits from point A to point B quite a bit. It helps to understand that
* the standard is uniformly little-endian, although it numbers bits from
* 1 rather than 0, so bit n has value 2^(n-1). The least significant bit
* of the 32-bit words that are manipulated in the algorithm is the first,
* lowest-numbered, in the bit string.
*/
/* A 32-bit data type */
#ifdef __alpha /* Any other 64-bit machines? */
typedef unsigned int word32;
#else
typedef unsigned long word32;
#endif
/*
* The standard does not specify the contents of the 8 4 bit->4 bit
* substitution boxes, saying they're a parameter of the network
* being set up. For illustration purposes here, I have used
* the first rows of the 8 S-boxes from the DES. (Note that the
* DES S-boxes are numbered starting from 1 at the msb. In keeping
* with the rest of the GOST, I have used little-endian numbering.
* Thus, k8 is S-box 1.
*
* Obviously, a careful look at the cryptographic properties of the cipher
* must be undertaken before "production" substitution boxes are defined.
*
* The standard also does not specify a standard bit-string representation
* for the contents of these blocks.
*/
static unsigned char const k8[16] = {
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 };
static unsigned char const k7[16] = {
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 };
static unsigned char const k6[16] = {
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 };
static unsigned char const k5[16] = {
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 };
static unsigned char const k4[16] = {
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 };
static unsigned char const k3[16] = {
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 };
static unsigned char const k2[16] = {
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 };
static unsigned char const k1[16] = {
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 };
/* Byte-at-a-time substitution boxes */
static unsigned char k87[256];
static unsigned char k65[256];
static unsigned char k43[256];
static unsigned char k21[256];
/*
* Build byte-at-a-time subtitution tables.
* This must be called once for global setup.
*/
void
kboxinit(void)
{
int i;
for (i = 0; i < 256; i++) {
k87[i] = k8[i >> 4] << 4 | k7[i & 15];
k65[i] = k6[i >> 4] << 4 | k5[i & 15];
k43[i] = k4[i >> 4] << 4 | k3[i & 15];
k21[i] = k2[i >> 4] << 4 | k1[i & 15];
}
}
/*
* Do the substitution and rotation that are the core of the operation,
* like the expansion, substitution and permutation of the DES.
* It would be possible to perform DES-like optimisations and store
* the table entries as 32-bit words, already rotated, but the
* efficiency gain is questionable.
*
* This should be inlined for maximum speed
*/
#if __GNUC__
__inline__
#endif
static word32
f(word32 x)
{
/* Do substitutions */
#if 0
/* This is annoyingly slow */
x = k8[x>>28 & 15] << 28 | k7[x>>24 & 15] << 24 |
k6[x>>20 & 15] << 20 | k5[x>>16 & 15] << 16 |
k4[x>>12 & 15] << 12 | k3[x>> 8 & 15] << 8 |
k2[x>> 4 & 15] << 4 | k1[x & 15];
#else
/* This is faster */
x = k87[x>>24 & 255] << 24 | k65[x>>16 & 255] << 16 |
k43[x>> 8 & 255] << 8 | k21[x & 255];
#endif
/* Rotate left 11 bits */
return x<<11 | x>>(32-11);
}
/*
* The GOST standard defines the input in terms of bits 1..64, with
* bit 1 being the lsb of in[0] and bit 64 being the msb of in[1].
*
* The keys are defined similarly, with bit 256 being the msb of key[7].
*/
void
gostcrypt(word32 const in[2], word32 out[2], word32 const key[8])
{
register word32 n1, n2; /* As named in the GOST */
n1 = in[0];
n2 = in[1];
/* Instead of swapping halves, swap names each round */
n2 ^= f(n1+key[0]);
n1 ^= f(n2+key[1]);
n2 ^= f(n1+key[2]);
n1 ^= f(n2+key[3]);
n2 ^= f(n1+key[4]);
n1 ^= f(n2+key[5]);
n2 ^= f(n1+key[6]);
n1 ^= f(n2+key[7]);
n2 ^= f(n1+key[0]);
n1 ^= f(n2+key[1]);
n2 ^= f(n1+key[2]);
n1 ^= f(n2+key[3]);
n2 ^= f(n1+key[4]);
n1 ^= f(n2+key[5]);
n2 ^= f(n1+key[6]);
n1 ^= f(n2+key[7]);
n2 ^= f(n1+key[0]);
n1 ^= f(n2+key[1]);
n2 ^= f(n1+key[2]);
n1 ^= f(n2+key[3]);
n2 ^= f(n1+key[4]);
n1 ^= f(n2+key[5]);
n2 ^= f(n1+key[6]);
n1 ^= f(n2+key[7]);
n2 ^= f(n1+key[7]);
n1 ^= f(n2+key[6]);
n2 ^= f(n1+key[5]);
n1 ^= f(n2+key[4]);
n2 ^= f(n1+key[3]);
n1 ^= f(n2+key[2]);
n2 ^= f(n1+key[1]);
n1 ^= f(n2+key[0]);
/* There is no swap after the last round */
out[0] = n2;
out[1] = n1;
}
/*
* The key schedule is somewhat different for decryption.
* (The key table is used once forward and three times backward.)
* You could define an expanded key, or just write the code twice,
* as done here.
*/
void
gostdecrypt(word32 const in[2], word32 out[2], word32 const key[8])
{
register word32 n1, n2; /* As named in the GOST */
n1 = in[0];
n2 = in[1];
n2 ^= f(n1+key[0]);
n1 ^= f(n2+key[1]);
n2 ^= f(n1+key[2]);
n1 ^= f(n2+key[3]);
n2 ^= f(n1+key[4]);
n1 ^= f(n2+key[5]);
n2 ^= f(n1+key[6]);
n1 ^= f(n2+key[7]);
n2 ^= f(n1+key[7]);
n1 ^= f(n2+key[6]);
n2 ^= f(n1+key[5]);
n1 ^= f(n2+key[4]);
n2 ^= f(n1+key[3]);
n1 ^= f(n2+key[2]);
n2 ^= f(n1+key[1]);
n1 ^= f(n2+key[0]);
n2 ^= f(n1+key[7]);
n1 ^= f(n2+key[6]);
n2 ^= f(n1+key[5]);
n1 ^= f(n2+key[4]);
n2 ^= f(n1+key[3]);
n1 ^= f(n2+key[2]);
n2 ^= f(n1+key[1]);
n1 ^= f(n2+key[0]);
n2 ^= f(n1+key[7]);
n1 ^= f(n2+key[6]);
n2 ^= f(n1+key[5]);
n1 ^= f(n2+key[4]);
n2 ^= f(n1+key[3]);
n1 ^= f(n2+key[2]);
n2 ^= f(n1+key[1]);
n1 ^= f(n2+key[0]);
out[0] = n2;
out[1] = n1;
}
/*
* The GOST "Output feedback" standard. It seems closer morally
* to the counter feedback mode some people have proposed for DES.
* The avoidance of the short cycles that are possible in OFB seems
* like a Good Thing.
*
* Calling it the stream mode makes more sense.
*
* The IV is encrypted with the key to produce the initial counter value.
* Then, for each output block, a constant is added, modulo 2^32-1
* (0 is represented as all-ones, not all-zeros), to each half of
* the counter, and the counter is encrypted to produce the value
* to XOR with the output.
*
* Len is the number of blocks. Sub-block encryption is
* left as an exercise for the user. Remember that the
* standard defines everything in a little-endian manner,
* so you want to use the low bit of gamma[0] first.
*
* OFB is, of course, self-inverse, so there is only one function.
*/
/* The constants for addition */
#define C1 0x01010104
#define C2 0x01010101
void
gostofb(word32 const *in, word32 *out, int len,
word32 const iv[2], word32 const key[8])
{
word32 temp[2]; /* Counter */
word32 gamma[2]; /* Output XOR value */
/* Compute starting value for counter */
gostcrypt(iv, temp, key);
while (len--) {
temp[0] += C2;
if (temp[0] < C2) /* Wrap modulo 2^32? */
temp[0]++; /* Make it modulo 2^32-1 */
temp[1] += C1;
if (temp[1] < C1) /* Wrap modulo 2^32? */
temp[1]++; /* Make it modulo 2^32-1 */
gostcrypt(temp, gamma, key);
*out++ = *in++ ^ gamma[0];
*out++ = *in++ ^ gamma[1];
}
}
/*
* The CFB mode is just what you'd expect. Each block of ciphertext y[] is
* derived from the input x[] by the following pseudocode:
* y[i] = x[i] ^ gostcrypt(y[i-1])
* x[i] = y[i] ^ gostcrypt(y[i-1])
* Where y[-1] is the IV.
*
* The IV is modified in place. Again, len is in *blocks*.
*/
void
gostcfbencrypt(word32 const *in, word32 *out, int len,
word32 iv[ 2 ], word32 const key[ 8 ])
{
while (len--) {
gostcrypt(iv, iv, key);
iv[ 0 ] = *out++ ^= iv[ 0 ];
iv[ 1 ] = *out++ ^= iv[ 1 ];
}
}
void
gostcfbdecrypt(word32 const *in, word32 *out, int len,
word32 iv[ 2 ], word32 const key[ 8 ])
{
word32 t;
while (len--) {
gostcrypt(iv, iv, key);
t = *out;
*out++ ^= iv[ 0 ];
iv[ 0 ] = t;
t = *out;
*out++ ^= iv[ 1 ];
iv[ 1 ] = t;
}
}
/*
* The message suthetication code uses only 16 of the 32 rounds.
* There *is* a swap after the 16th round.
* The last block should be padded to 64 bits with zeros.
* len is the number of *blocks* in the input.
*/
void
gostmac(word32 const *in, int len, word32 out[ 2 ], word32 const key[ 8 ])
{
register word32 n1, n2; /* As named in the GOST */
n1 = 0 ;
n2 = 0 ;
while (len--) {
n1 ^= *in++;
n2 = *in++;
/* Instead of swapping halves, swap names each round */
n2 ^= f(n1+key[ 0 ]);
n1 ^= f(n2+key[ 1 ]);
n2 ^= f(n1+key[ 2 ]);
n1 ^= f(n2+key[ 3 ]);
n2 ^= f(n1+key[ 4 ]);
n1 ^= f(n2+key[ 5 ]);
n2 ^= f(n1+key[ 6 ]);
n1 ^= f(n2+key[ 7 ]);
n2 ^= f(n1+key[ 0 ]);
n1 ^= f(n2+key[ 1 ]);
n2 ^= f(n1+key[ 2 ]);
n1 ^= f(n2+key[ 3 ]);
n2 ^= f(n1+key[ 4 ]);
n1 ^= f(n2+key[ 5 ]);
n2 ^= f(n1+key[ 6 ]);
n1 ^= f(n2+key[ 7 ]);
}
out[ 0 ] = n1;
out[ 1 ] = n2;
}
#ifdef TEST
#include <stdio.h>
#include <stdlib.h>
/* Designed to cope with 15-bit rand() implementations */
#define RAND32 ((word32)rand() << 17 ^ (word32)rand() << 9 ^ rand())
int
main(void)
{
word32 key[ 8 ];
word32 plain[ 2 ];
word32 cipher[ 2 ];
int i, j;
kboxinit();
printf("GOST 21847-89 test driver.\n");
for (j = 0 ; j < 8 ; j++){
key[j] = RAND32;
plain[ 0 ] = RAND32;
plain[ 1 ] = RAND32;
printf("%3d\r", i);
fflush(stdout);
gostcrypt(plain, cipher, key);
for (j = 0 ; j < 99 ; j++)
gostcrypt(cipher, cipher, key);
for (j = 0 ; j < 100 ; j++)
gostdecrypt(cipher, cipher, key);
if (plain[ 0 ] != cipher[ 0 ] || plain[ 1 ] != cipher[ 1 ]) {
fprintf(stderr, "\nError! i = %d\n", i);
return 1 ;
}
}
printf("All tests passed.\n");
return 0 ;
}
#endif /* TEST */
и
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360.
// РЕЛІЗАЦІЯ АЛГОРИТМУ ШИФРУВАННЯ ДАНИХ ГОСТ 28147-89
// автор:
// Геннадій Панасенко
//
// сайт:
// www.getsoft.com.ua
//
// Пояснення
//
// m та s - молодша та старша частини блоку, що щифрується відповідно (об'явлені як глобальні змінні)
// Gm та Gs - шифргамми для молодшої та старшої частини блоку, що шифрується відповідно (об'явлені як глобальні змінні)
// password - пароль введений користувачем
// keymas[32] - набір ключів (int) (об'явлена як глобальна змінна)
// action - дія шифрування або розшифрування ("true" та "false" відповідно)
// data_block[2] - блок даних для передачи функції шифрування (об'явлена як глобальна змінна)
// ZamTab[1024] - перетворена таблиця замін (об'явлена як глобальна змінна)
// TObject *Sender - таблиця в розмірності 16 колонок на 8 строчок (1 колонка і 1 строчка фіксовані і використовуються
// для нумерації) обов'язково StringGrid
//
// Порядок роботи функції:
// 1. Після введеня пароля і заповнення або вказання файла таблиці замін генерація масиву ключів
// функцією "void GetKeyMas (AnsiString password, int keymas[32], bool action)", перетворення таблиці замін до
// більш зручного вигляду функцією "char ConvertZamTab (TObject *Sender, char ZamTab[])".
// 2. Для зашифрування - читання по 4 символи і перетворення їх в числа функцією "int EnCodeString (char value[])".
// 3. Для розшифрування - читання необхідної кількості символів в змінну "char" довжиною 4 байта (4 символи. Не заповнені
// позиції символів обнуляються) і перетворюються в строку функцією "AnsiString DeCodeString (int value)".
// 4. Безпосередньо шифрування функцією "int USE_GOST_28147 (int data_block[], int keymas[], char ZamTab[], bool action)".
char ZamTab [ 1024 ];
int data_block[ 2 ],
keymas[ 32 ],
Gm,
Gs,
m,
s,
key,
oper;
//=======================================================================================
// Функція переведення прочитаних даних в число
int EnCodeString (char value[]); // Розмірність value = 4
int EnCodeString (char value[])
{
int result;
char znak;
for (int i = 0 ; i < 4 ; i++)
{
znak = value[i];
asm
{
mov eax, result;
shl eax, 8 ;
mov al, znak;
mov result, eax;
}
}
return result;
}
// Кінець функції переведення прочитаних даних в число
//=======================================================================================
// Функція переведення числа в дані
AnsiString DeCodeString (int value);
AnsiString DeCodeString (int value)
{
char result[ 4 ], znak;
AnsiString res;
for (int i = 3 ; i >= 0 ; i--)
{
asm
{
mov eax, value;
mov znak, al;
shr eax, 8 ;
mov value, eax;
}
result[i] = znak;
}
result[ 4 ] = 0 ;
res = (AnsiString)result;
return res;
}
// Кінець функції переведення числа в дані
//=======================================================================================
// Функція генерації шифргами та накладання її на дані
void CryptWithGamma ();
void CryptWithGamma ()
{
int Gamma, block;
Gamma = Gs;
block = s;
asm
{
mov eax, Gamma;
mov ebx, block;
ror eax, 1 ;
jnc end1;
xor eax, 0x1010101;
end1:
xor ebx, eax;
mov block, ebx;
mov Gamma, eax;
}
Gs = Gamma;
s = block;
Gamma = Gm;
block = m;
asm
{
mov eax, Gamma;
mov ebx, block;
ror eax, 1 ;
jnc end2;
xor eax, 0x1010104;
end2:
xor ebx, eax;
mov block, ebx;
mov Gamma, eax;
}
Gm = Gamma;
m = block;
}
// Кінець функції генерації шифргами та накладання її на дані
//=======================================================================================
// Функція отримання масиву ключів
void GetKeyMas (AnsiString password, int keymas[ 32 ], bool action);
void GetKeyMas (AnsiString password, int keymas[ 32 ], bool action)
{
char keystr [ 32 ];
int keycode = password.Length();
strcpy (keystr, password.c_str());
// Перетворення набраного пароля в 32 знакову комбінацію
for (int i = 0 ; i < password.Length(); i++)
{
keycode = (keycode * int(keystr[i]))% 16777216 ;
}
for (int i = password.Length(); i < 32 ; i++)
{
keystr[i] = keycode * i + i;
}
if (action == true) // Якщо зашифрування
{
keymas[ 0 ] = int(keystr[ 0 ]) * int(keystr[ 1 ]) * int(keystr[ 2 ]) * int(keystr[ 3 ]);
keymas[ 1 ] = int(keystr[ 4 ]) * int(keystr[ 5 ]) * int(keystr[ 6 ]) * int(keystr[ 7 ]);
keymas[ 2 ] = int(keystr[ 8 ]) * int(keystr[ 9 ]) * int(keystr[ 10 ]) * int(keystr[ 11 ]);
keymas[ 3 ] = int(keystr[ 12 ]) * int(keystr[ 13 ]) * int(keystr[ 14 ]) * int(keystr[ 15 ]);
keymas[ 4 ] = int(keystr[ 16 ]) * int(keystr[ 17 ]) * int(keystr[ 18 ]) * int(keystr[ 19 ]);
keymas[ 5 ] = int(keystr[ 20 ]) * int(keystr[ 21 ]) * int(keystr[ 22 ]) * int(keystr[ 23 ]);
keymas[ 6 ] = int(keystr[ 24 ]) * int(keystr[ 25 ]) * int(keystr[ 26 ]) * int(keystr[ 27 ]);
keymas[ 7 ] = int(keystr[ 28 ]) * int(keystr[ 29 ]) * int(keystr[ 30 ]) * int(keystr[ 31 ]);
keymas[ 8 ] = keymas[ 0 ];
keymas[ 9 ] = keymas[ 1 ];
keymas[ 10 ] = keymas[ 2 ];
keymas[ 11 ] = keymas[ 3 ];
keymas[ 12 ] = keymas[ 4 ];
keymas[ 13 ] = keymas[ 5 ];
keymas[ 14 ] = keymas[ 6 ];
keymas[ 15 ] = keymas[ 7 ];
keymas[ 16 ] = keymas[ 0 ];
keymas[ 17 ] = keymas[ 1 ];
keymas[ 18 ] = keymas[ 2 ];
keymas[ 19 ] = keymas[ 3 ];
keymas[ 20 ] = keymas[ 4 ];
keymas[ 21 ] = keymas[ 5 ];
keymas[ 22 ] = keymas[ 6 ];
keymas[ 23 ] = keymas[ 7 ];
keymas[ 24 ] = keymas[ 7 ];
keymas[ 25 ] = keymas[ 6 ];
keymas[ 26 ] = keymas[ 5 ];
keymas[ 27 ] = keymas[ 4 ];
keymas[ 28 ] = keymas[ 3 ];
keymas[ 29 ] = keymas[ 2 ];
keymas[ 30 ] = keymas[ 1 ];
keymas[ 31 ] = keymas[ 0 ];
}
if (action == false) // Якщо розшифрування
{
keymas[ 0 ] = int(keystr[ 0 ]) * int(keystr[ 1 ]) * int(keystr[ 2 ]) * int(keystr[ 3 ]);
keymas[ 1 ] = int(keystr[ 4 ]) * int(keystr[ 5 ]) * int(keystr[ 6 ]) * int(keystr[ 7 ]);
keymas[ 2 ] = int(keystr[ 8 ]) * int(keystr[ 9 ]) * int(keystr[ 10 ]) * int(keystr[ 11 ]);
keymas[ 3 ] = int(keystr[ 12 ]) * int(keystr[ 13 ]) * int(keystr[ 14 ]) * int(keystr[ 15 ]);
keymas[ 4 ] = int(keystr[ 16 ]) * int(keystr[ 17 ]) * int(keystr[ 18 ]) * int(keystr[ 19 ]);
keymas[ 5 ] = int(keystr[ 20 ]) * int(keystr[ 21 ]) * int(keystr[ 22 ]) * int(keystr[ 23 ]);
keymas[ 6 ] = int(keystr[ 24 ]) * int(keystr[ 25 ]) * int(keystr[ 26 ]) * int(keystr[ 27 ]);
keymas[ 7 ] = int(keystr[ 28 ]) * int(keystr[ 29 ]) * int(keystr[ 30 ]) * int(keystr[ 31 ]);
keymas[ 8 ] = keymas[ 7 ];
keymas[ 9 ] = keymas[ 6 ];
keymas[ 10 ] = keymas[ 5 ];
keymas[ 11 ] = keymas[ 4 ];
keymas[ 12 ] = keymas[ 3 ];
keymas[ 13 ] = keymas[ 2 ];
keymas[ 14 ] = keymas[ 1 ];
keymas[ 15 ] = keymas[ 0 ];
keymas[ 16 ] = keymas[ 7 ];
keymas[ 17 ] = keymas[ 6 ];
keymas[ 18 ] = keymas[ 5 ];
keymas[ 19 ] = keymas[ 4 ];
keymas[ 20 ] = keymas[ 3 ];
keymas[ 21 ] = keymas[ 2 ];
keymas[ 22 ] = keymas[ 1 ];
keymas[ 23 ] = keymas[ 0 ];
keymas[ 24 ] = keymas[ 7 ];
keymas[ 25 ] = keymas[ 6 ];
keymas[ 26 ] = keymas[ 5 ];
keymas[ 27 ] = keymas[ 4 ];
keymas[ 28 ] = keymas[ 3 ];
keymas[ 29 ] = keymas[ 2 ];
keymas[ 30 ] = keymas[ 1 ];
keymas[ 31 ] = keymas[ 0 ];
}
}
// Кінець функції отримання масиву ключів
//=======================================================================================
// Функція перетворення по ГОСТ
int USE_GOST_28147 (int data_block[], int keymas[], char ZamTab[], bool action);
int USE_GOST_28147 (int data_block[], int keymas[], char ZamTab[], bool action)
{
char tmp;
int ITEMP;
m = data_block[ 0 ];
s = data_block[ 1 ];
if (action == true) // Якщо зашифрування
{
CryptWithGamma ();
}
for (int i = 0 ; i < 32 ; i++)
{
int key = keymas[i];
// Складання по модулю з ключем
asm
{
mov eax, m;
mov ecx, key;
add eax, ecx;
mov oper, eax;
}
// Таблиця замін
for (int i = 0 ; i < 4 ; i++)
{
asm
{
mov eax, oper;
mov tmp, al;
}
ITEMP = tmp*i;
tmp = ZamTab [ITEMP];
asm
{
mov eax, oper;
xchg al, tmp;
ror eax, 8 ;
mov oper, eax;
}
}
// Циклічний зсув на 11 біт ліворуч
asm
{
mov eax, oper;
rol eax, 11 ;
// Побітове додавання отриманого значення і старшої половини блока
mov ebx, s;
xor eax, ebx;
mov oper, eax;
}
if (i < 31 )
{
s = m;
m = oper;
}
else
{
s = oper;
}
}
if (action == false) // Якщо розшифрування
{
CryptWithGamma ();
}
data_block[ 0 ] = m;
data_block[ 1 ] = s;
return *data_block;
}
// Кінець функції перетворення по ГОСТ
//=======================================================================================
// Функція перетворення таблиці замін в 8 бітний блок
char ConvertZamTab (TObject *Sender, char ZamTab[]);
char ConvertZamTab (TObject *Sender, char ZamTab[])
{
int count = 0 ;
TStringGrid *SG = dynamic_cast<TStringGrid*>(Sender);
for (int i = 1 ; i <= SG->RowCount - 2 ; )
{
for (int j = 1 ; j <= 16 ; j++)
{
for (int k = 1 ; k <= 16 ; k++)
{
ZamTab[count] = StrToInt(SG->Cells[j][i]) * StrToInt(SG->Cells[k][i + 1 ]);
count++;
}
}
i = i + 2 ;
}
return *ZamTab;
}
// Кінець функції перетворення таблиці замін в 8 бітний блок
//=======================================================================================
Бедные те кто на трафике, мне вас жалко :))
Я немогу не с одним разобраться как использовать..
В первом какие-то непонятно зачем циклы
for (j = 0; j < 89; j++) gostcrypt(cipher, cipher, key);
for (j = 0; j < 90; j++) gostdecrypt(cipher, cipher, key);
Непонятно почему ключ key [8] , разве длинна больше быть неможет?
Непонятно почему cipher [2] разве больше быть неможет? :)
Во втором непонятно как инициализировать таблицу подстаноки. Также непонятно как вызывать..
Вообщем я очень прошу знающих, напишите плз для любого из этих алгоритмов какую-то обёртку вроде
char* Crypt (char* key, char* source)
и расшифрование агалогично. Одним словом - по проще как-то :) Уверен там несколько строчек кода...
P.S. Плз, не отправляйте в поиск и ботать гост, я только что оттуда.. пока нашел эти сырсы довольно много пришлось про гост этот перечитать :)
|