├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── aes.c ├── aes.h ├── aes_cbc.c ├── aes_cbc.h ├── aes_client.c ├── aes_cmac.c ├── aes_cmac.h ├── bignum.c ├── bignum.h ├── bignum_test.c ├── hmac.c ├── hmac.h ├── rsa.c ├── rsa.h ├── sha256.c ├── sha256.h ├── sign.c ├── sign.h └── signature_client.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 jimzhong 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-c -Wall 3 | 4 | all: aes signature 5 | 6 | aes: aes.o aes_client.o aes_cbc.o aes_cmac.o 7 | $(CC) aes_client.o aes.o aes_cbc.o aes_cmac.o -o aes_client 8 | 9 | aes.o: aes.c aes.h 10 | $(CC) $(CFLAGS) aes.c 11 | 12 | aes_client.o: aes_client.c 13 | $(CC) $(CFLAGS) aes_client.c 14 | 15 | aes_cbc.o: aes_cbc.c aes_cbc.h 16 | $(CC) $(CFLAGS) aes_cbc.c 17 | 18 | clean: 19 | rm *.o 20 | rm aes_client 21 | rm signature_client 22 | 23 | aes_cmac.o: aes_cmac.c aes_cmac.h 24 | $(CC) $(CFLAGS) aes_cmac.c 25 | 26 | signature: sha256.o signature_client.o hmac.o bignum.o rsa.o sign.o 27 | $(CC) sha256.o signature_client.o hmac.o rsa.o bignum.o sign.o -o signature_client 28 | 29 | sha256.o: sha256.h sha256.c 30 | $(CC) $(CFLAGS) sha256.c 31 | 32 | hmac.o: hmac.c hmac.h 33 | $(CC) $(CFLAGS) hmac.c 34 | 35 | bignum.o: bignum.c bignum.h 36 | $(CC) $(CFLAGS) bignum.c 37 | 38 | signature_client.o: signature_client.c 39 | $(CC) $(CFLAGS) signature_client.c 40 | 41 | bignum_test: bignum_test.c bignum.o 42 | $(CC) bignum_test.c bignum.o -o bignum_test 43 | 44 | ras.o: rsa.c rsa.h 45 | $(CC) $(CFLAGS) rsa.c 46 | 47 | sign.o: sign.c sign.h 48 | $(CC) $(CFLAGS) sign.c 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A Project of Cryptography - the art of encrypting the text 2 | --------------------------------------- 3 | This project implements AES, CMAC, SHA256, HMAC, RSA in C language. 4 | 5 | The code is for demostration rather than production use. 6 | 7 | hope it will help you 8 | -------------------------------------------------------------------------------- /aes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "aes.h" 7 | 8 | // #define DEBUG_ENCRYPT 9 | // #define DEBUG_DECRYPT 10 | 11 | //SBox taken from Wikipedia 12 | static const uint8_t sbox[256] = 13 | { 14 | 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 15 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 16 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 17 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 18 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 19 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 20 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 21 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 22 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 23 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 24 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 25 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 26 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 27 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 28 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 29 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 30 | }; 31 | 32 | static const uint8_t inv_sbox[256] = 33 | { 34 | 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 35 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 36 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 37 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 38 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 39 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 40 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 41 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 42 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 43 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 44 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 45 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 46 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 47 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 48 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 49 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D 50 | }; 51 | 52 | //round constants for key expansion 53 | static const uint8_t rcon[255] = 54 | { 55 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 56 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 57 | 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 58 | 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 59 | 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 60 | 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 61 | 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 62 | 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 63 | 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 64 | 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 65 | 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 66 | 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 67 | 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 68 | 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 69 | 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 70 | 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb 71 | }; 72 | 73 | 74 | /* 75 | Internal function declaration 76 | */ 77 | static void mix_columns(aes_ctx_t *ctx); 78 | static void key_expansion(aes_ctx_t *ctx, int current_key_size, int required_key_size); 79 | static void sub_bytes(aes_ctx_t *ctx); 80 | static void shift_rows(aes_ctx_t *ctx); 81 | 82 | static void inv_sub_bytes(aes_ctx_t *ctx); 83 | static void inv_shift_rows(aes_ctx_t *ctx); 84 | static void inv_mix_columns(aes_ctx_t *ctx); 85 | 86 | static void add_roundkey(aes_ctx_t *ctx, int current_round); 87 | 88 | //for MixColumns 89 | static uint8_t multiply(uint8_t a, uint8_t b); 90 | 91 | //for key_expansion 92 | static void key_expansion_core(uint8_t *word, int iteration); 93 | static void rotate(uint8_t *word); 94 | 95 | //for debugging 96 | static void print_hex(uint8_t *ptr, int len); 97 | 98 | void AES_encrypt(aes_ctx_t *ctx, uint8_t *in, uint8_t *out) 99 | { 100 | int i; 101 | int current_round; //increasing 102 | 103 | #ifdef DEBUG_ENCRYPT 104 | printf("Input:\n"); 105 | print_hex(in, AES_BLOCKSIZE); 106 | #endif 107 | 108 | //copy input to state, by column 109 | for(i = 0; i < AES_BLOCKSIZE; i++) 110 | ctx->state[i%4][i/4] = in[i]; 111 | 112 | //round 0 113 | add_roundkey(ctx, 0); 114 | #ifdef DEBUG_ENCRYPT 115 | puts("round 0"); 116 | print_hex(ctx->state, AES_BLOCKSIZE); 117 | #endif 118 | 119 | for(current_round = 1; current_round < ctx->rounds; current_round++) 120 | { 121 | sub_bytes(ctx); 122 | shift_rows(ctx); 123 | mix_columns(ctx); 124 | add_roundkey(ctx, current_round); 125 | #ifdef DEBUG_ENCRYPT 126 | print_hex(ctx->state, AES_BLOCKSIZE); 127 | #endif 128 | } 129 | 130 | //last round 131 | sub_bytes(ctx); 132 | shift_rows(ctx); 133 | add_roundkey(ctx, ctx->rounds); 134 | #ifdef DEBUG_ENCRYPT 135 | puts("last round"); 136 | print_hex(ctx->state, AES_BLOCKSIZE); 137 | #endif 138 | 139 | //copy state to output, by column 140 | for(i = 0; i < AES_BLOCKSIZE; i++) 141 | out[i] = ctx->state[i%4][i/4]; 142 | 143 | #ifdef DEBUG_ENCRYPT 144 | printf("Output:\n"); 145 | print_hex(out, AES_BLOCKSIZE); 146 | #endif 147 | 148 | } 149 | 150 | void AES_decrypt(aes_ctx_t *ctx, uint8_t *in, uint8_t *out) 151 | { 152 | int i; 153 | int current_round; //decreasing 154 | 155 | #ifdef DEBUG_DECRYPT 156 | printf("Input:\n"); 157 | print_hex(in, AES_BLOCKSIZE); 158 | #endif 159 | 160 | for(i = 0; i < AES_BLOCKSIZE; i++) 161 | ctx->state[i%4][i/4] = in[i]; 162 | 163 | //first round 164 | add_roundkey(ctx, ctx->rounds); 165 | 166 | for(current_round = ctx->rounds-1; current_round > 0; current_round--) 167 | { 168 | inv_shift_rows(ctx); 169 | inv_sub_bytes(ctx); 170 | add_roundkey(ctx, current_round); 171 | inv_mix_columns(ctx); 172 | } 173 | 174 | //last round 175 | inv_shift_rows(ctx); 176 | inv_sub_bytes(ctx); 177 | add_roundkey(ctx, 0); 178 | 179 | //copy state to output, by column 180 | for(i = 0; i < AES_BLOCKSIZE; i++) 181 | out[i] = ctx->state[i%4][i/4]; 182 | 183 | #ifdef DEBUG_DECRYPT 184 | printf("Output:\n"); 185 | print_hex(out, AES_BLOCKSIZE); 186 | #endif 187 | } 188 | 189 | 190 | aes_ctx_t * AES_ctx_alloc(uint8_t *key, size_t keylen) 191 | { 192 | aes_ctx_t *ctx; 193 | int rounds; 194 | size_t round_key_size; 195 | 196 | switch (keylen) 197 | { 198 | case 16: 199 | rounds = 10; //AES128 200 | break; 201 | case 24: 202 | rounds = 12; //AES192 203 | break; 204 | case 32: 205 | rounds = 14; //AES256 206 | break; 207 | default: 208 | return NULL; 209 | } 210 | 211 | round_key_size = (rounds+1) * AES_BLOCKSIZE; 212 | ctx = malloc(sizeof(aes_ctx_t) + round_key_size); 213 | if(ctx) 214 | { 215 | ctx->rounds = rounds; 216 | ctx->keylen = keylen; 217 | memcpy(ctx->roundkey, key, keylen); 218 | key_expansion(ctx, keylen, round_key_size); 219 | // printf("expanded key:\n"); 220 | // print_hex(ctx->roundkey, round_key_size); 221 | } 222 | return ctx; 223 | } 224 | 225 | static void key_expansion(aes_ctx_t *ctx, int current_key_size, int required_key_size) 226 | { 227 | int iteration = 1; 228 | int i; 229 | uint8_t t[4]; 230 | 231 | while(current_key_size < required_key_size) 232 | { 233 | for(i = 0; i < 4; i++) 234 | t[i] = ctx->roundkey[current_key_size - 4 + i]; 235 | 236 | if(current_key_size % ctx->keylen == 0) 237 | //apply core schedule every keylen(16,24,32) bytes 238 | key_expansion_core(t, iteration++); 239 | 240 | //additional sbox operation for AES256 241 | if(ctx->keylen==32 && ((current_key_size % ctx->keylen) == 16)) 242 | { 243 | for(i = 0; i < 4; i++) 244 | t[i] = sbox[t[i]]; 245 | } 246 | 247 | for(i = 0; i < 4; i++) 248 | { 249 | ctx->roundkey[current_key_size] = ctx->roundkey[current_key_size - ctx->keylen] ^ t[i]; 250 | current_key_size++; 251 | } 252 | } 253 | } 254 | 255 | //rotate(0x12345678) -> 0x34567812 256 | static void inline rotate(uint8_t *word) 257 | { 258 | uint8_t c; 259 | c = word[0]; 260 | word[0] = word[1]; 261 | word[1] = word[2]; 262 | word[2] = word[3]; 263 | word[3] = c; 264 | } 265 | 266 | //core function for key_expansion 267 | static void key_expansion_core(uint8_t *word, int iteration) 268 | { 269 | int i; 270 | rotate(word); 271 | for (i = 0; i < 4; ++i) 272 | word[i] = sbox[word[i]]; 273 | word[0] ^= rcon[iteration]; 274 | } 275 | 276 | static void sub_bytes(aes_ctx_t *ctx) 277 | { 278 | int i, j; 279 | 280 | for(i = 0; i < 4; i++) 281 | for(j = 0; j < 4; j++) 282 | ctx->state[i][j] = sbox[ctx->state[i][j]]; 283 | } 284 | 285 | static void inv_sub_bytes(aes_ctx_t *ctx) 286 | { 287 | int i, j; 288 | 289 | for(i = 0; i < 4; i++) 290 | for(j = 0; j < 4; j++) 291 | ctx->state[i][j] = inv_sbox[ctx->state[i][j]]; 292 | } 293 | 294 | //ShiftRows for encryption 295 | static void shift_rows(aes_ctx_t *ctx) 296 | { 297 | uint8_t new_state[4][4]; 298 | int i, j; 299 | 300 | for(i = 0; i < 4; i++) 301 | for(j = 0; j < 4; j++) 302 | new_state[i][j] = ctx->state[i][(i+j) % 4]; 303 | 304 | memcpy(ctx->state, new_state, sizeof(ctx->state)); 305 | } 306 | 307 | //Inverse ShiftRows for decryption 308 | static void inv_shift_rows(aes_ctx_t *ctx) 309 | { 310 | uint8_t new_state[4][4]; 311 | int i, j; 312 | 313 | for(i = 0; i < 4; i++) 314 | for(j = 0; j < 4; j++) 315 | new_state[i][j] = ctx->state[i][(j-i+4) % 4]; 316 | 317 | memcpy(ctx->state, new_state, sizeof(ctx->state)); 318 | } 319 | 320 | //MixColumns for encryption 321 | static void mix_columns(aes_ctx_t *ctx) 322 | { 323 | uint8_t new_state[4][4]; 324 | int i; 325 | 326 | for(i = 0; i < 4; i++) { 327 | new_state[0][i] = multiply(2, ctx->state[0][i]) ^ 328 | multiply(3, ctx->state[1][i]) ^ 329 | ctx->state[2][i] ^ ctx->state[3][i]; 330 | 331 | new_state[1][i] = ctx->state[0][i] ^ 332 | multiply(2, ctx->state[1][i]) ^ 333 | multiply(3, ctx->state[2][i]) ^ 334 | ctx->state[3][i]; 335 | 336 | new_state[2][i] = ctx->state[0][i] ^ ctx->state[1][i] ^ 337 | multiply(2, ctx->state[2][i]) ^ 338 | multiply(3, ctx->state[3][i]); 339 | 340 | new_state[3][i] = multiply(3, ctx->state[0][i]) ^ 341 | ctx->state[1][i] ^ ctx->state[2][i] ^ 342 | multiply(2, ctx->state[3][i]); 343 | } 344 | 345 | memcpy(ctx->state, new_state, sizeof(ctx->state)); 346 | } 347 | 348 | //Inversed MixColumns for decryption 349 | static void inv_mix_columns(aes_ctx_t *ctx) 350 | { 351 | uint8_t new_state[4][4]; 352 | int i; 353 | 354 | for(i = 0; i < 4; i++) { 355 | new_state[0][i] = multiply(0x0e, ctx->state[0][i]) ^ 356 | multiply(0x0b, ctx->state[1][i]) ^ 357 | multiply(0x0d, ctx->state[2][i]) ^ 358 | multiply(0x09, ctx->state[3][i]); 359 | 360 | new_state[1][i] = multiply(0x09, ctx->state[0][i]) ^ 361 | multiply(0x0e, ctx->state[1][i]) ^ 362 | multiply(0x0b, ctx->state[2][i]) ^ 363 | multiply(0x0d, ctx->state[3][i]); 364 | 365 | new_state[2][i] = multiply(0x0d, ctx->state[0][i]) ^ 366 | multiply(0x09, ctx->state[1][i]) ^ 367 | multiply(0x0e, ctx->state[2][i]) ^ 368 | multiply(0x0b, ctx->state[3][i]); 369 | 370 | new_state[3][i] = multiply(0x0b, ctx->state[0][i]) ^ 371 | multiply(0x0d, ctx->state[1][i]) ^ 372 | multiply(0x09, ctx->state[2][i]) ^ 373 | multiply(0x0e, ctx->state[3][i]); 374 | } 375 | 376 | memcpy(ctx->state, new_state, sizeof(ctx->state)); 377 | } 378 | 379 | static void add_roundkey(aes_ctx_t *ctx, int current_round) 380 | { 381 | int i, j; 382 | // printf("%d round key:\n", current_round); 383 | // print_hex(ctx->roundkey + (current_round * AES_BLOCKSIZE), AES_BLOCKSIZE); 384 | 385 | for(i = 0; i < 4; i++) 386 | for(j = 0; j < 4; j++) 387 | ctx->state[i][j] ^= ctx->roundkey[current_round * AES_BLOCKSIZE + j * 4 + i]; 388 | } 389 | 390 | 391 | #define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x1b)) 392 | 393 | //multiply in GF(2^8) 394 | static uint8_t multiply(uint8_t a, uint8_t b) { 395 | int i; 396 | 397 | uint8_t c = 0; 398 | uint8_t d = b; 399 | 400 | for (i = 0 ; i < 8 ; i++) 401 | { 402 | if (a % 2 == 1) 403 | c ^= d; 404 | a /= 2; 405 | d = xtime(d); 406 | } 407 | return c; 408 | } 409 | 410 | static void print_hex(uint8_t *ptr, int len) 411 | { 412 | int i; 413 | for(i = 0; i < len; i++) 414 | { 415 | if (i % 16 == 0 && i > 0) 416 | printf("\n"); 417 | printf("%2.2x ", ptr[i]); 418 | } 419 | printf("\n"); 420 | } 421 | -------------------------------------------------------------------------------- /aes.h: -------------------------------------------------------------------------------- 1 | #ifndef __AES_H__ 2 | #define __AES_H__ 3 | 4 | #include 5 | #include 6 | 7 | #define AES_BLOCKSIZE 16 8 | 9 | typedef struct { 10 | uint8_t state[4][4]; 11 | int rounds; 12 | int keylen; 13 | uint8_t roundkey[0]; //allocate memory at runtime according to keysize 14 | } aes_ctx_t; 15 | 16 | void AES_encrypt(aes_ctx_t *ctx, uint8_t *in, uint8_t *out); 17 | 18 | void AES_decrypt(aes_ctx_t *ctx, uint8_t *in, uint8_t *out); 19 | 20 | aes_ctx_t * AES_ctx_alloc(uint8_t *key, size_t keylen); 21 | #endif 22 | -------------------------------------------------------------------------------- /aes_cbc.c: -------------------------------------------------------------------------------- 1 | #include "aes.h" 2 | #include "aes_cbc.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #define block_copy(dest, src) memcpy((dest), (src), AES_BLOCKSIZE) 8 | 9 | static void block_xor(uint8_t *a, uint8_t *b); 10 | 11 | unsigned long AES_CBC_encrypt(uint8_t *input, uint8_t *output, unsigned long length, uint8_t *key, size_t keylen, uint8_t *iv) 12 | { 13 | aes_ctx_t *ctx; 14 | uint8_t *previous_block_ciphertext = iv; 15 | unsigned long i; 16 | unsigned long output_length; 17 | 18 | ctx = AES_ctx_alloc(key, keylen); 19 | 20 | for(i = 0; i < length; i+= AES_BLOCKSIZE) 21 | { 22 | block_copy(output, input); 23 | block_xor(output, previous_block_ciphertext); 24 | AES_encrypt(ctx, output, output); 25 | previous_block_ciphertext = output; 26 | 27 | output += AES_BLOCKSIZE; 28 | input += AES_BLOCKSIZE; 29 | } 30 | output_length = (length / AES_BLOCKSIZE) * AES_BLOCKSIZE; 31 | i = length % AES_BLOCKSIZE; 32 | if (i > 0) 33 | { 34 | // puts("additional block"); 35 | //add zero padding 36 | memset(output, 0, AES_BLOCKSIZE); 37 | memcpy(output, input, i); 38 | block_xor(output, previous_block_ciphertext); 39 | AES_encrypt(ctx, output, output); 40 | output_length += AES_BLOCKSIZE; 41 | } 42 | free(ctx); 43 | 44 | return output_length; 45 | } 46 | 47 | void AES_CBC_decrypt(uint8_t *input, uint8_t *output, unsigned long length, uint8_t *key, size_t keylen, uint8_t *iv) 48 | { 49 | aes_ctx_t *ctx; 50 | uint8_t *previous_block_ciphertext = iv; 51 | unsigned long i; 52 | 53 | ctx = AES_ctx_alloc(key, keylen); 54 | 55 | for(i = 0; i < length; i+= AES_BLOCKSIZE) 56 | { 57 | block_copy(output, input); 58 | AES_decrypt(ctx, output, output); 59 | block_xor(output, previous_block_ciphertext); 60 | 61 | previous_block_ciphertext = input; 62 | output += AES_BLOCKSIZE; 63 | input += AES_BLOCKSIZE; 64 | } 65 | 66 | i = length % AES_BLOCKSIZE; 67 | if(i > 0) 68 | { 69 | block_copy(output, input); 70 | AES_decrypt(ctx, output, output); 71 | block_xor(output, previous_block_ciphertext); 72 | memset(output + i, 0, AES_BLOCKSIZE - i); 73 | } 74 | } 75 | 76 | //a = a xor b 77 | static void block_xor(uint8_t *a, uint8_t *b) 78 | { 79 | int i; 80 | for(i = 0; i < AES_BLOCKSIZE; i++) 81 | a[i] ^= b[i]; 82 | } 83 | -------------------------------------------------------------------------------- /aes_cbc.h: -------------------------------------------------------------------------------- 1 | #ifndef __AES_CBC_H__ 2 | #define __AES_CBC_H__ 3 | 4 | #include 5 | #include 6 | 7 | /* 8 | input: pointer to input data 9 | output: ..........output.... 10 | length: length of plaintext message 11 | key: pointer to key 12 | keylen: 16, 24 or 32 13 | iv: initial vector for CBC mode 14 | */ 15 | unsigned long AES_CBC_encrypt(uint8_t *input, uint8_t *output, unsigned long length, uint8_t *key, size_t keylen, uint8_t *iv); 16 | void AES_CBC_decrypt(uint8_t *input, uint8_t *output, unsigned long length, uint8_t *key, size_t keylen, uint8_t *iv); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /aes_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "aes.h" 7 | #include "aes_cbc.h" 8 | #include "aes_cmac.h" 9 | 10 | char teststring[] = "If someone loves a flower, of which just one single blossom \ 11 | grows in all the millions and millions of stars, it is enough to make him \ 12 | happy just to look at the stars. He can say to himself, \"Somewhere, my \ 13 | flower is there...\" But if the sheep eats the flower, in one moment all his \ 14 | stars will be darkened... And you think that is not important!"; 15 | 16 | static void print_hex(uint8_t *ptr, int len) 17 | { 18 | int i; 19 | for(i = 0; i < len; i++) 20 | printf("%2.2x ", ptr[i]); 21 | printf("\n"); 22 | } 23 | 24 | void aes_128_test() 25 | { 26 | uint8_t key[16] = {}; 27 | uint8_t plaintext[16] = "helloworld~"; 28 | uint8_t ciphertext[16]; 29 | uint8_t decrypted[16]; 30 | 31 | aes_ctx_t *ctx; 32 | ctx = AES_ctx_alloc(key, 16); 33 | 34 | AES_encrypt(ctx, plaintext, ciphertext); 35 | AES_decrypt(ctx, ciphertext, decrypted); 36 | free(ctx); 37 | 38 | puts("\n*********AES-128*********"); 39 | printf("plaintext: %s\n", plaintext); 40 | printf("encrypted:\n"); 41 | print_hex(ciphertext, 16); 42 | printf("decrypted: %s\n", decrypted); 43 | } 44 | 45 | void aes_256_test() 46 | { 47 | uint8_t key[32] = {}; 48 | uint8_t plaintext[16] = "I'm plaintext"; 49 | uint8_t ciphertext[16]; 50 | uint8_t decrypted[16]; 51 | 52 | aes_ctx_t *ctx; 53 | ctx = AES_ctx_alloc(key, 32); 54 | 55 | AES_encrypt(ctx, plaintext, ciphertext); 56 | AES_decrypt(ctx, ciphertext, decrypted); 57 | free(ctx); 58 | 59 | puts("\n*********AES-256**********"); 60 | printf("plaintext: %s\n", plaintext); 61 | printf("encrypted:\n"); 62 | print_hex(ciphertext, 16); 63 | printf("decrypted: %s\n", decrypted); 64 | } 65 | 66 | void aes_128_cbc_test() 67 | { 68 | uint8_t *plaintext = teststring; 69 | uint8_t ciphertext[512], decrypted[512]; 70 | uint8_t key[16] = "secretkey"; 71 | uint8_t iv[16] = "initialvec"; 72 | unsigned long ciphertext_len; 73 | unsigned long plaintext_len; 74 | 75 | puts("\n*********AES-128-CBC**********"); 76 | plaintext_len = strlen(plaintext); 77 | 78 | ciphertext_len = AES_CBC_encrypt(plaintext, ciphertext, plaintext_len, key, 16, iv); 79 | printf("key:\n"); 80 | print_hex(key, 16); 81 | printf("iv:\n"); 82 | print_hex(iv, 16); 83 | 84 | printf("plaintext: %lu bytes\n%s\n", plaintext_len, plaintext); 85 | printf("ciphertext: %lu bytes\n", ciphertext_len); 86 | print_hex(ciphertext, ciphertext_len); 87 | 88 | AES_CBC_decrypt(ciphertext, decrypted, plaintext_len, key, 16, iv); 89 | printf("decrypted:\n%s\n", decrypted); 90 | } 91 | 92 | void aes_cmac_test() 93 | { 94 | uint8_t key[16] = "secretkey"; 95 | uint8_t mac[16]; 96 | uint8_t *input = teststring; 97 | 98 | puts("\n*********AES-CMAC**********"); 99 | aes_cmac(input, strlen(input), key, mac); 100 | printf("message:\n%s\n", input); 101 | printf("key: %s\n", key); 102 | printf("CMAC result:\n"); 103 | print_hex(mac, 16); 104 | } 105 | 106 | int main() 107 | { 108 | aes_128_test(); 109 | // aes_256_test(); 110 | aes_128_cbc_test(); 111 | aes_cmac_test(); 112 | } 113 | -------------------------------------------------------------------------------- /aes_cmac.c: -------------------------------------------------------------------------------- 1 | #include "aes.h" 2 | #include "aes_cmac.h" 3 | #include 4 | #include 5 | #include 6 | 7 | // #define DEBUG 8 | 9 | static void print_block(uint8_t *ptr); 10 | static void left_shift(uint8_t *dest, uint8_t *src); 11 | static void gen_subkey(aes_ctx_t *aes_ctx, uint8_t *key, uint8_t *subkey_1, uint8_t *subkey_2); 12 | static void block_xor_triple(uint8_t *a, uint8_t *b, uint8_t *c); 13 | static void add_padding(uint8_t *block, int len); 14 | 15 | void aes_cmac(uint8_t *input, unsigned long length, uint8_t *key, uint8_t *mac_value) 16 | { 17 | uint8_t subkey_1[AES_BLOCKSIZE]; 18 | uint8_t subkey_2[AES_BLOCKSIZE]; 19 | uint8_t previous_block_ciphertext[AES_BLOCKSIZE] = {}; 20 | uint8_t temp[AES_BLOCKSIZE]; 21 | unsigned long i; 22 | aes_ctx_t *aes_ctx; 23 | 24 | aes_ctx = AES_ctx_alloc(key, 16); 25 | 26 | gen_subkey(aes_ctx, key, subkey_1, subkey_2); 27 | 28 | for(i = 0; i < length; i+= AES_BLOCKSIZE) 29 | { 30 | 31 | #ifdef DEBUG 32 | printf("Position %lx\n", i); 33 | printf("M:\n"); 34 | print_block(input); 35 | printf("IV:\n"); 36 | print_block(previous_block_ciphertext); 37 | #endif 38 | block_xor_triple(input, previous_block_ciphertext, temp); 39 | 40 | #ifdef DEBUG 41 | printf("xored with IV:\n"); 42 | print_block(temp); 43 | #endif 44 | 45 | if(i + AES_BLOCKSIZE == length) 46 | { 47 | //the last block if full, xor with subkey_1 48 | block_xor_triple(temp, subkey_1, temp); 49 | } 50 | else if(i + AES_BLOCKSIZE > length) 51 | { 52 | //last block is not full, add padding 53 | add_padding(temp, length - i); 54 | block_xor_triple(temp, subkey_2, temp); 55 | } 56 | 57 | #ifdef DEBUG 58 | printf("xored with key:\n"); 59 | print_block(temp); 60 | #endif 61 | 62 | AES_encrypt(aes_ctx, temp, previous_block_ciphertext); 63 | input += AES_BLOCKSIZE; 64 | } 65 | free(aes_ctx); 66 | memcpy(mac_value, previous_block_ciphertext, AES_BLOCKSIZE); 67 | } 68 | 69 | //put 0x80, 0x00, 0x00 after the first len bytes of block 70 | static void add_padding(uint8_t *block, int len) 71 | { 72 | int i; 73 | for(i = len; i < AES_BLOCKSIZE; i++) 74 | block[i] = 0; 75 | block[len] = 0x80; 76 | } 77 | 78 | static void block_xor_triple(uint8_t *a, uint8_t *b, uint8_t *c) 79 | { 80 | int i; 81 | for(i = 0; i < AES_BLOCKSIZE; i++) 82 | c[i] = a[i] ^ b[i]; 83 | } 84 | 85 | static void gen_subkey(aes_ctx_t *aes_ctx, uint8_t *key, uint8_t *subkey_1, uint8_t *subkey_2) 86 | { 87 | uint8_t zeros[16] = {}; 88 | uint8_t L[16]; 89 | 90 | AES_encrypt(aes_ctx, zeros, L); 91 | 92 | left_shift(subkey_1, L); 93 | if(L[0] & 0x80) 94 | subkey_1[15] ^= 0x87; 95 | 96 | left_shift(subkey_2, subkey_1); 97 | if(subkey_1[0] & 0x80) 98 | subkey_2[15] ^= 0x87; 99 | 100 | #ifdef DEBUG 101 | puts("K1:"); 102 | print_block(subkey_1); 103 | puts("K2:"); 104 | print_block(subkey_2); 105 | #endif 106 | } 107 | 108 | static void left_shift(uint8_t *dest, uint8_t *src) 109 | { 110 | int i; 111 | uint8_t overflow = 0; 112 | 113 | // print_block(src); 114 | for(i = 15; i >= 0; i--) 115 | { 116 | dest[i] = src[i] << 1; 117 | dest[i] |= overflow; 118 | overflow = (src[i] >> 7) & 1; 119 | } 120 | // print_block(dest); 121 | } 122 | 123 | static void print_block(uint8_t *ptr) 124 | { 125 | int i; 126 | for(i = 0; i < 16; i++) 127 | printf("%2.2x ", ptr[i]); 128 | printf("\n"); 129 | } 130 | -------------------------------------------------------------------------------- /aes_cmac.h: -------------------------------------------------------------------------------- 1 | #ifndef __AES_CMAC_H__ 2 | #define __AES_CMAC_H__ 3 | 4 | #include 5 | #include 6 | 7 | void aes_cmac(uint8_t *input, unsigned long length, uint8_t *key, uint8_t *mac_value); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /bignum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Functions for handling math operations on big numbers 3 | * credits: https://github.com/pantaloons/RSA/blob/master/multiple.c 4 | * MIT License 5 | */ 6 | 7 | #include "bignum.h" 8 | 9 | //initial capacity for a bignum structure. 10 | #define BIGNUM_DEFAULT_CAPACITY 20 11 | #define RADIX 4294967296UL 12 | #define HALFRADIX 2147483648UL 13 | 14 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) 15 | #define MIN(a,b) ((a) > (b) ? (b) : (a)) 16 | 17 | //some constants 18 | static uint32_t DATA0[1] = {0}; 19 | static uint32_t DATA1[1] = {1}; 20 | static uint32_t DATA2[1] = {2}; 21 | static uint32_t DATA3[1] = {3}; 22 | static uint32_t DATA4[1] = {4}; 23 | static uint32_t DATA5[1] = {5}; 24 | static uint32_t DATA6[1] = {6}; 25 | static uint32_t DATA7[1] = {7}; 26 | static uint32_t DATA8[1] = {8}; 27 | static uint32_t DATA9[1] = {9}; 28 | static uint32_t DATA10[1] = {10}; 29 | 30 | bignum NUMS[11] = {{1, 1, DATA0},{1, 1, DATA1},{1, 1, DATA2}, 31 | {1, 1, DATA3},{1, 1, DATA4},{1, 1, DATA5}, 32 | {1, 1, DATA6},{1, 1, DATA7},{1, 1, DATA8}, 33 | {1, 1, DATA9},{1, 1, DATA10}}; 34 | 35 | //allocate memory and initialize a bignum, return a pointer 36 | bignum * bignum_alloc() 37 | { 38 | bignum* b = malloc(sizeof(bignum)); 39 | b->length = 0; 40 | b->capacity = BIGNUM_DEFAULT_CAPACITY; 41 | b->data = calloc(BIGNUM_DEFAULT_CAPACITY, sizeof(uint32_t)); 42 | return b; 43 | } 44 | 45 | //Free memory used by a bignum. 46 | void bignum_free(bignum* b) 47 | { 48 | free(b->data); 49 | free(b); 50 | } 51 | 52 | int bignum_iszero(bignum* b) 53 | { 54 | return b->length == 0 || (b->length == 1 && b->data[0] == 0); 55 | } 56 | 57 | int bignum_isodd(bignum *b) 58 | { 59 | if (b->length == 0) 60 | return 0; 61 | return (b->data[0] & 1); 62 | } 63 | 64 | int bignum_isequal(bignum* b1, bignum* b2) 65 | { 66 | int i; 67 | if(bignum_iszero(b1) && bignum_iszero(b2)) return 1; 68 | else if(bignum_iszero(b1)) return 0; 69 | else if(bignum_iszero(b2)) return 0; 70 | else if(b1->length != b2->length) return 0; 71 | for(i = 0; i < b1->length; i ++) 72 | if(b1->data[i] != b2->data[i]) 73 | return 0; 74 | return 1; 75 | } 76 | 77 | int bignum_isgreater(bignum* b1, bignum* b2) 78 | { 79 | int i; 80 | if(bignum_iszero(b1) && bignum_iszero(b2)) return 0; 81 | else if(bignum_iszero(b1)) return 0; 82 | else if(bignum_iszero(b2)) return 1; 83 | else if(b1->length != b2->length) 84 | return b1->length > b2->length; 85 | for(i = b1->length - 1; i >= 0; i--) 86 | { 87 | if(b1->data[i] != b2->data[i]) 88 | return b1->data[i] > b2->data[i]; 89 | } 90 | return 0; 91 | } 92 | 93 | int bignum_isless(bignum* b1, bignum* b2) 94 | { 95 | int i; 96 | if(bignum_iszero(b1) && bignum_iszero(b2)) return 0; 97 | else if(bignum_iszero(b1)) return 1; 98 | else if(bignum_iszero(b2)) return 0; 99 | else if(b1->length != b2->length) 100 | return b1->length < b2->length; 101 | for(i = b1->length - 1; i >= 0; i--) 102 | { 103 | if(b1->data[i] != b2->data[i]) 104 | return b1->data[i] < b2->data[i]; 105 | } 106 | return 0; 107 | } 108 | 109 | int bignum_isgeq(bignum* b1, bignum* b2) 110 | { 111 | return !bignum_isless(b1, b2); 112 | } 113 | 114 | int bignum_isleq(bignum* b1, bignum* b2) 115 | { 116 | return !bignum_isgreater(b1, b2); 117 | } 118 | 119 | //generate a random number of given bytes 120 | void bignum_random(int bytes, bignum *result) 121 | { 122 | int i; 123 | result->length = bytes / 4; 124 | if(result->capacity < bytes / 4) 125 | { 126 | result->capacity = bytes / 4; 127 | result->data = realloc(result->data, sizeof(uint32_t) * result->capacity); 128 | } 129 | for(i = 0; i < bytes/4; i++) 130 | { 131 | result->data[i] = rand(); 132 | } 133 | } 134 | 135 | //add two bignums in place 136 | void bignum_iadd(bignum* source, bignum* add) 137 | { 138 | bignum* temp = bignum_alloc(); 139 | bignum_add(temp, source, add); 140 | bignum_copy(temp, source); 141 | bignum_free(temp); 142 | } 143 | 144 | //source += 2 145 | void bignum_iadd_2(bignum* source) 146 | { 147 | bignum_iadd(source, &NUMS[2]); 148 | } 149 | 150 | //result = b1 + b2 151 | void bignum_add(bignum* result, bignum* b1, bignum* b2) { 152 | uint32_t sum, carry = 0; 153 | int i; 154 | int n = MAX(b1->length, b2->length); 155 | if(n + 1 > result->capacity) 156 | { 157 | result->capacity = n + 1; 158 | result->data = realloc(result->data, result->capacity * sizeof(uint32_t)); 159 | } 160 | for(i = 0; i < n; i++) 161 | { 162 | sum = carry; 163 | if(i < b1->length) sum += b1->data[i]; 164 | if(i < b2->length) sum += b2->data[i]; 165 | result->data[i] = sum; /* Already taken mod 2^32 by unsigned wrap around */ 166 | 167 | if(i < b1->length) 168 | { 169 | if(sum < b1->data[i]) 170 | carry = 1; /* Result must have wrapped 2^32 */ 171 | else 172 | carry = 0; 173 | } 174 | else 175 | { 176 | if(sum < b2->data[i]) 177 | carry = 1; /* Result must have wrapped 2^32 */ 178 | else 179 | carry = 0; 180 | } 181 | } 182 | if(carry == 1) 183 | { 184 | result->length = n + 1; 185 | result->data[n] = 1; 186 | } 187 | else 188 | result->length = n; 189 | } 190 | 191 | //inplace substract 192 | void bignum_isubtract(bignum* source, bignum* sub) 193 | { 194 | bignum* temp = bignum_alloc(); 195 | bignum_subtract(temp, source, sub); 196 | bignum_copy(temp, source); 197 | bignum_free(temp); 198 | } 199 | 200 | //result = b1-b2 201 | void bignum_subtract(bignum* result, bignum* b1, bignum* b2) 202 | { 203 | int length, i; 204 | uint32_t carry, diff, temp; 205 | 206 | length = carry = 0; 207 | if(b1->length > result->capacity) 208 | { 209 | result->capacity = b1->length; 210 | result->data = realloc(result->data, result->capacity * sizeof(uint32_t)); 211 | } 212 | 213 | for(i = 0; i < b1->length; i++) 214 | { 215 | temp = carry; 216 | if(i < b2->length) 217 | temp = temp + b2->data[i]; /* Auto wrapped mod RADIX */ 218 | diff = b1->data[i] - temp; 219 | if(temp > b1->data[i]) 220 | carry = 1; 221 | else 222 | carry = 0; 223 | result->data[i] = diff; 224 | if(result->data[i] != 0) 225 | length = i + 1; 226 | } 227 | result->length = length; 228 | } 229 | 230 | void bignum_imultiply(bignum* source, bignum* mult) 231 | { 232 | bignum* temp = bignum_alloc(); 233 | bignum_multiply(temp, source, mult); 234 | bignum_copy(temp, source); 235 | bignum_free(temp); 236 | } 237 | 238 | void bignum_multiply(bignum* result, bignum* b1, bignum* b2) 239 | { 240 | int i, j, k; 241 | uint32_t carry, temp; 242 | uint64_t prod; //intermediate product 243 | if(b1->length + b2->length > result->capacity) 244 | { 245 | result->capacity = b1->length + b2->length; 246 | result->data = realloc(result->data, result->capacity * sizeof(uint32_t)); 247 | } 248 | for(i = 0; i < b1->length + b2->length; i++) 249 | result->data[i] = 0; 250 | 251 | for(i = 0; i < b1->length; i++) 252 | { 253 | for(j = 0; j < b2->length; j++) 254 | { 255 | prod = (b1->data[i] * (uint64_t)b2->data[j]) + (uint64_t)(result->data[i+j]); 256 | carry = (uint32_t)(prod / RADIX); 257 | 258 | /* Add carry to the next uint32_t over, but this may cause further overflow.. propogate */ 259 | k = 1; 260 | while(carry > 0) 261 | { 262 | temp = result->data[i+j+k] + carry; 263 | if(temp < result->data[i+j+k]) carry = 1; 264 | else carry = 0; 265 | result->data[i+j+k] = temp; /* Already wrapped in unsigned arithmetic */ 266 | k++; 267 | } 268 | 269 | prod = (result->data[i+j] + b1->data[i] * (uint64_t)b2->data[j]) % RADIX; /* Again, should not overflow... */ 270 | result->data[i+j] = prod; /* Add */ 271 | } 272 | } 273 | if(b1->length + b2->length > 0 && result->data[b1->length + b2->length - 1] == 0) 274 | result->length = b1->length + b2->length - 1; 275 | else 276 | result->length = b1->length + b2->length; 277 | } 278 | 279 | //source = source / div 280 | void bignum_idivide(bignum *source, bignum *div) 281 | { 282 | bignum *q = bignum_alloc(); 283 | bignum *r = bignum_alloc(); 284 | bignum_divide(q, r, source, div); 285 | bignum_copy(q, source); 286 | bignum_free(q); 287 | bignum_free(r); 288 | } 289 | 290 | //source /= 2 291 | void bignum_idivide_2(bignum *source) 292 | { 293 | bignum_idivide(source, &NUMS[2]); 294 | } 295 | 296 | 297 | //remainder = source % div 298 | void bignum_mod(bignum* source, bignum *div, bignum* remainder) 299 | { 300 | bignum *q = bignum_alloc(); 301 | bignum_divide(q, remainder, source, div); 302 | bignum_free(q); 303 | } 304 | 305 | //source = source/div. remainder = source - source/div 306 | void bignum_idivider(bignum* source, bignum* div, bignum* rem) 307 | { 308 | bignum *q = bignum_alloc(); 309 | bignum_divide(q, rem, source, div); 310 | bignum_copy(q, source); 311 | bignum_free(q); 312 | } 313 | 314 | //source = source % modulus 315 | void bignum_imod(bignum* source, bignum* modulus) { 316 | bignum *q = bignum_alloc(); 317 | bignum *r = bignum_alloc(); 318 | bignum_divide(q, r, source, modulus); 319 | bignum_copy(r, source); 320 | bignum_free(q); 321 | bignum_free(r); 322 | } 323 | 324 | //quotient = b1 // b2 325 | //remainder = b1 % b2 326 | void bignum_divide(bignum* quotient, bignum* remainder, bignum* b1, bignum* b2) { 327 | bignum *b2copy = bignum_alloc(), *b1copy = bignum_alloc(); 328 | bignum *temp = bignum_alloc(), *temp2 = bignum_alloc(), *temp3 = bignum_alloc(); 329 | bignum* quottemp = bignum_alloc(); 330 | uint32_t carry = 0; 331 | uint64_t factor = 1; 332 | uint64_t gquot, gtemp, grem; 333 | int n, m, i, j, length = 0; 334 | 335 | if(bignum_isless(b1, b2)) { /* Trivial case, b1/b2 = 0 iff b1 < b2. */ 336 | quotient->length = 0; 337 | bignum_copy(b1, remainder); 338 | } 339 | else if(bignum_iszero(b1)) { /* 0/x = 0.. assuming b2 is nonzero */ 340 | quotient->length = 0; 341 | bignum_fromint(remainder, 0); 342 | } 343 | else if(b2->length == 1) { /* Division by a single limb means we can do simple division */ 344 | if(quotient->capacity < b1->length) { 345 | quotient->capacity = b1->length; 346 | quotient->data = realloc(quotient->data, quotient->capacity * sizeof(uint32_t)); 347 | } 348 | for(i = b1->length - 1; i >= 0; i--) { 349 | gtemp = carry * RADIX + b1->data[i]; 350 | gquot = gtemp / b2->data[0]; 351 | quotient->data[i] = gquot; 352 | if(quotient->data[i] != 0 && length == 0) length = i + 1; 353 | carry = gtemp % b2->data[0]; 354 | } 355 | bignum_fromint(remainder, carry); 356 | quotient->length = length; 357 | } 358 | else 359 | { /* do long division */ 360 | n = b1->length + 1; 361 | m = b2->length; 362 | if(quotient->capacity < n - m) { 363 | quotient->capacity = n - m; 364 | quotient->data = realloc(quotient->data, (n - m) * sizeof(uint32_t)); 365 | } 366 | bignum_copy(b1, b1copy); 367 | bignum_copy(b2, b2copy); 368 | /* Normalize.. multiply by the divisor by 2 until MSB >= HALFRADIX. This ensures fast 369 | * convergence when guessing the quotient below. We also multiply the dividend by the 370 | * same amount to ensure the result does not change. */ 371 | while(b2copy->data[b2copy->length - 1] < HALFRADIX) 372 | { 373 | factor *= 2; 374 | bignum_imultiply(b2copy, &NUMS[2]); 375 | } 376 | if(factor > 1) 377 | { 378 | bignum_fromint(temp, factor); 379 | bignum_imultiply(b1copy, temp); 380 | } 381 | /* Ensure the dividend is longer than the original (pre-normalized) divisor. If it is not 382 | * we introduce a dummy zero uint32_t to artificially inflate it. */ 383 | if(b1copy->length != n) 384 | { 385 | b1copy->length++; 386 | if(b1copy->length > b1copy->capacity) { 387 | b1copy->capacity = b1copy->length; 388 | b1copy->data = realloc(b1copy->data, b1copy->capacity * sizeof(uint32_t)); 389 | } 390 | b1copy->data[n - 1] = 0; 391 | } 392 | 393 | /* Process quotient by long division */ 394 | for(i = n - m - 1; i >= 0; i--) 395 | { 396 | gtemp = RADIX * b1copy->data[i + m] + b1copy->data[i + m - 1]; 397 | gquot = gtemp / b2copy->data[m - 1]; 398 | if(gquot >= RADIX) gquot = UINT_MAX; 399 | grem = gtemp % b2copy->data[m - 1]; 400 | while(grem < RADIX && gquot * b2copy->data[m - 2] > RADIX * grem + b1copy->data[i + m - 2]) 401 | { /* Should not overflow... ? */ 402 | gquot--; 403 | grem += b2copy->data[m - 1]; 404 | } 405 | quottemp->data[0] = gquot % RADIX; 406 | quottemp->data[1] = (gquot / RADIX); 407 | if(quottemp->data[1] != 0) 408 | quottemp->length = 2; 409 | else 410 | quottemp->length = 1; 411 | 412 | bignum_multiply(temp2, b2copy, quottemp); 413 | if(m + 1 > temp3->capacity) 414 | { 415 | temp3->capacity = m + 1; 416 | temp3->data = realloc(temp3->data, temp3->capacity * sizeof(uint32_t)); 417 | } 418 | temp3->length = 0; 419 | for(j = 0; j <= m; j++) 420 | { 421 | temp3->data[j] = b1copy->data[i + j]; 422 | if(temp3->data[j] != 0) temp3->length = j + 1; 423 | } 424 | if(bignum_isless(temp3, temp2)) { 425 | bignum_iadd(temp3, b2copy); 426 | gquot--; 427 | } 428 | 429 | bignum_isubtract(temp3, temp2); 430 | for(j = 0; j < temp3->length; j++) 431 | b1copy->data[i + j] = temp3->data[j]; 432 | for(j = temp3->length; j <= m; j++) 433 | b1copy->data[i + j] = 0; 434 | quotient->data[i] = gquot; 435 | if(quotient->data[i] != 0) 436 | quotient->length = i; 437 | } 438 | 439 | if(quotient->data[b1->length - b2->length] == 0) 440 | quotient->length = b1->length - b2->length; 441 | else 442 | quotient->length = b1->length - b2->length + 1; 443 | 444 | /* Divide by factor now to find final remainder */ 445 | carry = 0; 446 | for(i = b1copy->length - 1; i >= 0; i--) 447 | { 448 | gtemp = carry * RADIX + b1copy->data[i]; 449 | b1copy->data[i] = gtemp/factor; 450 | if(b1copy->data[i] != 0 && length == 0) 451 | length = i + 1; 452 | carry = gtemp % factor; 453 | } 454 | b1copy->length = length; 455 | bignum_copy(b1copy, remainder); 456 | } 457 | bignum_free(temp); 458 | bignum_free(temp2); 459 | bignum_free(temp3); 460 | bignum_free(b1copy); 461 | bignum_free(b2copy); 462 | bignum_free(quottemp); 463 | } 464 | 465 | //dest = source 466 | void bignum_copy(bignum* source, bignum* dest) 467 | { 468 | dest->length = source->length; 469 | if(source->capacity > dest->capacity) 470 | { 471 | dest->capacity = source->capacity; 472 | dest->data = realloc(dest->data, dest->capacity * sizeof(uint32_t)); 473 | } 474 | memcpy(dest->data, source->data, dest->length * sizeof(uint32_t)); 475 | } 476 | 477 | //b = 0 478 | void bignum_set_zero(bignum *b) 479 | { 480 | int i; 481 | for(i = 0; i < b->length; i++) 482 | b->data[i] = 0; 483 | b->length = 0; 484 | } 485 | 486 | //load a bignum from an unsigned integer. 487 | void bignum_fromint(bignum* b, uint32_t num) 488 | { 489 | bignum_set_zero(b); 490 | b->length = 1; 491 | if(b->capacity < 1) 492 | { 493 | b->capacity = 1; 494 | b->data = realloc(b->data, sizeof(uint32_t)); 495 | } 496 | b->data[0] = num; 497 | } 498 | 499 | //load bignum from a string ended with '\0' 500 | void bignum_fromstring(bignum* b, char* string) 501 | { 502 | int i, len = 0; 503 | len = strlen(string); 504 | bignum_set_zero(b); 505 | for(i = 0; i < len; i++) 506 | { 507 | if(i != 0) 508 | bignum_imultiply(b, &NUMS[10]); 509 | bignum_iadd(b, &NUMS[string[i] - '0']); 510 | } 511 | } 512 | 513 | //convert bignum to a string 514 | char * bignum_tostring(bignum* b) 515 | { 516 | int cap = 100; 517 | int len = 0; 518 | int i; 519 | char* buffer; 520 | bignum *copy; 521 | bignum *remainder; 522 | 523 | uint32_t tmp; 524 | 525 | buffer = malloc(cap * sizeof(char)); 526 | if(bignum_iszero(b)) 527 | { 528 | buffer[0] = '0'; 529 | buffer[1] = '\0'; 530 | } 531 | else 532 | { 533 | copy = bignum_alloc(); 534 | remainder = bignum_alloc(); 535 | 536 | bignum_copy(b, copy); 537 | while(!bignum_iszero(copy)) 538 | { 539 | bignum_idivider(copy, &NUMS[10], remainder); 540 | buffer[len++] = remainder->data[0] + '0'; 541 | if(len >= cap) 542 | { 543 | cap *= 2; 544 | buffer = realloc(buffer, cap * sizeof(char)); 545 | } 546 | } 547 | //flip around 548 | for(i = 0; i < (len / 2); i++) 549 | { 550 | tmp = buffer[i]; 551 | buffer[i] = buffer[len - i - 1]; 552 | buffer[len - i - 1] = tmp; 553 | } 554 | buffer[len] = '\0'; 555 | bignum_free(copy); 556 | bignum_free(remainder); 557 | } 558 | return buffer; 559 | } 560 | -------------------------------------------------------------------------------- /bignum.h: -------------------------------------------------------------------------------- 1 | #ifndef __BIGNUM_H__ 2 | #define __BIGNUM_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct 11 | { 12 | int length; 13 | int capacity; 14 | uint32_t * data; //data[0] is LSB, memory allocated at runtime 15 | } bignum; 16 | 17 | bignum * bignum_alloc(); 18 | void bignum_free(bignum *b); 19 | 20 | void bignum_set_zero(bignum *b); 21 | void bignum_fromint(bignum* b, uint32_t num); 22 | void bignum_fromstring(bignum* b, char* string); 23 | char * bignum_tostring(bignum* b); 24 | void bignum_copy(bignum* source, bignum* dest); 25 | 26 | void bignum_random(int bytes, bignum *result); 27 | 28 | //compare & testing 29 | int bignum_iszero(bignum* b); 30 | int bignum_isodd(bignum *b); 31 | int bignum_isequal(bignum* b1, bignum* b2); 32 | int bignum_isgreater(bignum* b1, bignum* b2); 33 | int bignum_isless(bignum* b1, bignum* b2); 34 | int bignum_isgeq(bignum* b1, bignum* b2); 35 | int bignum_isleq(bignum* b1, bignum* b2); 36 | 37 | //math operations 38 | void bignum_iadd(bignum* source, bignum* add); 39 | void bignum_iadd_2(bignum* source); 40 | void bignum_add(bignum* result, bignum* b1, bignum* b2); 41 | void bignum_isubtract(bignum* source, bignum* add); 42 | void bignum_subtract(bignum* result, bignum* b1, bignum* b2); 43 | void bignum_imultiply(bignum* source, bignum* add); 44 | void bignum_multiply(bignum* result, bignum* b1, bignum* b2); 45 | void bignum_idivide(bignum* source, bignum* div); 46 | void bignum_idivide_2(bignum *source); 47 | // void bignum_idivider(bignum* source, bignum* div, bignum* remainder); 48 | void bignum_mod(bignum* source, bignum *div, bignum* remainder); 49 | void bignum_imod(bignum* source, bignum* modulus); 50 | void bignum_divide(bignum* quotient, bignum* remainder, bignum* b1, bignum* b2); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /bignum_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "bignum.h" 5 | 6 | char *stra = "1221323213871983878"; 7 | char *strb = "9821231821382178271832173765453"; 8 | 9 | int main() 10 | { 11 | bignum *a, *b, *c, *d, *e; 12 | char *resulta, *resultb; 13 | a = bignum_alloc(); 14 | b = bignum_alloc(); 15 | c = bignum_alloc(); 16 | d = bignum_alloc(); 17 | e = bignum_alloc(); 18 | 19 | bignum_fromstring(a, stra); 20 | bignum_fromstring(b, strb); 21 | resulta = bignum_tostring(a); 22 | resultb = bignum_tostring(b); 23 | puts(resultb); 24 | puts(resulta); 25 | free(resulta); 26 | free(resultb); 27 | 28 | bignum_multiply(c, a, b); 29 | puts(bignum_tostring(c)); 30 | 31 | bignum_subtract(c, a, b); 32 | puts(bignum_tostring(c)); 33 | 34 | bignum_divide(d, e, a, b); 35 | 36 | printf("quotient=%s\n", bignum_tostring(d)); 37 | printf("remainder=%s\n", bignum_tostring(e)); 38 | 39 | bignum_free(a); 40 | bignum_free(b); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /hmac.c: -------------------------------------------------------------------------------- 1 | #include "sha256.h" 2 | #include 3 | 4 | 5 | void hmac_sha256(uint8_t *data, unsigned long length, uint8_t *key, unsigned int keylen, uint8_t *mac_value) 6 | { 7 | uint8_t ikey[SHA256_BLOCK_SIZE], okey[SHA256_BLOCK_SIZE]; 8 | uint8_t hash[SHA256_HASH_LEN]; 9 | sha256_ctx_t ctx; 10 | int i; 11 | 12 | if(keylen <= SHA256_BLOCK_SIZE) 13 | { 14 | memset(ikey, 0, SHA256_BLOCK_SIZE); 15 | memset(okey, 0, SHA256_BLOCK_SIZE); 16 | memcpy(ikey, key, keylen); 17 | memcpy(okey, key, keylen); 18 | } 19 | else 20 | { 21 | sha256_init(&ctx); 22 | sha256_update(&ctx, key, keylen); 23 | sha256_finish(&ctx, ikey); 24 | memcpy(okey, ikey, SHA256_BLOCK_SIZE); 25 | } 26 | 27 | for(i = 0; i < SHA256_BLOCK_SIZE; i++) 28 | { 29 | ikey[i] = ikey[i] ^ 0x36; 30 | okey[i] = okey[i] ^ 0x5c; 31 | } 32 | 33 | sha256_init(&ctx); 34 | sha256_update(&ctx, ikey, SHA256_BLOCK_SIZE); 35 | sha256_update(&ctx, data, length); 36 | sha256_finish(&ctx, hash); 37 | 38 | sha256_init(&ctx); 39 | sha256_update(&ctx, okey, SHA256_BLOCK_SIZE); 40 | sha256_update(&ctx, hash, SHA256_HASH_LEN); 41 | sha256_finish(&ctx, mac_value); 42 | } 43 | -------------------------------------------------------------------------------- /hmac.h: -------------------------------------------------------------------------------- 1 | #ifndef __HMAC_H__ 2 | #define __HMAC_H__ 3 | 4 | 5 | void hmac_sha256(uint8_t *data, unsigned long length, uint8_t *key, unsigned int keylen, uint8_t *mac_value); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /rsa.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "rsa.h" 9 | #include "bignum.h" 10 | 11 | #define PRIMALITY_TEST_REPEAT 100 12 | #define EXPONENT_MAX RAND_MAX 13 | 14 | static void gcd(bignum *b1, bignum *b2, bignum *result); 15 | static void random_exponent(bignum *phi, uint32_t upper, bignum *result); 16 | static void bignum_pow_mod(bignum *result, bignum *base, bignum *expo, bignum *mod); 17 | static int miller_rabin_test(bignum *n, int repeat); 18 | static void random_prime(int digits, bignum *result); 19 | void randPrime(int numDigits, bignum* result); 20 | 21 | 22 | static void print_bignum(char *s, bignum *b) 23 | { 24 | char *k; 25 | k = bignum_tostring(b); 26 | printf("%s = %s\n", s, k); 27 | free(k); 28 | } 29 | 30 | static void gcd(bignum *b1, bignum *b2, bignum *result) 31 | { 32 | bignum *a = bignum_alloc(), *b = bignum_alloc(); 33 | bignum *temp = bignum_alloc(); 34 | bignum_copy(b1, a); 35 | bignum_copy(b2, b); 36 | while(!bignum_iszero(b)) 37 | { 38 | bignum_copy(b, temp); 39 | bignum_imod(a, b); 40 | bignum_copy(a, b); 41 | bignum_copy(temp, a); 42 | } 43 | bignum_copy(a, result); 44 | } 45 | 46 | /* 47 | void xgcd(bignum* a, bignum* mod, bignum* result) 48 | { 49 | bignum *remprev = bignum_alloc(), *rem = bignum_alloc(); 50 | bignum *auxprev = bignum_alloc(), *aux = bignum_alloc(); 51 | bignum *rcur = bignum_alloc(), *qcur = bignum_alloc(), *acur = bignum_alloc(); 52 | bignum *one = bignum_alloc(); 53 | bignum_fromint(one, 1); 54 | 55 | bignum_copy(mod, remprev); 56 | bignum_copy(a, rem); 57 | bignum_fromint(auxprev, 0); 58 | bignum_fromint(aux, 1); 59 | while(bignum_isgreater(rem, one)) 60 | { 61 | bignum_divide(qcur, rcur, remprev, rem); 62 | bignum_subtract(acur, mod, qcur); 63 | bignum_imultiply(acur, aux); 64 | bignum_iadd(acur, auxprev); 65 | bignum_imod(acur, mod); 66 | 67 | bignum_copy(rem, remprev); 68 | bignum_copy(aux, auxprev); 69 | bignum_copy(rcur, rem); 70 | bignum_copy(acur, aux); 71 | } 72 | 73 | bignum_copy(acur, result); 74 | 75 | bignum_free(remprev); bignum_free(rem); bignum_free(auxprev); 76 | bignum_free(aux); bignum_free(rcur); bignum_free(qcur); 77 | bignum_free(acur); bignum_free(one); 78 | } 79 | */ 80 | 81 | //modified extended Euclidean algorithm from Knuth [KNU298, Vol 2 Algorithm X p 342] 82 | //avoiding negative integers. 83 | void modular_inverse(bignum* a, bignum* mod, bignum* result) 84 | { 85 | bignum *u1 = bignum_alloc(); 86 | bignum *u3 = bignum_alloc(); 87 | bignum *v1 = bignum_alloc(); 88 | bignum *v3 = bignum_alloc(); 89 | bignum *t1 = bignum_alloc(); 90 | bignum *t3 = bignum_alloc(); 91 | bignum *q = bignum_alloc(); 92 | 93 | int iter=1; 94 | bignum_fromint(u1, 1); 95 | bignum_copy(a, u3); 96 | bignum_copy(mod, v3); 97 | 98 | while (!bignum_iszero(v3)) 99 | { 100 | bignum_divide(q, t3, u3, v3); 101 | bignum_imultiply(q, v1); 102 | bignum_add(t1, u1, q); 103 | 104 | bignum_copy(v1, u1); 105 | bignum_copy(t1, v1); 106 | bignum_copy(v3, u3); 107 | bignum_copy(t3, v3); 108 | 109 | iter = -iter; 110 | } 111 | if (iter < 0) 112 | bignum_subtract(result, mod, u1); 113 | else 114 | bignum_copy(u1, result); 115 | bignum_free(t1); 116 | bignum_free(u1); 117 | bignum_free(v1); 118 | bignum_free(v3); 119 | bignum_free(t3); 120 | bignum_free(u3); 121 | bignum_free(q); 122 | } 123 | 124 | 125 | //find result < upper such that gcd(result, phi)==1 126 | static void random_exponent(bignum *phi, uint32_t upper, bignum *result) 127 | { 128 | bignum* x = bignum_alloc(); 129 | uint32_t e; 130 | e = rand() % upper; 131 | while(1) 132 | { 133 | // printf("ee = %u\n", e); 134 | bignum_fromint(result, e); 135 | gcd(result, phi, x); 136 | // print_bignum("gcd", x); 137 | if(x->length == 1 && x->data[0] == 1) 138 | { 139 | //break when gcd==1 140 | break; 141 | } 142 | //try next number 143 | e = (e+1) % upper; 144 | if(e < 3) 145 | e = 3; 146 | } 147 | bignum_free(x); 148 | } 149 | 150 | //result = base^exp % mod 151 | static void bignum_pow_mod(bignum* result, bignum* base, bignum* expo, bignum* mod) 152 | { 153 | bignum *a = bignum_alloc(), *b = bignum_alloc(); 154 | bignum *tmp = bignum_alloc(); 155 | 156 | bignum_copy(base, a); 157 | bignum_copy(expo, b); 158 | bignum_fromint(result, 1); 159 | 160 | while(!bignum_iszero(b)) 161 | { 162 | if(b->data[0] & 1) 163 | { 164 | bignum_imultiply(result, a); 165 | bignum_imod(result, mod); 166 | } 167 | bignum_idivide_2(b); 168 | bignum_copy(a, tmp); 169 | bignum_imultiply(a, tmp); 170 | bignum_imod(a, mod); 171 | } 172 | bignum_free(a); 173 | bignum_free(b); 174 | bignum_free(tmp); 175 | } 176 | 177 | static int miller_rabin_test(bignum *n, int repeat) 178 | { 179 | bignum *n_1 = bignum_alloc(); 180 | bignum *a = bignum_alloc(); 181 | bignum *q = bignum_alloc(); 182 | bignum *one = bignum_alloc(); 183 | bignum *x = bignum_alloc(); 184 | uint32_t k = 0; 185 | uint32_t i; 186 | int result = 1; 187 | 188 | one->length = 1; 189 | one->data[0] = 1; 190 | 191 | bignum_subtract(n_1, n, one); 192 | bignum_copy(n_1, q); 193 | //n-1 = 2^k x q 194 | while(!bignum_isodd(q)) 195 | { 196 | bignum_idivide_2(q); 197 | k++; 198 | } 199 | 200 | while(repeat--) 201 | { 202 | bignum_random(10*n_1->length, a); 203 | bignum_imod(a, n_1); 204 | bignum_pow_mod(x, a, q, n); 205 | if (bignum_isequal(x, one)) 206 | continue; //a is not well chosen 207 | i = 0; 208 | while(!bignum_isequal(x, n_1)) 209 | { 210 | // printf("i=%u\n", i); 211 | if(i == (k-1)) 212 | { 213 | result = 0; 214 | goto test_done; 215 | } 216 | else 217 | { 218 | i++; 219 | bignum_imultiply(x, x); 220 | bignum_imod(x, n); 221 | } 222 | } 223 | } 224 | 225 | test_done: 226 | bignum_free(a); 227 | bignum_free(q); 228 | bignum_free(n_1); 229 | bignum_free(x); 230 | bignum_free(one); 231 | return result; 232 | } 233 | 234 | static void random_prime(int bytes, bignum *result) 235 | { 236 | bignum_random(bytes, result); 237 | if(!bignum_isodd(result)) 238 | result->data[0] += 1; 239 | while(1) 240 | { 241 | printf("."); 242 | fflush(stdout); 243 | if(miller_rabin_test(result, PRIMALITY_TEST_REPEAT)) 244 | break; 245 | bignum_iadd_2(result); 246 | } 247 | printf("\n"); 248 | } 249 | 250 | void rsa_generate_key_pair(char *ns, char *ds, char *es, char *phis, int bytes) 251 | { 252 | bignum *p, *q; 253 | bignum *n, *d, *e, *phi; 254 | bignum *one; 255 | char *buf; 256 | 257 | p = bignum_alloc(); 258 | q = bignum_alloc(); 259 | one = bignum_alloc(); 260 | n = bignum_alloc(); 261 | d = bignum_alloc(); 262 | e = bignum_alloc(); 263 | phi = bignum_alloc(); 264 | 265 | bignum_fromint(one, 1); 266 | random_prime(bytes, p); 267 | print_bignum("p", p); 268 | random_prime(bytes, q); 269 | print_bignum("q", q); 270 | 271 | bignum_multiply(n, p, q); 272 | bignum_isubtract(p, one); 273 | bignum_isubtract(q, one); 274 | bignum_multiply(phi, p, q); 275 | 276 | random_exponent(phi, EXPONENT_MAX, e); 277 | modular_inverse(e, phi, d); 278 | 279 | buf = bignum_tostring(n); 280 | strcpy(ns, buf); free(buf); 281 | buf = bignum_tostring(d); 282 | strcpy(ds, buf); free(buf); 283 | buf = bignum_tostring(e); 284 | strcpy(es, buf); free(buf); 285 | if(phis != NULL) 286 | { 287 | buf = bignum_tostring(phi); 288 | strcpy(phis, buf); free(buf); 289 | } 290 | bignum_free(p); bignum_free(n); bignum_free(d); 291 | bignum_free(q); bignum_free(e); bignum_free(phi); 292 | bignum_free(one); 293 | } 294 | 295 | void rsa_encrypt(char *result, char *plaintext, int bytes, char *modulus, char *exponent) 296 | { 297 | bignum *n, *e, *ct, *pt; 298 | char *s; 299 | 300 | n = bignum_alloc(); 301 | e = bignum_alloc(); 302 | ct = bignum_alloc(); 303 | pt = bignum_alloc(); 304 | 305 | //load n,e from string 306 | bignum_fromstring(n, modulus); 307 | bignum_fromstring(e, exponent); 308 | bignum_fromstring(pt, plaintext); 309 | 310 | bignum_pow_mod(ct, pt, e, n); 311 | s = bignum_tostring(ct); 312 | strcpy(result, s); 313 | free(s); 314 | 315 | //clean up 316 | bignum_free(ct); 317 | bignum_free(pt); 318 | bignum_free(e); 319 | bignum_free(n); 320 | } 321 | 322 | void rsa_decrypt(char *result, char *ciphertext, int bytes, char *n, char *exponent) 323 | { 324 | rsa_encrypt(result, ciphertext, bytes, n, exponent); 325 | } 326 | 327 | char * rsa_bin2dec(uint8_t *bin, int bytes) 328 | { 329 | int i; 330 | bignum *base256; 331 | bignum *tmp, *pt; 332 | bignum *num256; 333 | char *s; 334 | 335 | tmp = bignum_alloc(); 336 | base256 = bignum_alloc(); 337 | num256 = bignum_alloc(); 338 | pt = bignum_alloc(); 339 | 340 | bignum_fromint(base256, 1); 341 | bignum_fromint(num256, 256); 342 | 343 | for(i = 0; i < bytes; i++) 344 | { 345 | bignum_fromint(tmp, bin[i]); 346 | bignum_imultiply(tmp, base256); 347 | bignum_iadd(pt, tmp); 348 | bignum_imultiply(base256, num256); 349 | } 350 | 351 | s = bignum_tostring(pt); 352 | bignum_free(tmp); bignum_free(base256); 353 | bignum_free(num256); bignum_free(pt); 354 | 355 | return s; 356 | } 357 | 358 | /* 359 | void test1() 360 | { 361 | bignum *s; 362 | s = bignum_alloc(); 363 | random_prime(32, s); 364 | printf("%s\n", bignum_tostring(s)); 365 | printf("%d\n", miller_rabin_test(s, 30)); 366 | bignum_free(s); 367 | } 368 | */ 369 | 370 | /* 371 | int main() 372 | { 373 | bignum *a = bignum_alloc(); 374 | bignum *q = bignum_alloc(); 375 | bignum *inv = bignum_alloc(); 376 | bignum_fromstring(a, "5370702670177023357401198310401014925440001998254581061067882702546083975820467325803176536972583529046575157542254922963861667552601010631836478246909136859790891031240313975899931659373997627468479745588743233740231321214180408099897847114606064671860223946420243996731490198422261789694999790565839515281024770870764105086818848319762638885566100900975823570599688742835848176989452563188758222004735494633988600280094096160414100491691513358805586795182152183430254174163313220405487051847310519011871605356430320158997573187097059463514867880382134916538530386331818970560882451465000858533260840120529939745216"); 377 | bignum_fromint(q, 1331748509); 378 | modular_inverse(q, a, inv); 379 | print_bignum("inv", inv); 380 | return 0; 381 | } 382 | */ 383 | -------------------------------------------------------------------------------- /rsa.h: -------------------------------------------------------------------------------- 1 | #ifndef __RSA_H__ 2 | #define __RSA_H__ 3 | 4 | #include "bignum.h" 5 | 6 | void rsa_generate_key_pair(char *n, char *d, char *e, char *phi, int bytes); 7 | void rsa_encrypt(char *result, char *plaintext, int bytes, char *modulus, char *exponent); 8 | void rsa_decrypt(char *result, char *ciphertext, int bytes, char *modulus, char *exponent); 9 | char * rsa_bin2dec(uint8_t *bin, int len); 10 | #endif 11 | -------------------------------------------------------------------------------- /sha256.c: -------------------------------------------------------------------------------- 1 | #include "sha256.h" 2 | // #include "stdio.h" 3 | 4 | #define ROTR(x,n) (((x) >> n) | ((x) << (32 - n))) 5 | 6 | //round constants 7 | static const uint32_t K[64] = { 8 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 9 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 10 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 11 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 12 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 13 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 14 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 15 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 16 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 17 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 18 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 19 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 20 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 21 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 22 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 23 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 24 | }; 25 | 26 | static void compress(sha256_ctx_t *ctx); 27 | static void bit_len_add(sha256_ctx_t *ctx, uint32_t val); 28 | 29 | void sha256_init(sha256_ctx_t *ctx) 30 | { 31 | ctx->buf_len = 0; 32 | ctx->bit_len[0] = ctx->bit_len[1] = 0; 33 | ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85; 34 | ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a; 35 | ctx->state[4] = 0x510e527f; ctx->state[5] = 0x9b05688c; 36 | ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19; 37 | } 38 | 39 | void sha256_update(sha256_ctx_t *ctx, uint8_t *message, uint32_t len) 40 | { 41 | uint32_t i; 42 | for(i = 0; i < len;i ++) 43 | { 44 | ctx->buf[ctx->buf_len] = message[i]; 45 | ctx->buf_len++; 46 | if(ctx->buf_len == SHA256_BLOCK_SIZE) //a chunk is ready 47 | { 48 | compress(ctx); 49 | bit_len_add(ctx, SHA256_BLOCK_SIZE * 8); 50 | ctx->buf_len = 0; 51 | } 52 | } 53 | } 54 | 55 | void sha256_finish(sha256_ctx_t *ctx, uint8_t *hash) 56 | { 57 | register uint32_t i; 58 | i = ctx->buf_len; 59 | 60 | //add padding 1000... 61 | if(i < 56) 62 | { 63 | ctx->buf[i++] = 0x80; 64 | while(i < 56) 65 | ctx->buf[i++] = 0; 66 | } 67 | else 68 | { 69 | ctx->buf[i++] = 0x80; 70 | while(i < 64) 71 | ctx->buf[i++] = 0; 72 | compress(ctx); 73 | memset(ctx->buf, 0, 56); 74 | } 75 | 76 | //append total lenth in bits to message 77 | bit_len_add(ctx, ctx->buf_len * 8); 78 | 79 | //add to buf, Big Endian 80 | for (i = 0; i < 4; i++) 81 | { 82 | ctx->buf[63-i] = ctx->bit_len[0] >> (i*8); 83 | ctx->buf[59-i] = ctx->bit_len[1] >> (i*8); 84 | } 85 | compress(ctx); 86 | 87 | //convert to Big-Endian and output 88 | for (i = 0; i < 32; i++) 89 | { 90 | hash[i] = (ctx->state[i/4] >> (24 - 8*(i%4))) & 0x000000ff; 91 | } 92 | } 93 | 94 | static void bit_len_add(sha256_ctx_t *ctx, uint32_t val) 95 | { 96 | if (ctx->bit_len[0] > 0xffffffff - val) 97 | ctx->bit_len[1]++; 98 | ctx->bit_len[0] += val; 99 | } 100 | 101 | static void compress(sha256_ctx_t *ctx) 102 | { 103 | uint32_t b[8]; 104 | uint32_t w[64]; //message schedule array 105 | uint32_t t1, t2, s0, s1; 106 | int i, j; 107 | 108 | for(i = 0; i < 8; i++) 109 | { 110 | b[i] = ctx->state[i]; 111 | // printf("b[%d] = %x\n", i, b[i]); 112 | } 113 | 114 | //copy chunk into first 16 words of the message schedule array 115 | for (i = j = 0; i < 16; i++, j+=4) 116 | { 117 | w[i] = (ctx->buf[j] << 24) | (ctx->buf[j+1] << 16) | (ctx->buf[j+2] << 8) | (ctx->buf[j+3]); 118 | } 119 | 120 | //extend W array 121 | for(i = 16; i < 64; i++) 122 | { 123 | t1 = ROTR(w[i-15], 7) ^ ROTR(w[i-15], 18) ^ (w[i-15] >> 3); 124 | t2 = ROTR(w[i-2], 17) ^ ROTR(w[i-2], 19) ^ (w[i-2] >> 10); 125 | w[i] = w[i-16] + t1 + w[i-7] + t2; 126 | } 127 | 128 | //main loop 129 | for(i = 0; i < 64; i++) 130 | { 131 | s1 = ROTR(b[4], 6) ^ ROTR(b[4], 11) ^ ROTR(b[4], 25); 132 | t1 = b[7] + s1 + K[i] + w[i] + ((b[4] & b[5]) ^ ((~b[4]) & b[6])); 133 | s0 = ROTR(b[0], 2) ^ ROTR(b[0], 13) ^ ROTR(b[0], 22); 134 | t2 = s0 + ((b[0] & b[1]) ^ (b[0] & b[2]) ^ (b[1] & b[2])); 135 | 136 | b[7] = b[6]; 137 | b[6] = b[5]; 138 | b[5] = b[4]; 139 | b[4] = b[3] + t1; 140 | b[3] = b[2]; 141 | b[2] = b[1]; 142 | b[1] = b[0]; 143 | b[0] = t1 + t2; 144 | } 145 | 146 | // printf("%x\t%x\t%x\t%x\n", b[0], b[1], b[2], b[3]); 147 | // printf("%x\t%x\t%x\t%x\n", b[4], b[5], b[6], b[7]); 148 | 149 | for(i = 0; i < 8; i++) 150 | ctx->state[i] += b[i]; 151 | } 152 | -------------------------------------------------------------------------------- /sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef __SHA256_H__ 2 | #define __SHA256_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define SHA256_BLOCK_SIZE 64 9 | #define SHA256_HASH_LEN 32 10 | 11 | typedef struct { 12 | uint8_t buf[64]; //512bit chunks 13 | uint32_t state[8]; //256bit hash value 14 | uint32_t buf_len; //bytes in buf 15 | uint32_t bit_len[2]; //total length in bits 16 | } sha256_ctx_t; 17 | 18 | void sha256_init(sha256_ctx_t *ctx); 19 | void sha256_update(sha256_ctx_t *ctx, uint8_t *message, uint32_t len); 20 | void sha256_finish(sha256_ctx_t *ctx, uint8_t *hash); 21 | 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /sign.c: -------------------------------------------------------------------------------- 1 | #include "sha256.h" 2 | #include "rsa.h" 3 | 4 | #define MAX_SIGNATURE_LEN 2048 5 | 6 | char * sign(char *message, int len, char *n, char *d) 7 | { 8 | uint8_t hash[SHA256_HASH_LEN]; 9 | char *dec_hash, *signature; 10 | sha256_ctx_t ctx; 11 | sha256_init(&ctx); 12 | 13 | signature = malloc(MAX_SIGNATURE_LEN); 14 | 15 | sha256_update(&ctx, message, len); 16 | sha256_finish(&ctx, hash); 17 | 18 | dec_hash = rsa_bin2dec(hash, SHA256_HASH_LEN); 19 | printf("Hash value (in dec):\n%s\n", dec_hash); 20 | rsa_encrypt(signature, dec_hash, strlen(dec_hash), n, d); 21 | free(dec_hash); 22 | printf("Signature result:\n%s\n", signature); 23 | return signature; 24 | } 25 | 26 | int verify(char *message, int len, char *n, char *e, char *signature) 27 | { 28 | uint8_t hash[SHA256_HASH_LEN]; 29 | char your_hash[MAX_SIGNATURE_LEN], *my_hash; 30 | int match; 31 | 32 | sha256_ctx_t ctx; 33 | sha256_init(&ctx); 34 | sha256_update(&ctx, message, len); 35 | sha256_finish(&ctx, hash); 36 | my_hash = rsa_bin2dec(hash, SHA256_HASH_LEN); 37 | 38 | rsa_encrypt(your_hash, signature, strlen(signature), n, e); 39 | printf("Decrypted Hash value:\n%s\n", your_hash); 40 | if(strcmp(my_hash, your_hash) == 0) 41 | match = 1; 42 | else 43 | match = 0; 44 | free(my_hash); 45 | return match; 46 | } 47 | -------------------------------------------------------------------------------- /sign.h: -------------------------------------------------------------------------------- 1 | #ifndef __SIGN_H__ 2 | #define __SIGN_H__ 3 | 4 | 5 | int verify(char *message, int len, char *n, char *e, char *signature); 6 | char * sign(char *message, int len, char *n, char *d); 7 | 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /signature_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "sha256.h" 7 | #include "hmac.h" 8 | #include "rsa.h" 9 | #include "bignum.h" 10 | #include "sign.h" 11 | 12 | 13 | char message[] = "If someone loves a flower, of which just one single blossom \ 14 | grows in all the millions and millions of stars, it is enough to make him \ 15 | happy just to look at the stars. He can say to himself, \"Somewhere, my \ 16 | flower is there...\" But if the sheep eats the flower, in one moment all his \ 17 | stars will be darkened... And you think that is not important!"; 18 | 19 | char n[] = "2633080698619971615437014920877996278289800735266923785544426889944\ 20 | 0609476923080683027336422535126368322315074618477456816398312119637107174579114\ 21 | 6077889271153062424857361678839770414279603418258155137950669839476924880367722\ 22 | 7208754742309849130234906643942284202464540412162804353349325546974376995059994\ 23 | 9330325414410987655903196060428517308136957636128192517521032855823390274073501\ 24 | 3439285983045554313762834966326627260773872229023350480565433033059416766300354\ 25 | 3887701136666299285622928321437845693875410943358836663939407517138169975952711\ 26 | 275846765751052131139716555711355334713006212037080193708644870739003106023"; 27 | 28 | char d[] = "1534955005102752603929712492582465707392358566400470260398774839789\ 29 | 4934889672823592887074193372766370351195859772623603896884885924863886807706002\ 30 | 7938585710836982931342203312897564505231339737103623651425536893524351182472794\ 31 | 2027649848012582902905561935678338888913802659008057450433739864083753793978570\ 32 | 8323755112163962040283206669767339836307290354653158546139557266465579456201338\ 33 | 3640633190584017214343503798689012135964734952444966804075760697120758901874182\ 34 | 4461444633608054278015035978191475115533914789852447157474083845793224473202128\ 35 | 57398343699866494688143223633808351948490217995252693651367403612040470935"; 36 | 37 | char e[] = "1730645815"; 38 | 39 | 40 | void print_hex(uint8_t *ptr, int len) 41 | { 42 | int i; 43 | for (i = 0; i < len; i++) 44 | printf("%2.2x", ptr[i]); 45 | printf("\n"); 46 | } 47 | 48 | void sha256_test() 49 | { 50 | int len; 51 | uint8_t hash[SHA256_HASH_LEN]; 52 | sha256_ctx_t ctx; 53 | sha256_init(&ctx); 54 | 55 | len = strlen(message); 56 | 57 | sha256_update(&ctx, message, len); 58 | sha256_finish(&ctx, hash); 59 | 60 | printf("************SHA-256*************\n"); 61 | printf("message:\n%s\n", message); 62 | printf("digest:\n"); 63 | print_hex(hash, SHA256_HASH_LEN); 64 | } 65 | 66 | void hmac_sha256_test() 67 | { 68 | uint8_t key[] = "secretkey"; 69 | uint8_t mac[SHA256_HASH_LEN]; 70 | int keylen, msglen; 71 | 72 | keylen = strlen(key); 73 | msglen = strlen(message); 74 | 75 | printf("************HMAC-SHA-256*************\n"); 76 | hmac_sha256(message, msglen, key, keylen, mac); 77 | print_hex(mac, SHA256_HASH_LEN); 78 | } 79 | 80 | void rsa_key_gen_test() 81 | { 82 | char d[2048], e[2048], n[2048]; 83 | printf("************RSA_KEY_GEN*************\n"); 84 | rsa_generate_key_pair(n, d, e, NULL, 128); 85 | printf("n=%s\nd=%s\ne=%s\n",n,d,e); 86 | } 87 | 88 | void rsa_signature_test() 89 | { 90 | char *signature; 91 | int match; 92 | puts("************RSA Sigature*************"); 93 | signature = sign(message, strlen(message), n, d); 94 | match = verify(message, strlen(message), n, e, signature); 95 | if(match) 96 | puts("match!"); 97 | else 98 | puts("no match!"); 99 | } 100 | 101 | int main() 102 | { 103 | sha256_test(); 104 | hmac_sha256_test(); 105 | rsa_key_gen_test(); 106 | rsa_signature_test(); 107 | return 0; 108 | } 109 | --------------------------------------------------------------------------------