📄 anubis.c
字号:
/** Initialize the Anubis block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */#ifdef LTC_CLEAN_STACKstatic int _anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)#elseint anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)#endif{ int N, R, i, pos, r; ulong32 kappa[MAX_N]; ulong32 inter[MAX_N]; ulong32 v, K0, K1, K2, K3; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* Valid sizes (in bytes) are 16, 20, 24, 28, 32, 36, and 40. */ if ((keylen & 3) || (keylen < 16) || (keylen > 40)) { return CRYPT_INVALID_KEYSIZE; } skey->anubis.keyBits = keylen*8; /* * determine the N length parameter: * (N.B. it is assumed that the key length is valid!) */ N = skey->anubis.keyBits >> 5; /* * determine number of rounds from key size: */ skey->anubis.R = R = 8 + N; if (num_rounds != 0 && num_rounds != skey->anubis.R) { return CRYPT_INVALID_ROUNDS; } /* * map cipher key to initial key state (mu): */ for (i = 0, pos = 0; i < N; i++, pos += 4) { kappa[i] = (key[pos ] << 24) ^ (key[pos + 1] << 16) ^ (key[pos + 2] << 8) ^ (key[pos + 3] ); } /* * generate R + 1 round keys: */ for (r = 0; r <= R; r++) { /* * generate r-th round key K^r: */ K0 = T4[(kappa[N - 1] >> 24) ]; K1 = T4[(kappa[N - 1] >> 16) & 0xff]; K2 = T4[(kappa[N - 1] >> 8) & 0xff]; K3 = T4[(kappa[N - 1] ) & 0xff]; for (i = N - 2; i >= 0; i--) { K0 = T4[(kappa[i] >> 24) ] ^ (T5[(K0 >> 24) ] & 0xff000000U) ^ (T5[(K0 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K0 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K0 ) & 0xff] & 0x000000ffU); K1 = T4[(kappa[i] >> 16) & 0xff] ^ (T5[(K1 >> 24) ] & 0xff000000U) ^ (T5[(K1 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K1 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K1 ) & 0xff] & 0x000000ffU); K2 = T4[(kappa[i] >> 8) & 0xff] ^ (T5[(K2 >> 24) ] & 0xff000000U) ^ (T5[(K2 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K2 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K2 ) & 0xff] & 0x000000ffU); K3 = T4[(kappa[i] ) & 0xff] ^ (T5[(K3 >> 24) ] & 0xff000000U) ^ (T5[(K3 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K3 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K3 ) & 0xff] & 0x000000ffU); } /* -- this is the code to use with the large U tables: K0 = K1 = K2 = K3 = 0; for (i = 0; i < N; i++) { K0 ^= U[i][(kappa[i] >> 24) ]; K1 ^= U[i][(kappa[i] >> 16) & 0xff]; K2 ^= U[i][(kappa[i] >> 8) & 0xff]; K3 ^= U[i][(kappa[i] ) & 0xff]; } */ skey->anubis.roundKeyEnc[r][0] = K0; skey->anubis.roundKeyEnc[r][1] = K1; skey->anubis.roundKeyEnc[r][2] = K2; skey->anubis.roundKeyEnc[r][3] = K3; /* * compute kappa^{r+1} from kappa^r: */ if (r == R) { break; } for (i = 0; i < N; i++) { int j = i; inter[i] = T0[(kappa[j--] >> 24) ]; if (j < 0) j = N - 1; inter[i] ^= T1[(kappa[j--] >> 16) & 0xff]; if (j < 0) j = N - 1; inter[i] ^= T2[(kappa[j--] >> 8) & 0xff]; if (j < 0) j = N - 1; inter[i] ^= T3[(kappa[j ] ) & 0xff]; } kappa[0] = inter[0] ^ rc[r]; for (i = 1; i < N; i++) { kappa[i] = inter[i]; } } /* * generate inverse key schedule: K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}): */ for (i = 0; i < 4; i++) { skey->anubis.roundKeyDec[0][i] = skey->anubis.roundKeyEnc[R][i]; skey->anubis.roundKeyDec[R][i] = skey->anubis.roundKeyEnc[0][i]; } for (r = 1; r < R; r++) { for (i = 0; i < 4; i++) { v = skey->anubis.roundKeyEnc[R - r][i]; skey->anubis.roundKeyDec[r][i] = T0[T4[(v >> 24) ] & 0xff] ^ T1[T4[(v >> 16) & 0xff] & 0xff] ^ T2[T4[(v >> 8) & 0xff] & 0xff] ^ T3[T4[(v ) & 0xff] & 0xff]; } } return CRYPT_OK;}#ifdef LTC_CLEAN_STACKint anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey){ int err; err = _anubis_setup(key, keylen, num_rounds, skey); burn_stack(sizeof(int) * 5 + sizeof(ulong32) * (MAX_N + MAX_N + 5)); return err;}#endif static void anubis_crypt(const unsigned char *plaintext, unsigned char *ciphertext, ulong32 roundKey[18 + 1][4], int R) { int i, pos, r; ulong32 state[4]; ulong32 inter[4]; /* * map plaintext block to cipher state (mu) * and add initial round key (sigma[K^0]): */ for (i = 0, pos = 0; i < 4; i++, pos += 4) { state[i] = (plaintext[pos ] << 24) ^ (plaintext[pos + 1] << 16) ^ (plaintext[pos + 2] << 8) ^ (plaintext[pos + 3] ) ^ roundKey[0][i]; } /* * R - 1 full rounds: */ for (r = 1; r < R; r++) { inter[0] = T0[(state[0] >> 24) ] ^ T1[(state[1] >> 24) ] ^ T2[(state[2] >> 24) ] ^ T3[(state[3] >> 24) ] ^ roundKey[r][0]; inter[1] = T0[(state[0] >> 16) & 0xff] ^ T1[(state[1] >> 16) & 0xff] ^ T2[(state[2] >> 16) & 0xff] ^ T3[(state[3] >> 16) & 0xff] ^ roundKey[r][1]; inter[2] = T0[(state[0] >> 8) & 0xff] ^ T1[(state[1] >> 8) & 0xff] ^ T2[(state[2] >> 8) & 0xff] ^ T3[(state[3] >> 8) & 0xff] ^ roundKey[r][2]; inter[3] = T0[(state[0] ) & 0xff] ^ T1[(state[1] ) & 0xff] ^ T2[(state[2] ) & 0xff] ^ T3[(state[3] ) & 0xff] ^ roundKey[r][3]; state[0] = inter[0]; state[1] = inter[1]; state[2] = inter[2]; state[3] = inter[3]; } /* * last round: */ inter[0] = (T0[(state[0] >> 24) ] & 0xff000000U) ^ (T1[(state[1] >> 24) ] & 0x00ff0000U) ^ (T2[(state[2] >> 24) ] & 0x0000ff00U) ^ (T3[(state[3] >> 24) ] & 0x000000ffU) ^ roundKey[R][0]; inter[1] = (T0[(state[0] >> 16) & 0xff] & 0xff000000U) ^ (T1[(state[1] >> 16) & 0xff] & 0x00ff0000U) ^ (T2[(state[2] >> 16) & 0xff] & 0x0000ff00U) ^ (T3[(state[3] >> 16) & 0xff] & 0x000000ffU) ^ roundKey[R][1]; inter[2] = (T0[(state[0] >> 8) & 0xff] & 0xff000000U) ^ (T1[(state[1] >> 8) & 0xff] & 0x00ff0000U) ^ (T2[(state[2] >> 8) & 0xff] & 0x0000ff00U) ^ (T3[(state[3] >> 8) & 0xff] & 0x000000ffU) ^ roundKey[R][2]; inter[3] = (T0[(state[0] ) & 0xff] & 0xff000000U) ^ (T1[(state[1] ) & 0xff] & 0x00ff0000U) ^ (T2[(state[2] ) & 0xff] & 0x0000ff00U) ^ (T3[(state[3] ) & 0xff] & 0x000000ffU) ^ roundKey[R][3]; /* * map cipher state to ciphertext block (mu^{-1}): */ for (i = 0, pos = 0; i < 4; i++, pos += 4) { ulong32 w = inter[i]; ciphertext[pos ] = (unsigned char)(w >> 24); ciphertext[pos + 1] = (unsigned char)(w >> 16); ciphertext[pos + 2] = (unsigned char)(w >> 8); ciphertext[pos + 3] = (unsigned char)(w ); }}/** Encrypts a block of text with Anubis @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful*/int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey){ LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); anubis_crypt(pt, ct, skey->anubis.roundKeyEnc, skey->anubis.R); return CRYPT_OK;}/** Decrypts a block of text with Anubis @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful*/int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey){ LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); anubis_crypt(ct, pt, skey->anubis.roundKeyDec, skey->anubis.R); return CRYPT_OK;}/** Performs a self-test of the Anubis block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled*/int anubis_test(void){#if !defined(LTC_TEST) return CRYPT_NOP;#else static const struct test { int keylen; unsigned char pt[16], ct[16], key[40]; } tests[] = {#ifndef ANUBIS_TWEAK /**** ORIGINAL ANUBIS ****/ /* 128 bit keys */{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -