📄 loki97.c
字号:
return TRUE;}/* * decrypt blocks in CFB1 mode */static int deCFB1(cipherInstance *cipher, keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer){ int i,j,k; /* assorted loop counters */ int b; /* bit number being processed in byte */ BYTE msgbit, prev, keybit; /* current & prev message and stream key bits */ ULONG64 L, R; /* left and right data blocks */ ULONG64 nR, f_out; /* get CFB1 input buffer from IV */ L = cipher->IVL; R = cipher->IVR; /* get ready to process first byte */ b = 7; /* start with top bit in byte */ *outBuffer = 0; /* and zero byte in outBuffer */ /* now loop over all bits of input */ for (j = 0; j < inputLen; j++) { msgbit = (*input >> b) & 01; /* get next msg bit */ prev = msgbit; /* and save for shift register update */ if (debuglevel) fprintf(stderr,"%s: deCFB1(%01X,%08X%08X%08X%08X) ", NAME, msgbit, L.l, L.r, R.l, R.r); if (debuglevel > 1) fprintf(stderr,"\n"); /* compute all rounds to encrypt current CFB1 buffer */ k = 0; for (i = 0; i < ROUNDS; i++) { nR = add64(R, key->SK[k++]); /* nR = R+SK(k) */ f_out = f(nR, key->SK[k++]); /* f = f(nR,SK(k+1)) */ nR = add64(nR, key->SK[k++]); /* nR = nR+SK(k+2) */ R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */ L = nR; /* L = nR */ if (debuglevel > 1) fprintf(stderr," L[%02d]=%08X%08X; R[%02d]=%08X%08X; f(SK(%02d))=%08X%08X\n", i+1, L.l, L.r, i+1, R.l, R.r, k-2, f_out.l, f_out.r); } /* undo last swap */ L = R; R = nR; /* now process msgbit by getting stream key bit, XOR in and or to out */ keybit = L.l >> 31; msgbit ^= keybit; *outBuffer |= (msgbit << b); if (debuglevel > 0) fprintf(stderr,"= %01X,%08X%08X%08X%08X\n", msgbit, L.l, L.r, R.l, R.r); /* and update the CFB1 shift register (input buffer L,R) */ L.l = (L.l << 1) | (L.r >> 31); L.r = (L.r << 1) | (R.l >> 31); R.l = (R.l << 1) | (R.r >> 31); R.r = (R.r << 1) | prev; /* and update bit position counter */ b--; /* and move to next input/output byte if necessary */ if (b<0) { b = 7; input++; outBuffer++; *outBuffer = 0; } } /* save new IV value */ cipher->IVL = L; cipher->IVR = R; return TRUE;}/* LOKI97 methods *//* ......................................................................... */ /* * f(A,B) = Sb(P(Sa(E(KP(A,hi(B))))),lo(B)) - complex non-linear round function */static ULONG64 f (ULONG64 A, ULONG64 B){ ULONG64 d, e, f; /* intermediate values in f computation */ register s; /* s-box output value */ /* Intermediate values in the computation are: */ /* d = KP(A,Br) */ /* e = P(Sa(d)) */ /* f = Sb(e,Bl) */ /* Compute d = KP(A,B), where KP is a keyed permutation used to */ /* exchange corresponding bits in 32-bit words [Al,Ar] */ /* based on the lower half of B (swap if B bit is 1) */ /* KP(A,B) = ((Al & ~Br)|(Ar & Br)) | ((Ar & ~Br)|(Al & Br)) */ d.l = ((A.l & ~B.r) | (A.r & B.r)); d.r = ((A.r & ~B.r) | (A.l & B.r)); /* Compute e = P(Sa(d)) */ /* mask out each group of 12 bits for E */ /* then compute first S-box column [S1,S2,S1,S2,S2,S1,S2,S1] */ /* permuting output through P (with extra shift to build full P) */ s = S1[(d.l>>24 | d.r<<8) & 0x1FFF]; e.l = P[s].l>>7; e.r = P[s].r>>7; s = S2[(d.l>>16) & 0x7FF]; e.l |= P[s].l>>6; e.r |= P[s].r>>6; s = S1[(d.l>> 8) & 0x1FFF]; e.l |= P[s].l>>5; e.r |= P[s].r>>5; s = S2[ d.l & 0x7FF]; e.l |= P[s].l>>4; e.r |= P[s].r>>4; s = S2[(d.r>>24 | d.l<<8) & 0x7FF]; e.l |= P[s].l>>3; e.r |= P[s].r>>3; s = S1[(d.r>>16) & 0x1FFF]; e.l |= P[s].l>>2; e.r |= P[s].r>>2; s = S2[(d.r>> 8) & 0x7FF]; e.l |= P[s].l>>1; e.r |= P[s].r>>1; s = S1[ d.r & 0x1FFF]; e.l |= P[s].l; e.r |= P[s].r; /* Compute f = Sb(e,B) */ /* where the second S-box column is [S2,S2,S1,S1,S2,S2,S1,S1] */ /* for each S, lower bits come from e, upper from upper half of B */ f.l = S2[(((e.l>>24) & 0xFF) | ((B.l>>21) & 0x700))] << 24 | S2[(((e.l>>16) & 0xFF) | ((B.l>>18) & 0x700))] << 16 | S1[(((e.l>> 8) & 0xFF) | ((B.l>>13) & 0x1F00))] << 8 | S1[(((e.l ) & 0xFF) | ((B.l>> 8) & 0x1F00))]; f.r = S2[(((e.r>>24) & 0xFF) | ((B.l>> 5) & 0x700))] << 24 | S2[(((e.r>>16) & 0xFF) | ((B.l>> 2) & 0x700))] << 16 | S1[(((e.r>> 8) & 0xFF) | ((B.l<< 3) & 0x1F00))] << 8 | S1[(( e.r & 0xFF) | ((B.l<< 8) & 0x1F00))]; if (debuglevel > 3) fprintf(stderr,"%s: f(%08X%08X,%08X%08X) = %08X%08X\n", NAME, A.l, A.r, B.l, B.r, f.l, f.r); if (debuglevel > 4) fprintf(stderr,"%s: d=%08X%08X; e=%08X%08X\n", NAME, d.l, d.r, e.l, e.r); return f;}/* utility methods *//* ......................................................................... *//* add64(a,b) - fudge 64-bit addition of ULONG64's a and b *//* thanks to Markku-Juhani Saarinen <mjos@ssh.fi> for the nice tips */static ULONG64 add64(ULONG64 a, ULONG64 b){ ULONG64 sum; /* sum = a + b */ sum.r = a.r + b.r; /* add lower half */ sum.l = a.l + b.l; /* add upper half without carry */ if (sum.r < b.r) sum.l++; /* add carry if needed */ return sum; /* return resulting sum */}/* sub64(a,b) - fudge 64-bit subtraction of ULONG64's a and b *//* thanks to Markku-Juhani Saarinen <mjos@ssh.fi> for the nice tips */static ULONG64 sub64(ULONG64 a, ULONG64 b){ ULONG64 diff; /* diff = a + b */ diff.r = a.r - b.r; /* sub lower 32-bits */ diff.l = a.l - b.l; /* sub upper 32-bits */ if (diff.r > a.r) diff.l--; /* sub borrow if needed */ return diff; /* return resulting diff */}/* Returns a ULONG64 I constructed from a byte array. */static ULONG64 byteToULONG64(BYTE *inp){ ULONG64 I; I.l = (*inp++ << 24); I.l |= (*inp++ << 16); I.l |= (*inp++ << 8); I.l |= *inp++; I.r = (*inp++ << 24); I.r |= (*inp++ << 16); I.r |= (*inp++ << 8); I.r |= *inp++; return I;}/* Returns a byte array buf constructed by unpacking ULONG64 I. */static BYTE *ULONG64ToBYTE(BYTE *buf, ULONG64 I){ BYTE *sav = buf; *buf++ = (I.l >> 24); *buf++ = (I.l >> 16); *buf++ = (I.l >> 8); *buf++ = I.l; *buf++ = (I.r >> 24); *buf++ = (I.r >> 16); *buf++ = (I.r >> 8); *buf++ = I.r; return sav;}/* Returns a BYTE array from a string of hexadecimal digits. */static BYTE *charToBYTE(BYTE *buf, char *hex, int len){ int i = 0, j = 0; while (j < len) { buf[j++] = (BYTE)((fromHex(hex[i++])<<4) | fromHex(hex[i++])); } return buf;}/* Returns a ULONG64 I constructed from a string of hexadecimal digits. */static ULONG64 charToULONG64(char *hex){ ULONG64 I; I.l = fromHex(*hex++) << 28; I.l |= fromHex(*hex++) << 24; I.l |= fromHex(*hex++) << 20; I.l |= fromHex(*hex++) << 16; I.l |= fromHex(*hex++) << 12; I.l |= fromHex(*hex++) << 8; I.l |= fromHex(*hex++) << 4; I.l |= fromHex(*hex++); I.r = fromHex(*hex++) << 28; I.r |= fromHex(*hex++) << 24; I.r |= fromHex(*hex++) << 20; I.r |= fromHex(*hex++) << 16; I.r |= fromHex(*hex++) << 12; I.r |= fromHex(*hex++) << 8; I.r |= fromHex(*hex++) << 4; I.r |= fromHex(*hex++); return I;}/* Returns number from 0 to 15 corresponding to hex digit ch */static int fromHex (char ch){ if (ch >= '0' && ch <= '9') return ch - '0'; else if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; else if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; else return 0;}/* puthex(out, len, f) - display a len byte value out in hex to file f */static int puthex(BYTE *out, int len, FILE *f){ int i; for(i=0;i<len;i++){ fprintf(f, "%02X",*out++ & 0xff); } fputc(' ', f);}/* ......................................................................... *//* * self_test() - Encryption/decryption test using the standard single triple * returns true or error code */int self_test(){ int enok = TRUE, deok = TRUE; char *hexkey = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"; char *hexcipher = "75080E359F10FE640144B35C57128DAD"; char *hexIV = "00000000000000000000000000000000"; BYTE plain[BLOCK_SIZE] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; BYTE etemp[BLOCK_SIZE], dtemp[BLOCK_SIZE], cipher[BLOCK_SIZE]; keyInstance enc_key, dec_key; /* AES keyInstances */ cipherInstance loki97_cipher; /* AES cipherInstance */ int i, st; /* construct desired cipher block */ charToBYTE(cipher,hexcipher,sizeof(cipher)); /* Init LOKI97 cipher in ECB mode */ st = cipherInit(&loki97_cipher, MODE_ECB, hexIV); if (st != TRUE) return st; /* test encrypt */ st = makeKey(&enc_key, DIR_ENCRYPT, 256, hexkey); if (st != TRUE) return st; fprintf(stderr,"Plaintext is: "); puthex(plain,16,stderr); fprintf(stderr,"\n"); st = blockEncrypt(&loki97_cipher, &enc_key, plain, sizeof(plain)*8, etemp); if (st != TRUE) return st; if (memcmp(etemp, cipher, sizeof(etemp)) != 0) enok = FALSE; fprintf(stderr,"Test encrypt: "); puthex(etemp,16,stderr); fprintf(stderr," %s\n", (enok?"GOOD" : "FAILED")); /* test decrypt */ st = makeKey(&dec_key, DIR_DECRYPT, 256, hexkey); if (st != TRUE) return st; st = blockDecrypt(&loki97_cipher, &dec_key, etemp, sizeof(etemp)*8, dtemp); if (st != TRUE) return st; if (memcmp(dtemp, plain, sizeof(dtemp)) != 0) deok = FALSE; fprintf(stderr,"Test decrypt: "); puthex(dtemp,16,stderr); fprintf(stderr," %s\n", (deok?"GOOD" : "FAILED")); return (enok && deok); /* return TRUE only if both en & decrypt ok */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -