├── LICENSE ├── Makefile ├── README.md ├── main.c ├── sha3.c └── sha3.h /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Markku-Juhani O. Saarinen 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 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # 19-Nov-11 Markku-Juhani O. Saarinen 3 | 4 | BINARY = sha3test 5 | OBJS = sha3.o main.o 6 | DIST = tiny_sha3 7 | 8 | CC = gcc 9 | CFLAGS = -Wall -O3 10 | LIBS = 11 | LDFLAGS = 12 | INCLUDES = 13 | 14 | $(BINARY): $(OBJS) 15 | $(CC) $(LDFLAGS) -o $(BINARY) $(OBJS) $(LIBS) 16 | 17 | .c.o: 18 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 19 | 20 | clean: 21 | rm -rf $(DIST)-*.txz $(OBJS) $(BINARY) *~ 22 | 23 | dist: clean 24 | cd ..; \ 25 | tar cfvJ $(DIST)/$(DIST)-`date -u "+%Y%m%d%H%M00"`.txz \ 26 | $(DIST)/* 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny_sha3 2 | Very small, readable implementation of the FIPS 202 and SHA3 hash function. 3 | Public domain. 4 | 5 | ### Updated 27-Dec-15: 6 | 7 | Added SHAKE128 and SHAKE256 code and test vectors. The code can actually do 8 | a XOF of arbitrary size (like "SHAKE512"). 9 | 10 | 11 | ### Updated 03-Sep-15: 12 | 13 | Made the implementation portable. The API is now pretty much the 14 | same that OpenSSL uses. 15 | 16 | 17 | ### Updated 07-Aug-15: 18 | 19 | Now that SHA3 spec is out, I've updated the package to match with the 20 | new padding rules. There is literally one line difference between 21 | Keccak 3.0 and SHA-3 implementations: 22 | 23 | ``` 24 | temp[inlen++] = 0x06; // XXX Padding Changed from Keccak 3.0 25 | ``` 26 | 27 | The 0x06 constant there used to be 0x01. But this of course totally 28 | breaks compatibility and test vectors had to be revised. 29 | 30 | SHA-3 Spec: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf 31 | 32 | Cheers, 33 | - markku 34 | 35 | 36 | ### Original README.TXT from 19-Nov-11: 37 | 38 | Hi. 39 | 40 | The SHA-3 competition is nearing it's end and I would personally like 41 | to support Keccak as the winner. I have a PhD in hash function cryptanalysis 42 | so don't take my word for it, go ahead and look into the code ! 43 | 44 | Since I couldn't find a *compact* and/or *readable* implementation of Keccak 45 | anywhere, here's one I cooked up as a service to the curious. 46 | 47 | This implementation is intended for study of the algorithm, not for 48 | production use. 49 | 50 | The code works correctly on 64-bit little-endian platforms with gcc. 51 | Like your Linux box. The main.c module contains self-tests for all 52 | officially supported hash sizes. 53 | 54 | If you're looking for production code, the official multi-megabyte package 55 | covers everyting you could possibly need and too much much more: 56 | http://keccak.noekeon.org/ 57 | 58 | Cheers, 59 | - Markku 19-Nov-11 60 | 61 | Dr. Markku-Juhani O. Saarinen 62 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | // main.c 2 | // 19-Nov-11 Markku-Juhani O. Saarinen 3 | 4 | #include 5 | #include 6 | #include 7 | #include "sha3.h" 8 | 9 | // read a hex string, return byte length or -1 on error. 10 | 11 | static int test_hexdigit(char ch) 12 | { 13 | if (ch >= '0' && ch <= '9') 14 | return ch - '0'; 15 | if (ch >= 'A' && ch <= 'F') 16 | return ch - 'A' + 10; 17 | if (ch >= 'a' && ch <= 'f') 18 | return ch - 'a' + 10; 19 | return -1; 20 | } 21 | 22 | static int test_readhex(uint8_t *buf, const char *str, int maxbytes) 23 | { 24 | int i, h, l; 25 | 26 | for (i = 0; i < maxbytes; i++) { 27 | h = test_hexdigit(str[2 * i]); 28 | if (h < 0) 29 | return i; 30 | l = test_hexdigit(str[2 * i + 1]); 31 | if (l < 0) 32 | return i; 33 | buf[i] = (h << 4) + l; 34 | } 35 | 36 | return i; 37 | } 38 | 39 | // returns zero on success, nonzero + stderr messages on failure 40 | 41 | int test_sha3() 42 | { 43 | // message / digest pairs, lifted from ShortMsgKAT_SHA3-xxx.txt files 44 | // in the official package: https://github.com/gvanas/KeccakCodePackage 45 | 46 | const char *testvec[][2] = { 47 | { // SHA3-224, corner case with 0-length message 48 | "", 49 | "6B4E03423667DBB73B6E15454F0EB1ABD4597F9A1B078E3F5B5A6BC7" 50 | }, 51 | { // SHA3-256, short message 52 | "9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10", 53 | "2F1A5F7159E34EA19CDDC70EBF9B81F1A66DB40615D7EAD3CC1F1B954D82A3AF" 54 | }, 55 | { // SHA3-384, exact block size 56 | "E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486" 57 | "F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826D" 58 | "B923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A" 59 | "21691E1069413848", 60 | "D1C0FA85C8D183BEFF99AD9D752B263E286B477F79F0710B0103170173978133" 61 | "44B99DAF3BB7B1BC5E8D722BAC85943A" 62 | }, 63 | { // SHA3-512, multiblock message 64 | "3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5" 65 | "623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A" 66 | "15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0" 67 | "A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764" 68 | "B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43" 69 | "C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D" 70 | "817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E08" 71 | "5172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1", 72 | "6E8B8BD195BDD560689AF2348BDC74AB7CD05ED8B9A57711E9BE71E9726FDA45" 73 | "91FEE12205EDACAF82FFBBAF16DFF9E702A708862080166C2FF6BA379BC7FFC2" 74 | } 75 | }; 76 | 77 | int i, fails, msg_len, sha_len; 78 | uint8_t sha[64], buf[64], msg[256]; 79 | 80 | fails = 0; 81 | for (i = 0; i < 4; i++) { 82 | 83 | memset(sha, 0, sizeof(sha)); 84 | memset(buf, 0, sizeof(buf)); 85 | memset(msg, 0, sizeof(msg)); 86 | 87 | msg_len = test_readhex(msg, testvec[i][0], sizeof(msg)); 88 | sha_len = test_readhex(sha, testvec[i][1], sizeof(sha)); 89 | 90 | sha3(msg, msg_len, buf, sha_len); 91 | 92 | if (memcmp(sha, buf, sha_len) != 0) { 93 | fprintf(stderr, "[%d] SHA3-%d, len %d test FAILED.\n", 94 | i, sha_len * 8, msg_len); 95 | fails++; 96 | } 97 | } 98 | 99 | return fails; 100 | } 101 | 102 | // test for SHAKE128 and SHAKE256 103 | 104 | int test_shake() 105 | { 106 | // Test vectors have bytes 480..511 of XOF output for given inputs. 107 | // From http://csrc.nist.gov/groups/ST/toolkit/examples.html#aHashing 108 | 109 | const char *testhex[4] = { 110 | // SHAKE128, message of length 0 111 | "43E41B45A653F2A5C4492C1ADD544512DDA2529833462B71A41A45BE97290B6F", 112 | // SHAKE256, message of length 0 113 | "AB0BAE316339894304E35877B0C28A9B1FD166C796B9CC258A064A8F57E27F2A", 114 | // SHAKE128, 1600-bit test pattern 115 | "44C9FB359FD56AC0A9A75A743CFF6862F17D7259AB075216C0699511643B6439", 116 | // SHAKE256, 1600-bit test pattern 117 | "6A1A9D7846436E4DCA5728B6F760EEF0CA92BF0BE5615E96959D767197A0BEEB" 118 | }; 119 | 120 | int i, j, fails; 121 | sha3_ctx_t sha3; 122 | uint8_t buf[32], ref[32]; 123 | 124 | fails = 0; 125 | 126 | for (i = 0; i < 4; i++) { 127 | 128 | if ((i & 1) == 0) { // test each twice 129 | shake128_init(&sha3); 130 | } else { 131 | shake256_init(&sha3); 132 | } 133 | 134 | if (i >= 2) { // 1600-bit test pattern 135 | memset(buf, 0xA3, 20); 136 | for (j = 0; j < 200; j += 20) 137 | shake_update(&sha3, buf, 20); 138 | } 139 | 140 | shake_xof(&sha3); // switch to extensible output 141 | 142 | for (j = 0; j < 512; j += 32) // output. discard bytes 0..479 143 | shake_out(&sha3, buf, 32); 144 | 145 | // compare to reference 146 | test_readhex(ref, testhex[i], sizeof(ref)); 147 | if (memcmp(buf, ref, 32) != 0) { 148 | fprintf(stderr, "[%d] SHAKE%d, len %d test FAILED.\n", 149 | i, i & 1 ? 256 : 128, i >= 2 ? 1600 : 0); 150 | fails++; 151 | } 152 | } 153 | 154 | return fails; 155 | } 156 | 157 | // test speed of the comp 158 | 159 | void test_speed() 160 | { 161 | int i; 162 | uint64_t st[25], x, n; 163 | clock_t bg, us; 164 | 165 | for (i = 0; i < 25; i++) 166 | st[i] = i; 167 | 168 | bg = clock(); 169 | n = 0; 170 | do { 171 | for (i = 0; i < 100000; i++) 172 | sha3_keccakf(st); 173 | n += i; 174 | us = clock() - bg; 175 | } while (us < 3 * CLOCKS_PER_SEC); 176 | 177 | x = 0; 178 | for (i = 0; i < 25; i++) 179 | x += st[i]; 180 | 181 | printf("(%016lX) %.3f Keccak-p[1600,24] / Second.\n", 182 | (unsigned long) x, (CLOCKS_PER_SEC * ((double) n)) / ((double) us)); 183 | 184 | 185 | } 186 | 187 | // main 188 | int main(int argc, char **argv) 189 | { 190 | if (test_sha3() == 0 && test_shake() == 0) 191 | printf("FIPS 202 / SHA3, SHAKE128, SHAKE256 Self-Tests OK!\n"); 192 | test_speed(); 193 | 194 | return 0; 195 | } 196 | 197 | -------------------------------------------------------------------------------- /sha3.c: -------------------------------------------------------------------------------- 1 | // sha3.c 2 | // 19-Nov-11 Markku-Juhani O. Saarinen 3 | 4 | // Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3" 5 | // Revised 03-Sep-15 for portability + OpenSSL - style API 6 | 7 | #include "sha3.h" 8 | 9 | // update the state with given number of rounds 10 | 11 | void sha3_keccakf(uint64_t st[25]) 12 | { 13 | // constants 14 | const uint64_t keccakf_rndc[24] = { 15 | 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 16 | 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, 17 | 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, 18 | 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, 19 | 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 20 | 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 21 | 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, 22 | 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 23 | }; 24 | const int keccakf_rotc[24] = { 25 | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 26 | 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 27 | }; 28 | const int keccakf_piln[24] = { 29 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 30 | 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 31 | }; 32 | 33 | // variables 34 | int i, j, r; 35 | uint64_t t, bc[5]; 36 | 37 | #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ 38 | uint8_t *v; 39 | 40 | // endianess conversion. this is redundant on little-endian targets 41 | for (i = 0; i < 25; i++) { 42 | v = (uint8_t *) &st[i]; 43 | st[i] = ((uint64_t) v[0]) | (((uint64_t) v[1]) << 8) | 44 | (((uint64_t) v[2]) << 16) | (((uint64_t) v[3]) << 24) | 45 | (((uint64_t) v[4]) << 32) | (((uint64_t) v[5]) << 40) | 46 | (((uint64_t) v[6]) << 48) | (((uint64_t) v[7]) << 56); 47 | } 48 | #endif 49 | 50 | // actual iteration 51 | for (r = 0; r < KECCAKF_ROUNDS; r++) { 52 | 53 | // Theta 54 | for (i = 0; i < 5; i++) 55 | bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; 56 | 57 | for (i = 0; i < 5; i++) { 58 | t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); 59 | for (j = 0; j < 25; j += 5) 60 | st[j + i] ^= t; 61 | } 62 | 63 | // Rho Pi 64 | t = st[1]; 65 | for (i = 0; i < 24; i++) { 66 | j = keccakf_piln[i]; 67 | bc[0] = st[j]; 68 | st[j] = ROTL64(t, keccakf_rotc[i]); 69 | t = bc[0]; 70 | } 71 | 72 | // Chi 73 | for (j = 0; j < 25; j += 5) { 74 | for (i = 0; i < 5; i++) 75 | bc[i] = st[j + i]; 76 | for (i = 0; i < 5; i++) 77 | st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; 78 | } 79 | 80 | // Iota 81 | st[0] ^= keccakf_rndc[r]; 82 | } 83 | 84 | #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ 85 | // endianess conversion. this is redundant on little-endian targets 86 | for (i = 0; i < 25; i++) { 87 | v = (uint8_t *) &st[i]; 88 | t = st[i]; 89 | v[0] = t & 0xFF; 90 | v[1] = (t >> 8) & 0xFF; 91 | v[2] = (t >> 16) & 0xFF; 92 | v[3] = (t >> 24) & 0xFF; 93 | v[4] = (t >> 32) & 0xFF; 94 | v[5] = (t >> 40) & 0xFF; 95 | v[6] = (t >> 48) & 0xFF; 96 | v[7] = (t >> 56) & 0xFF; 97 | } 98 | #endif 99 | } 100 | 101 | // Initialize the context for SHA3 102 | 103 | int sha3_init(sha3_ctx_t *c, int mdlen) 104 | { 105 | int i; 106 | 107 | for (i = 0; i < 25; i++) 108 | c->st.q[i] = 0; 109 | c->mdlen = mdlen; 110 | c->rsiz = 200 - 2 * mdlen; 111 | c->pt = 0; 112 | 113 | return 1; 114 | } 115 | 116 | // update state with more data 117 | 118 | int sha3_update(sha3_ctx_t *c, const void *data, size_t len) 119 | { 120 | size_t i; 121 | int j; 122 | 123 | j = c->pt; 124 | for (i = 0; i < len; i++) { 125 | c->st.b[j++] ^= ((const uint8_t *) data)[i]; 126 | if (j >= c->rsiz) { 127 | sha3_keccakf(c->st.q); 128 | j = 0; 129 | } 130 | } 131 | c->pt = j; 132 | 133 | return 1; 134 | } 135 | 136 | // finalize and output a hash 137 | 138 | int sha3_final(void *md, sha3_ctx_t *c) 139 | { 140 | int i; 141 | 142 | c->st.b[c->pt] ^= 0x06; 143 | c->st.b[c->rsiz - 1] ^= 0x80; 144 | sha3_keccakf(c->st.q); 145 | 146 | for (i = 0; i < c->mdlen; i++) { 147 | ((uint8_t *) md)[i] = c->st.b[i]; 148 | } 149 | 150 | return 1; 151 | } 152 | 153 | // compute a SHA-3 hash (md) of given byte length from "in" 154 | 155 | void *sha3(const void *in, size_t inlen, void *md, int mdlen) 156 | { 157 | sha3_ctx_t sha3; 158 | 159 | sha3_init(&sha3, mdlen); 160 | sha3_update(&sha3, in, inlen); 161 | sha3_final(md, &sha3); 162 | 163 | return md; 164 | } 165 | 166 | // SHAKE128 and SHAKE256 extensible-output functionality 167 | 168 | void shake_xof(sha3_ctx_t *c) 169 | { 170 | c->st.b[c->pt] ^= 0x1F; 171 | c->st.b[c->rsiz - 1] ^= 0x80; 172 | sha3_keccakf(c->st.q); 173 | c->pt = 0; 174 | } 175 | 176 | void shake_out(sha3_ctx_t *c, void *out, size_t len) 177 | { 178 | size_t i; 179 | int j; 180 | 181 | j = c->pt; 182 | for (i = 0; i < len; i++) { 183 | if (j >= c->rsiz) { 184 | sha3_keccakf(c->st.q); 185 | j = 0; 186 | } 187 | ((uint8_t *) out)[i] = c->st.b[j++]; 188 | } 189 | c->pt = j; 190 | } 191 | 192 | -------------------------------------------------------------------------------- /sha3.h: -------------------------------------------------------------------------------- 1 | // sha3.h 2 | // 19-Nov-11 Markku-Juhani O. Saarinen 3 | 4 | #ifndef SHA3_H 5 | #define SHA3_H 6 | 7 | #include 8 | #include 9 | 10 | #ifndef KECCAKF_ROUNDS 11 | #define KECCAKF_ROUNDS 24 12 | #endif 13 | 14 | #ifndef ROTL64 15 | #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) 16 | #endif 17 | 18 | // state context 19 | typedef struct { 20 | union { // state: 21 | uint8_t b[200]; // 8-bit bytes 22 | uint64_t q[25]; // 64-bit words 23 | } st; 24 | int pt, rsiz, mdlen; // these don't overflow 25 | } sha3_ctx_t; 26 | 27 | // Compression function. 28 | void sha3_keccakf(uint64_t st[25]); 29 | 30 | // OpenSSL - like interfece 31 | int sha3_init(sha3_ctx_t *c, int mdlen); // mdlen = hash output in bytes 32 | int sha3_update(sha3_ctx_t *c, const void *data, size_t len); 33 | int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md 34 | 35 | // compute a sha3 hash (md) of given byte length from "in" 36 | void *sha3(const void *in, size_t inlen, void *md, int mdlen); 37 | 38 | // SHAKE128 and SHAKE256 extensible-output functions 39 | #define shake128_init(c) sha3_init(c, 16) 40 | #define shake256_init(c) sha3_init(c, 32) 41 | #define shake_update sha3_update 42 | 43 | void shake_xof(sha3_ctx_t *c); 44 | void shake_out(sha3_ctx_t *c, void *out, size_t len); 45 | 46 | #endif 47 | 48 | --------------------------------------------------------------------------------