(*--------------------------------------------------------------------------------------------------- Implementacja szyfru strumieniowego VMPC oraz schematu uwierzytelnionego szyfrowania VMPC-MAC w języku ASSEMBLER osadzona w środowisku Pascal/Delphi wykorzystująca konwencję wywoływania procedur "register" (calling convention = "register") Autor algorytmów: Bartosz Żółtak Autor implementacji: Bartosz Żółtak www.szyfrowanie.com ----------------------------------------------------------------------------------------------------- ----------------------- Wykorzystanie algorytmów: --------------------------------------------------- ----------------------------------------------------------------------------------------------------- var Klucz, Wektor : array[0..63] of byte; Wiadomosc : array[0..999] of byte; WiadomoscMAC : array[0..19] of byte; Szyfrowanie: VMPCInitKey_ASM(Klucz, Wektor, 16, 16); VMPCEncrypt_ASM(Wiadomosc, 1000); Deszyfrowanie: VMPCInitKey_ASM(Klucz, Wektor, 16, 16); VMPCEncrypt_ASM(Wiadomosc, 1000); (procedura VMPCEncrypt_ASM służy do szyfrowania i deszyfrowania). Szyfrowanie z uwierzytelnianiem (z kodem MAC): VMPCInitKey_ASM(Klucz, Wektor, 16, 16); VMPCInitMAC_ASM; VMPCEncryptMAC_ASM(Wiadomosc, 1000); VMPCOutputMAC_ASM; //Kod MAC umieszczony zostaje w 20-bajtowej tablicy "MAC" Move(MAC, WiadomoscMAC, 20); //Zapamietaj wygenerowany MAC w tablicy "WiadomoscMAC" Deszyfrowanie i weryfikacja kodu MAC: VMPCInitKey_ASM(Klucz, Wektor, 16, 16); VMPCInitMAC_ASM; VMPCDecryptMAC_ASM(Wiadomosc, 1000); VMPCOutputMAC_ASM; //Kod MAC umieszczony zostaje w 20-bajtowej tablicy "MAC" Jeśli 20-bajtowe tablice "MAC" i "WiadomoscMAC" są identyczne, wiadomość została poprawnie odszyfrowana - użyty został właściwy klucz i wiadomość nie została zmieniona. ---------------------------------------------------------------------------------------------------- Procedury VMPCInitKey_ASM / VMPCInitKey16_ASM (wykorzystujące algorytm inicjowania klucza VMPC-KSA3) zapewniają wyższy poziom bezpieczeństwa, ale o około 1/3 niższą wydajność niż podstawowe procedury VMPCInitKeyBASIC_ASM / VMPCInitKey16BASIC_ASM. Jeśli tylko wydajność systemu pozwala, autor zaleca stosować procedury VMPCInitKey_ASM / VMPCInitKey16_ASM. Jednocześnie procedury VMPCInitKeyBASIC_ASM / VMPCInitKey16BASIC_ASM także pozostają bezpieczne. ---------------------------------------------------------------------------------------------------- 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 "byte" oznacza zmienną 8-bitową bez znaku //--- Typ danych "word" oznacza zmienną 16-bitową bez znaku //--- Typ danych "longword" oznacza zmienną 32-bitową bez znaku //----------- Zmienne szyfru VMPC: ----------- var P : array[0..255] of byte; s, n : byte; //----------- Zmienne schematu uwierzytelnionego szyfrowania VMPC-MAC: ----------- MAC : array[0..31] of byte; m1, m2, m3, m4, mn : byte; //----------------- Dane testowe: ----------------- TestKey : array[0..15] of byte = ($96, $61, $41, $0A, $B7, $97, $D8, $A9, $EB, $76, $7C, $21, $17, $2D, $F6, $C7); TestVector : array[0..15] of byte = ($4B, $5C, $2F, $00, $3E, $67, $F3, $95, $57, $A8, $D2, $6F, $3D, $A2, $B1, $55); TestOutPInd : array[0..7] of byte = (0, 1, 2, 3, 252, 253, 254, 255); TestOutInd : array[0..15] of longword = (0,1,2,3,252,253,254,255,1020,1021,1022,1023,102396,102397,102398,102399); TestOutPBASIC : array[0..7] of byte = ($3F, $A5, $22, $67, $75, $B3, $D2, $C3); TestOutBASIC : array[0..15] of byte = ($A8, $24, $79, $F5, $B8, $FC, $66, $A4, $E0, $56, $40, $A5, $81, $CA, $49, $9A); //VMPCInitKeyBASIC_ASM(TestKey, TestVector, 16, 16); //P[TestOutPInd[x]]=TestOutPBASIC[x]; x=0,1,...,7 //Table[x]=0; x=0,1,...,102399 //VMPCEncrypt_ASM(Table, 102400); LUB VMPCEncryptMAC_ASM(Table, 102400); //Table[TestOutInd[x]]=TestOutBASIC[x]; x=0,1,...,15 TestOutP : array[0..7] of byte = ($1F, $00, $E2, $03, $5C, $EE, $C2, $2B); TestOut : array[0..15] of byte = ($B6, $EB, $AE, $FE, $48, $17, $24, $73, $1D, $AE, $C3, $5A, $1D, $A7, $E1, $DC); //VMPCInitKey_ASM(TestKey, TestVector, 16, 16); //P[TestOutPInd[x]]=TestOutP[x]; x=0,1,...,7 //Table[x]=0; x=0,1,...,102399 //VMPCEncrypt_ASM(Table, 102400); LUB VMPCEncryptMAC_ASM(Table, 102400); //Table[TestOutInd[x]]=TestOut[x]; x=0,1,...,15 TestOutMACBASIC : array[0..19] of byte = ($9B, $DA, $16, $E2, $AD, $0E, $28, $47, $74, $A3, $AC, $BC, $88, $35, $A8, $32, $6C, $11, $FA, $AD); //Table[x]=x; x=0,1,2,...,254,255 //VMPCInitKeyBASIC_ASM(TestKey, TestVector, 16, 16); //VMPCInitMAC_ASM; //VMPCEncryptMAC_ASM(Table, 256); //VMPCOutputMAC_ASM; //MAC[x]=TestOutMACBASIC[x]; x=0,1,...,19 TestOutMAC : array[0..19] of byte = ($A2, $B6, $0D, $B7, $B3, $90, $1D, $5C, $99, $61, $7C, $E2, $A3, $95, $02, $81, $75, $3A, $0C, $98); //Table[x]=x and 255; x=0,1,2,...,999998,999999; (Table[0]=0; Table[1]=1; ...; Table[999998]=62; Table[999999]=63) //VMPCInitKey_ASM(TestKey, TestVector, 16, 16); //VMPCInitMAC_ASM; //VMPCEncryptMAC_ASM(Table, 1000000); //VMPCOutputMAC_ASM; //MAC[x]=TestOutMAC[x]; x=0,1,...,19 //----------------------------------------------------------------------------------------------------------- const Permut123 : array[0..255] of byte = //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); //----------------------------------------------------------------------------------------------------------- procedure VMPCInitKeyRound_ASM(var Data; Len, Src:longword); //[Data]=eax; Len=edx; Src=ecx //Procedura dziala tylko dla Len=2,4,8,16,32,64 asm push edi push esi push ebp push ebx mov ebp, eax cmp ecx, 0 jnz @Start mov esi, offset Permut123 mov edi, offset P mov ecx, 64 cld rep movsd mov s, 0 @Start: mov eax, 768 //ah=3, al=0 mov al, s dec edx xor ebx, ebx @Step: mov esi, 0 @Loop: mov ebx, esi and ebx, edx //tozsame z "ebx modulo Len" dla Len=2^X mov bl, [ebp+ebx] add bl, byte ptr [P+esi] add bl, al mov al, byte ptr [P+ebx] mov bl, al mov ch, byte ptr [P+ebx] mov cl, byte ptr [P+esi] mov byte ptr [P+ebx], cl mov byte ptr [P+esi], ch inc esi cmp esi, 256 jb @Loop dec ah jnz @Step mov s, al mov n, 0 pop ebx pop ebp pop esi pop edi end; procedure VMPCInitKey_ASM(var Key, Vec:array of byte; KeyLen, VecLen:byte); //KeyLen, VecLen = 2,4,8,16,32,64 begin VMPCInitKeyRound_ASM(Key, KeyLen, 0); VMPCInitKeyRound_ASM(Vec, VecLen, 1); VMPCInitKeyRound_ASM(Key, KeyLen, 1); end; procedure VMPCInitKeyBASIC_ASM(var Key, Vec:array of byte; KeyLen, VecLen:byte); //KeyLen, VecLen = 2,4,8,16,32,64 begin VMPCInitKeyRound_ASM(Key, KeyLen, 0); VMPCInitKeyRound_ASM(Vec, VecLen, 1); end; procedure VMPCInitMAC_ASM; asm push edi xor eax, eax mov edi, offset MAC mov ecx, 8 cld rep stosd mov m1, 0 mov m2, 0 mov m3, 0 mov m4, 0 mov mn, 0 pop edi end; procedure VMPCEncrypt_ASM(var Data; Len :longword); //[Data]=eax; Len=edx asm cmp edx, 0 jz @Koniec; push edi push esi push ebp push ebx mov edi, eax mov ebp, edx add ebp, edi xor eax, eax xor ebx, ebx mov al, s mov bl, n mov esi, ebx @Loop: add al, byte ptr [P+esi] mov al, byte ptr [P+eax] mov bl, byte ptr [P+eax] mov bl, byte ptr [P+ebx] add bl, 1 mov bl, byte ptr [P+ebx] xor byte ptr [edi], bl mov bl, byte ptr [P+eax] mov cl, byte ptr [P+esi] mov byte ptr [P+eax], cl mov byte ptr [P+esi], bl inc esi and esi, 255 inc edi cmp edi, ebp jb @Loop mov s, al mov ebx, esi mov n, bl pop ebx pop ebp pop esi pop edi @Koniec: end; procedure VMPCEncryptMAC_ASM(var Data; Len :longword); //[Data]=eax; Len=edx asm cmp edx, 0 jz @Koniec; push edi push esi push ebp push ebx mov edi, eax mov ebp, edx add ebp, edi xor eax, eax xor ebx, ebx mov al, s mov bl, n mov esi, ebx mov cl, m1 mov ch, m2 mov dl, m3 mov dh, m4 @Loop: add al, byte ptr [P+esi] mov al, byte ptr [P+eax] mov bl, byte ptr [P+eax] mov bl, byte ptr [P+ebx] add bl, 1 mov ah, byte ptr [P+ebx] xor ah, byte ptr [edi] mov byte ptr [edi], ah mov bl, dh add bl, dl mov dh, byte ptr [P+ebx] mov bl, dl add bl, ch mov dl, byte ptr [P+ebx] mov bl, ch add bl, cl mov ch, byte ptr [P+ebx] mov bl, al add bl, ah add bl, cl mov cl, byte ptr [P+ebx] xor ah, ah mov ebx, esi and ebx, 7 xor word ptr[MAC+ebx*4], cx xor word ptr[MAC+ebx*4+2], dx mov bl, byte ptr [P+eax] mov bh, byte ptr [P+esi] mov byte ptr [P+eax], bh mov byte ptr [P+esi], bl xor ebx, ebx inc esi and esi, 255 inc edi cmp edi, ebp jb @Loop mov s, al mov ebx, esi mov n, bl mov m1, cl mov m2, ch mov m3, dl mov m4, dh pop ebx pop ebp pop esi pop edi @Koniec: end; procedure VMPCDecryptMAC_ASM(var Data; Len :longword); //[Data]=eax; Len=edx asm cmp edx, 0 jz @Koniec; push edi push esi push ebp push ebx mov edi, eax mov ebp, edx add ebp, edi xor eax, eax xor ebx, ebx mov al, s mov bl, n mov esi, ebx mov cl, m1 mov ch, m2 mov dl, m3 mov dh, m4 @Loop: add al, byte ptr [P+esi] mov al, byte ptr [P+eax] mov bl, byte ptr [P+eax] mov bl, byte ptr [P+ebx] add bl, 1 mov bl, byte ptr [P+ebx] mov ah, byte ptr [edi] xor bl, ah mov byte ptr [edi], bl mov bl, dh add bl, dl mov dh, byte ptr [P+ebx] mov bl, dl add bl, ch mov dl, byte ptr [P+ebx] mov bl, ch add bl, cl mov ch, byte ptr [P+ebx] mov bl, al add bl, ah add bl, cl mov cl, byte ptr [P+ebx] xor ah, ah mov ebx, esi and ebx, 7 xor word ptr[MAC+ebx*4], cx xor word ptr[MAC+ebx*4+2], dx mov bl, byte ptr [P+eax] mov bh, byte ptr [P+esi] mov byte ptr [P+eax], bh mov byte ptr [P+esi], bl xor ebx, ebx inc esi and esi, 255 inc edi cmp edi, ebp jb @Loop mov s, al mov ebx, esi mov n, bl mov m1, cl mov m2, ch mov m3, dl mov m4, dh pop ebx pop ebp pop esi pop edi @Koniec: end; procedure VMPCOutputMAC_ASM_internal; asm push edi push esi push ebx mov edi, 1 xor eax, eax xor ebx, ebx mov al, s mov bl, n mov esi, ebx mov cl, m1 mov ch, m2 mov dl, m3 mov dh, m4 @Loop: add al, byte ptr [P+esi] mov al, byte ptr [P+eax] mov bl, dh add bl, dl add ebx, edi and ebx, 255 mov dh, byte ptr [P+ebx] mov bl, dl add bl, ch add ebx, edi and ebx, 255 mov dl, byte ptr [P+ebx] mov bl, ch add bl, cl add ebx, edi and ebx, 255 mov ch, byte ptr [P+ebx] mov bl, al add bl, cl add ebx, edi and ebx, 255 mov cl, byte ptr [P+ebx] mov ebx, esi and ebx, 7 xor word ptr[MAC+ebx*4], cx xor word ptr[MAC+ebx*4+2], dx mov bl, byte ptr [P+eax] mov bh, byte ptr [P+esi] mov byte ptr [P+eax], bh mov byte ptr [P+esi], bl xor ebx, ebx inc esi and esi, 255 inc edi cmp edi, 24 jbe @Loop mov s, al pop ebx pop esi pop edi end; procedure VMPCOutputMAC_ASM; begin VMPCOutputMAC_ASM_internal; VMPCInitKeyRound_ASM(MAC, 32, 1); FillChar(MAC, 20, 0); VMPCEncrypt_ASM(MAC, 20); end; procedure VMPCEraseKey_ASM; asm push edi xor eax, eax mov edi, offset P mov ecx, 64 cld rep stosd mov edi, offset MAC mov ecx, 8 rep stosd mov s, 0 mov n, 0 mov m1, 0 mov m2, 0 mov m3, 0 mov m4, 0 mov mn, 0 pop edi end; //--------------------------------------------------------------------------------------------------- //--------------------------------------------- KONIEC ---------------------------------------------- //---------------------------------------------------------------------------------------------------