├── ZUC.h ├── Makefile ├── README.md ├── LICENSE ├── main.cpp └── ZUC.cpp /ZUC.h: -------------------------------------------------------------------------------- 1 | #ifndef ZUC_H 2 | #define ZUC_H 3 | 4 | void GenerateKeyStream(unsigned int *pKeyStream, unsigned int KeyStreamLen); 5 | void Initialization(unsigned char *k, unsigned char *iv); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC=g++ 3 | CFLAGS=-c -Wall 4 | 5 | SOURCES= ZUC.cpp main.cpp 6 | OBJECTS=$(SOURCES:.cpp=.o) 7 | EXECUTABLE=prog 8 | 9 | all: $(SOURCES) $(EXECUTABLE) clean 10 | 11 | $(EXECUTABLE): $(OBJECTS) 12 | $(CC) $(LDFLAGS) $(OBJECTS) -o $@ 13 | 14 | .cpp.o: 15 | $(CC) $(CFLAGS) $< -o $@ 16 | 17 | clean: 18 | rm *.o 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ZUC 2 | ======= 3 | 4 | The stream cipher ZUC is a world–oriented stream cipher, taking a 128-bit secret key and a 128-bit IV as input, and outputs a keystream of 32-bit words, which is used to encrypt or decrypt the data. 5 | 6 | This repository is my implementation of standart: [Specification](http://www.gsma.com/aboutus/wp-content/uploads/2014/12/eea3eia3zucv16.pdf). 7 | 8 | 9 | ##### Algorithm 10 | 11 | ![alg](https://i.imgur.com/ON9DPmY.png) 12 | 13 | 14 | ##### Links 15 | 16 | [Analysis on ZUC Algorithm](https://eprint.iacr.org/2012/299.pdf) 17 | 18 | [Wiki](https://en.wikipedia.org/wiki/Zuc_stream_cipher) 19 | 20 | [ZUC in Cryptol](https://galois.com/blog/2011/06/zuc-in-cryptol) 21 | 22 | 23 | ##### Usage 24 | 25 | Count `main.cpp` as test case. 26 | 27 | ```bash 28 | $ make 29 | $ ./prog 30 | ``` 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Kirill Bobrov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ZUC.h" 8 | 9 | int main(int argc, char *argv[]){ 10 | unsigned char iv[16] = {0x84, 0x31, 0x9a, 0xa8, 0xde, 0x69, 0x15, 0xca, 0x1f, 0x6b, 0xda, 0x6b, 0xfb, 0xd8, 0xc7, 0x66}; 11 | 12 | std::string key_string; 13 | std::cout << "Enter key (16 symbols only):\n>>"; 14 | getline(std::cin, key_string); 15 | if(key_string.size() != 16){ 16 | std::cout << "Bad key size:" << key_string.size() << std::endl; 17 | return -1; 18 | } 19 | unsigned char *key = (unsigned char*)key_string.c_str(); 20 | 21 | int keyStreamSize = 0; 22 | std::cout << "Enter key stream size:\n>>"; 23 | std::cin >> keyStreamSize; 24 | 25 | unsigned int *pKeyStream = new unsigned int[keyStreamSize]; 26 | Initialization(key, iv); 27 | GenerateKeyStream(pKeyStream, keyStreamSize); 28 | 29 | std::cout << "Generated key stream:" << std::endl << std::endl; 30 | 31 | for (int i = 0; i < keyStreamSize; ++i){ 32 | std::cout << std::dec << i << "\t0x" << std::oct << pKeyStream[i] << std::endl; 33 | } 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /ZUC.cpp: -------------------------------------------------------------------------------- 1 | #include "ZUC.h" 2 | 3 | /* state registers LFSR */ 4 | unsigned int LFSR_S[16] ; 5 | 6 | /* F registers */ 7 | unsigned int F_R1 ; 8 | unsigned int F_R2 ; 9 | 10 | /* output of BR procedure */ 11 | unsigned int BRC_X[4] ; 12 | 13 | /* S-boxes */ 14 | unsigned char S0[256] = { 15 | 0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb, 16 | 0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90, 17 | 0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac, 18 | 0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38, 19 | 0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b, 20 | 0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c, 21 | 0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad, 22 | 0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8, 23 | 0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56, 24 | 0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe, 25 | 0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d, 26 | 0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23, 27 | 0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1, 28 | 0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f, 29 | 0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65, 30 | 0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60 31 | }; 32 | 33 | unsigned char S1[256] = { 34 | 0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77, 35 | 0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42, 36 | 0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1, 37 | 0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48, 38 | 0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87, 39 | 0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb, 40 | 0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09, 41 | 0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9, 42 | 0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9, 43 | 0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89, 44 | 0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4, 45 | 0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde, 46 | 0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21, 47 | 0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34, 48 | 0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28, 49 | 0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2 50 | }; 51 | 52 | /* D constants */ 53 | unsigned int EK_d[16] = { 54 | 0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF, 55 | 0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC 56 | }; 57 | 58 | unsigned int AddM(unsigned int a, unsigned int b) { 59 | unsigned int c = a + b; 60 | return (c & 0x7FFFFFFF) + (c >> 31); 61 | } 62 | 63 | #define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF) 64 | 65 | /* LFSR */ 66 | void LFSRWithInitializationMode(unsigned int u) { 67 | unsigned int f, v; 68 | 69 | f = LFSR_S[0]; 70 | v = MulByPow2(LFSR_S[0], 8); 71 | f = AddM(f, v); 72 | 73 | v = MulByPow2(LFSR_S[4], 20); 74 | f = AddM(f, v); 75 | 76 | v = MulByPow2(LFSR_S[10], 21); 77 | f = AddM(f, v); 78 | 79 | v = MulByPow2(LFSR_S[13], 17); 80 | f = AddM(f, v); 81 | 82 | v = MulByPow2(LFSR_S[15], 15); 83 | f = AddM(f, v); 84 | 85 | f = AddM(f, u); 86 | 87 | /* update the state */ 88 | for(int i = 0; i < 15; ++i) { 89 | LFSR_S[i] = LFSR_S[i + 1]; 90 | } 91 | LFSR_S[15] = f; 92 | } 93 | 94 | /* LFSR with work mode */ 95 | void LFSRWithWorkMode() { 96 | unsigned int f, v; 97 | 98 | f = LFSR_S[0]; 99 | v = MulByPow2(LFSR_S[0], 8); 100 | f = AddM(f, v); 101 | 102 | v = MulByPow2(LFSR_S[4], 20); 103 | f = AddM(f, v); 104 | 105 | v = MulByPow2(LFSR_S[10], 21); 106 | f = AddM(f, v); 107 | 108 | v = MulByPow2(LFSR_S[13], 17); 109 | f = AddM(f, v); 110 | 111 | v = MulByPow2(LFSR_S[15], 15); 112 | f = AddM(f, v); 113 | 114 | /* update state */ 115 | for(int i = 0; i < 15; ++i) { 116 | LFSR_S[i] = LFSR_S[i + 1]; 117 | } 118 | LFSR_S[15] = f; 119 | } 120 | 121 | /* Bit Reorganization Procedure */ 122 | void BitReorganization() { 123 | BRC_X[0] = ((LFSR_S[15] & 0x7FFF8000) << 1) | (LFSR_S[14] & 0xFFFF); 124 | BRC_X[1] = ((LFSR_S[11] & 0xFFFF) << 16) | (LFSR_S[9] >> 15); 125 | BRC_X[2] = ((LFSR_S[7] & 0xFFFF) << 16) | (LFSR_S[5] >> 15); 126 | BRC_X[3] = ((LFSR_S[2] & 0xFFFF) << 16) | (LFSR_S[0] >> 15); 127 | } 128 | 129 | #define ROT(a, k) (((a) << k) | ((a) >> (32 - k))) 130 | 131 | /* linear transformation L1 */ 132 | unsigned int L1(unsigned int X) { 133 | return (X ^ ROT(X, 2) ^ ROT(X, 10) ^ ROT(X, 18) ^ ROT(X, 24)); 134 | } 135 | 136 | /* linear transformation L2 */ 137 | unsigned int L2(unsigned int X) { 138 | return (X ^ ROT(X, 8) ^ ROT(X, 14) ^ ROT(X, 22) ^ ROT(X, 30)); 139 | } 140 | 141 | /* create 32-bit word */ 142 | #define MAKEU32(a, b, c ,d) (\ 143 | ((unsigned int)(a) << 24) \ 144 | | ((unsigned int)(b) << 16) \ 145 | | ((unsigned int)(c) << 8) \ 146 | | ((unsigned int)(d))) 147 | 148 | 149 | /* non-linear function F */ 150 | unsigned int F(void) { 151 | unsigned int W, W1, W2, u, v; 152 | 153 | W = (BRC_X[0] ^ F_R1) + F_R2; 154 | W1 = F_R1 + BRC_X[1]; 155 | W2 = F_R2 ^ BRC_X[2]; 156 | u = L1((W1 << 16) | (W2 >> 16)); 157 | v = L2((W2 << 16) | (W1 >> 16)); 158 | F_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF], S0[(u >> 8) & 0xFF], S1[u & 0xFF]); 159 | F_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF], S0[(v >> 8) & 0xFF], S1[v & 0xFF]); 160 | 161 | return W; 162 | } 163 | 164 | #define MAKEU31(a, b, c) ( \ 165 | ((unsigned int)((unsigned int)(0) \ 166 | | (unsigned char)(a)) << 23) \ 167 | | ((unsigned int)(b) << 8) \ 168 | | (unsigned int)((unsigned int)(0) \ 169 | | (unsigned char)(c))) 170 | 171 | 172 | void Initialization(unsigned char *k, unsigned char *iv) { 173 | unsigned int w; 174 | 175 | /* expand key */ 176 | for(int i = 0; i < 16; ++i) { 177 | LFSR_S[i] = MAKEU31(k[i], EK_d[i], iv[i]); 178 | } 179 | /* set F_R1 and F_R2 to zero */ 180 | F_R1 = 0; 181 | F_R2 = 0; 182 | unsigned int nCount = 32; 183 | while (nCount > 0){ 184 | BitReorganization(); 185 | w = F(); 186 | LFSRWithInitializationMode(w >> 1); 187 | nCount--; 188 | } 189 | 190 | BitReorganization(); 191 | F(); 192 | LFSRWithWorkMode(); 193 | } 194 | 195 | void GenerateKeyStream(unsigned int *pKeyStream, unsigned int KeyStreamLen){ 196 | /* working cycles */ 197 | for (int i = 0; i < KeyStreamLen; ++i){ 198 | BitReorganization(); 199 | pKeyStream[i] = F() ^ BRC_X[3]; 200 | LFSRWithWorkMode(); 201 | } 202 | } 203 | --------------------------------------------------------------------------------