| 0. 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. | // Solitaire Cipher algorithm: Bruce Schneier -> http://schneier.com/solitaire.html //
// Implementation by: B-Con (Brad Conte) //
//////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#define CARDS 54
#define JOKER_A 53
#define JOKER_B 54
char find_move_joker(char deck[], char joker) {
char idx=0,temp,joker_index,new_index;
while (deck[idx] != joker)
joker_index = ++idx;
temp = deck[joker_index];
new_index = (joker_index + 1) % CARDS;
if (!new_index)
new_index++;
deck[joker_index] = deck[new_index];
deck[new_index] = temp;
return(new_index);
}
void three_way_split(char deck[], char hi, char low) {
char temp[CARDS];
memcpy(temp,&deck[low+1],CARDS-1-low);
memcpy(&temp[CARDS-1-low],&deck[hi],low-hi+1);
memcpy(&temp[CARDS-1-hi+1],deck,hi);
memcpy(deck,temp,CARDS);
}
void count_cut(char deck[], char count) {
char temp[CARDS];
deck[count] == JOKER_B ? (count = JOKER_A) : (count = deck[CARDS-1]);
memcpy(temp,&deck[count],CARDS-1-count);
memcpy(&temp[CARDS-1-count],deck,count);
memcpy(deck,temp,CARDS-1);
}
void init_deck(char deck[], char key[]) {
unsigned char idx,joker_a,joker_b,len=strlen(key);
for (idx=0; idx < len; idx++)
key[idx] >= 'a' && key[idx] <= 'z' ? (key[idx] -= 'a' - 26 - 1) : (key[idx] -= 'A' - 1);
for (idx=0; idx < CARDS; idx++)
deck[idx] = idx + 1;
for (idx=0; idx < len; idx++) {
joker_a = find_move_joker(deck,JOKER_A);
joker_b = find_move_joker(deck,JOKER_B);
joker_b = find_move_joker(deck,JOKER_B);
joker_a < joker_b ? three_way_split(deck,joker_a,joker_b) : three_way_split(deck,joker_b,joker_a);
count_cut(deck,deck[CARDS-1]);
count_cut(deck,key[idx]);
}
}
void gen_keystream(char deck[], char keystream[], int len) {
char temp[CARDS],joker_a,joker_b,new_key;
int idx;
for (idx=0; idx < len; idx++) {
joker_a = find_move_joker(deck,JOKER_A);
joker_b = find_move_joker(deck,JOKER_B);
joker_b = find_move_joker(deck,JOKER_B);
joker_a < joker_b ? three_way_split(deck,joker_a,joker_b) : three_way_split(deck,joker_b,joker_a);
count_cut(deck,deck[CARDS-1]);
new_key = deck[deck[0]];
if (new_key == JOKER_A || new_key == JOKER_B)
idx--;
else
(new_key > 26) ? (keystream[idx] = new_key + ('a' - 26 - 1)) : (keystream[idx] = new_key + ('A' - 1));
}
}
int main() {
char deck[CARDS],deck_init_key[256],key_len[8],keystream[2048]={0};
printf("Key: ");
gets(deck_init_key);
init_deck(deck,deck_init_key);
printf("Length of keystream: ");
gets(key_len);
gen_keystream(deck,keystream,atoi(key_len));
printf("Keystream: ");
puts(keystream);
getchar();
return 0;
} |