/*--------------------------------------------------------------------------------------------------- Implementacja kryptograficznie bezpiecznego generatora liczb pseudolosowych VMPC-R w języku C Autor algorytmu: Bartosz Żółtak Autor implementacji: Bartosz Żółtak www.szyfrowanie.com ----------------------------------------------------------------------------------------------------- ----------------------- Wykorzystanie algorytmu: ---------------------------------------------------- ----------------------------------------------------------------------------------------------------- unsigned char Klucz[256], Wektor[256]; Wiadomosc[1000]; Generowanie strumienia liczb pseudolosowych / szyfrowanie: VMPCRInitKey(Klucz, Wektor, 32, 32); VMPCREncrypt(Wiadomosc, 1000); Deszyfrowanie: VMPCRInitKey(Klucz, Wektor, 16, 16); VMPCREncrypt(Wiadomosc, 1000); (funkcja VMPCREncrypt służy do generowania liczb pseudolosowych, szyfrowania i deszyfrowania). Znakiem /**/ zaznaczono miejsce w kodzie, które decyduje, czy algorytm działa w trybie generowania liczb pseudolosowych czy w trybie szyfrowania/deszyfrowania ---------------------------------------------------------------------------------------------------- UWAGA! Do każdego szyfrowania z tym samym kluczem ("Klucz") należy użyć INNEJ wartości wektora inicjującego "Wektor". Szyfrowanie dwóch wiadomości TYM SAMYM kluczem i TYM SAMYM wektorem inicjującym drastycznie obniża poziom bezpieczeństwa! Klucz jest wartością tajną. Wektor inicjujący jest wartością jawną - można go przekazać jawnie wraz z zaszyfrowaną wiadomością. ----------------------------------------------------------------------------------------------------*/ //--------------------------------------------------------------------------------------------------- //----------------------------------------- IMPLEMENTACJA: ------------------------------------------ //--------------------------------------------------------------------------------------------------- //--- Typ danych "int" oznacza zmienną 32-bitową //----------- Zmienne algorytmu VMPC-R: ----------- unsigned char P[256], S[256]; unsigned char a, b, c, d, e, f, n; //----------------- Dane testowe: ----------------- unsigned char TestOutPSInd[8] = {0, 1, 2, 3, 252, 253, 254, 255}; unsigned int TestOutInd[16] = {0, 1, 2, 3, 254, 255, 256, 257,1000,1001,10000,10001,100000,100001,1000000,1000001}; unsigned char TestKey[9] = {11,22,33,144,155,166,233,244,255}; unsigned char TestVector[8] = {255,250,200,150,100,50,5,1}; unsigned char TestKey32[32] = {104, 9, 46, 231, 132, 149, 234, 147, 224, 97, 230, 127, 124, 109, 34, 171, 88, 185, 158, 23, 116, 69, 90, 195, 208, 17, 86, 175, 108, 29, 146, 219}; //RND=123; repeat 32 times:{RND=RND*134775813+1; output=(RND & 255)} unsigned char TestVector32[32] = {149, 234, 147, 224, 97, 230, 127, 124, 109, 34, 171, 88, 185, 158, 23, 116, 69, 90, 195, 208, 17, 86, 175, 108, 29, 146, 219, 72, 105, 14, 71, 100}; //RND=132; repeat 32 times:{RND=RND*134775813+1; output=(RND & 255)} unsigned char TestKey256[256] = {147, 224, 97, 230, 127, 124, 109, 34, 171, 88, 185, 158, 23, 116, 69, 90, 195, 208, 17, 86, 175, 108, 29, 146, 219, 72, 105, 14, 71, 100, 245, 202, 243, 192, 193, 198, 223, 92, 205, 2, 11, 56, 25, 126, 119, 84, 165, 58, 35, 176, 113, 54, 15, 76, 125, 114, 59, 40, 201, 238, 167, 68, 85, 170, 83, 160, 33, 166, 63, 60, 45, 226, 107, 24, 121, 94, 215, 52, 5, 26, 131, 144, 209, 22, 111, 44, 221, 82, 155, 8, 41, 206, 7, 36, 181, 138, 179, 128, 129, 134, 159, 28, 141, 194, 203, 248, 217, 62, 55, 20, 101, 250, 227, 112, 49, 246, 207, 12, 61, 50, 251, 232, 137, 174, 103, 4, 21, 106, 19, 96, 225, 102, 255, 252, 237, 162, 43, 216, 57, 30, 151, 244, 197, 218, 67, 80, 145, 214, 47, 236, 157, 18, 91, 200, 233, 142, 199, 228, 117, 74, 115, 64, 65, 70, 95, 220, 77, 130, 139, 184, 153, 254, 247, 212, 37, 186, 163, 48, 241, 182, 143, 204, 253, 242, 187, 168, 73, 110, 39, 196, 213, 42, 211, 32, 161, 38, 191, 188, 173, 98, 235, 152, 249, 222, 87, 180, 133, 154, 3, 16, 81, 150, 239, 172, 93, 210, 27, 136, 169, 78, 135, 164, 53, 10, 51, 0, 1, 6, 31, 156, 13, 66, 75, 120, 89, 190, 183, 148, 229, 122, 99, 240, 177, 118, 79, 140, 189, 178, 123, 104, 9, 46, 231, 132, 149, 234}; //RND=234; repeat 256 times:{RND=RND*134775813+1; output=(RND & 255)} unsigned char TestOutP[8] = {97,218,106,125,139,86,36,126}; unsigned char TestOutS[8] = {152,143,19,154,92,25,24,157}; unsigned char TestOut[16] = {49,161,79,69,85,237,96,243,181,184,136,99,67,27,253,231}; //VMPCRInitKey(TestKey, TestVector, 9, 8); //P[TestOutPSInd[x]]==TestOutP[x]; x=0,1,...,7 //S[TestOutPSInd[x]]==TestOutS[x]; x=0,1,...,7 //VMPCREncrypt(Table, 1000002); //Table[TestOutInd[x]]==TestOut[x]; x=0,1,...,15 unsigned char TestOutP32[8] = {76, 44, 167, 7, 250, 147, 240, 51}; unsigned char TestOutS32[8] = {239, 59, 110, 207, 98, 23, 178, 227}; unsigned char TestOut32[16] = {219, 178, 157, 119, 2, 155, 62, 20, 3, 239, 236, 81, 195, 11, 186, 127}; //VMPCRInitKey(TestKey32, TestVector32, 32, 32); LUB VMPCRInitKey32(TestKey32, TestVector32); //P[TestOutPSInd[x]]==TestOutP32[x]; x=0,1,...,7 //S[TestOutPSInd[x]]==TestOutS32[x]; x=0,1,...,7 //VMPCREncrypt(Table, 1000002); //Table[TestOutInd[x]]==TestOut32[x]; x=0,1,...,15 unsigned char TestOutP256[8] = {10, 34, 13, 239, 209, 9, 154, 220}; unsigned char TestOutS256[8] = {253, 106, 200, 178, 75, 251, 129, 209}; unsigned char TestOut256[16] = {201, 85, 155, 17, 187, 48, 55, 198, 110, 179, 189, 210, 4, 15, 253, 83}; //VMPCRInitKey(TestKey256, TestVector, 256, 8); //P[TestOutPSInd[x]]==TestOutP256[x]; x=0,1,...,7 //S[TestOutPSInd[x]]==TestOutS256[x]; x=0,1,...,7 //VMPCREncrypt(Table, 1000002); //Table[TestOutInd[x]]==TestOut256[x]; x=0,1,...,15 //------------------------------------------------------------------------------------------------------------- unsigned char Permut123[256]= //Permut123[x]=x {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,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}; unsigned char InitKeyRounds[256]= //InitKeyRounds[x]=Ceiling((x+1)*(x+1) / (6*256)) {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43}; //------------------------------------------------------------------------------------------------------------- void VMPCRInitKeyRound(unsigned char Data[], int Len) //Data: klucz lub wektor inicjujacy //Len=1,2,3,...,256: dlugosc klucza/wektora inicjujacego (w bajtach) { unsigned char i, t; i=0; for (int r=1; r<=InitKeyRounds[Len-1]; r++) { //InitKeyRounds[Len-1] = Ceiling(Len*Len / (6*256)) for (int x=0; x<256; x++) { //x w tej petli przyjmie te same wartosci, co n w specyfikacji algorytmu a=(P[ (a + f + Data[i]) & 255 ] + i) & 255; i++; if (i==Len) i=0; b=(S[ (b + a + Data[i]) & 255 ] + i) & 255; i++; if (i==Len) i=0; c=(P[ (c + b + Data[i]) & 255 ] + i) & 255; i++; if (i==Len) i=0; d=(S[ (d + c + Data[i]) & 255 ] + i) & 255; i++; if (i==Len) i=0; e=(P[ (e + d + Data[i]) & 255 ] + i) & 255; i++; if (i==Len) i=0; f=(S[ (f + e + Data[i]) & 255 ] + i) & 255; i++; if (i==Len) i=0; t=P[x]; P[x]=P[b]; P[b]=t; t=S[x]; S[x]=S[e]; S[e]=t; t=P[d]; P[d]=P[f]; P[f]=t; t=S[a]; S[a]=S[c]; S[c]=t; } } } void VMPCRInitKeyRound32(unsigned char Data[]) //Dla kluczy i wektorow o rozmiarze 32 bajtow (256 bitow) //Data: klucz lub wektor inicjujacy { unsigned char i, t; i=0; for (int r=1; r<=InitKeyRounds[31]; r++) { //InitKeyRounds[31] = Ceiling(32*32 / (6*256)) for (int x=0; x<256; x++) { //w tej petli x przyjmie te same wartosci, co n w specyfikacji algorytmu a=(P[ (a + f + Data[i]) & 255 ] + i) & 255; i=++i & 31; b=(S[ (b + a + Data[i]) & 255 ] + i) & 255; i=++i & 31; c=(P[ (c + b + Data[i]) & 255 ] + i) & 255; i=++i & 31; d=(S[ (d + c + Data[i]) & 255 ] + i) & 255; i=++i & 31; e=(P[ (e + d + Data[i]) & 255 ] + i) & 255; i=++i & 31; f=(S[ (f + e + Data[i]) & 255 ] + i) & 255; i=++i & 31; t=P[x]; P[x]=P[b]; P[b]=t; t=S[x]; S[x]=S[e]; S[e]=t; t=P[d]; P[d]=P[f]; P[f]=t; t=S[a]; S[a]=S[c]; S[c]=t; } } } void VMPCRInitKeyFinalize() { unsigned char t; for (unsigned int x=0; x<256; x++) { a=P[ (a + c + S[n]) & 255 ]; b=P[ (b + a) & 255 ]; c=P[ (c + b) & 255 ]; d=S[ (d + f + P[n]) & 255 ]; e=S[ (e + d) & 255 ]; f=S[ (f + e) & 255 ]; t=P[n]; P[n]=P[f]; P[f]=t; t=S[n]; S[n]=S[a]; S[a]=t; n++; } } void VMPCRInitKey(unsigned char Key[], unsigned char Vec[], int KeyLen, int VecLen) //LeyLen, VecLen={1,2,3,...,256} { memcpy(P, Permut123, 256); memcpy(S, Permut123, 256); a=0; b=0; c=0; d=0; e=0; f=0; n=0; VMPCRInitKeyRound(Key, KeyLen); VMPCRInitKeyRound(Vec, VecLen); VMPCRInitKeyRound(Key, KeyLen); n=S[(S[S[ (c + d) & 255 ]]+1) & 255]; VMPCRInitKeyFinalize(); } void VMPCRInitKey32(unsigned char Key[], unsigned char Vec[]) //zoptymalizowane dla szybkosci dla 32-bajtowych kluczy i wektorow { memcpy(P, Permut123, 256); memcpy(S, Permut123, 256); a=0; b=0; c=0; d=0; e=0; f=0; n=0; VMPCRInitKeyRound32(Key); VMPCRInitKeyRound32(Vec); VMPCRInitKeyRound32(Key); n=S[(S[S[ (c + d) & 255 ]]+1) & 255]; VMPCRInitKeyFinalize(); } void VMPCREncrypt(unsigned char Data[], unsigned int Len) { unsigned char t; for (unsigned int x=0; x