├── README.md ├── test.c ├── lonesha256.h └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | This is a header-only library, as such most of its functional documentation is contained within the "header section" of the 4 | source code in the form of comments. It is highly recommended that you read said documentation before using this library. 5 | 6 | ## Features 7 | 8 | The lonesha256 library provides portable sha256 hashing in a single function, its features include: 9 | 10 | - No hard dependencies besides the standard library, making it fully portable 11 | - Avoids endianness issues by relying entirely on endian-agnostic operations 12 | - Simple hashing in a single function without any convoluted initialization 13 | 14 | ## Attribution 15 | 16 | You are not required to give attribution when using this library. If you want to give attribution anyway, either link to 17 | this repository, [my website](https://www.slopegames.com/), or credit me as [BareRose](https://github.com/BareRose). 18 | If you want to support me financially, consider giving to my [Patreon](https://www.patreon.com/slopegames). 19 | 20 | ## License 21 | 22 | Licensed under CC0 aka the most lawyer-friendly way of spelling "public domain". -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | /* 2 | lonesha256.h test by comparison with known hashes of strings, also serves as usage example 3 | 4 | To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring 5 | rights to this software to the public domain worldwide. This software is distributed without any warranty. 6 | You should have received a copy of the CC0 Public Domain Dedication along with this software. 7 | If not, see . 8 | */ 9 | 10 | /* 11 | Compile using "gcc test.c" or equivalent, then run from command line to see the results. 12 | If you find an error in this test or a test pair which lonesha256 fails, please open an issue. 13 | */ 14 | 15 | //includes 16 | #define LONESHA256_STATIC 17 | #include "lonesha256.h" 18 | #include 19 | 20 | //structs 21 | struct pair { 22 | unsigned char* in; //input string 23 | unsigned char out[32]; //expected output 24 | }; 25 | 26 | //known input/output pairs 27 | struct pair pairs[] = { 28 | //0: empty string 29 | { 30 | "", 31 | {0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 32 | 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 33 | 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 34 | 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55} 35 | }, 36 | //1: foobar string 37 | { 38 | "foobar", 39 | {0xC3, 0xAB, 0x8F, 0xF1, 0x37, 0x20, 0xE8, 0xAD, 40 | 0x90, 0x47, 0xDD, 0x39, 0x46, 0x6B, 0x3C, 0x89, 41 | 0x74, 0xE5, 0x92, 0xC2, 0xFA, 0x38, 0x3D, 0x4A, 42 | 0x39, 0x60, 0x71, 0x4C, 0xAE, 0xF0, 0xC4, 0xF2} 43 | }, 44 | //2: quick brown fox 45 | { 46 | "The quick brown fox jumps over the lazy dog", 47 | {0xD7, 0xA8, 0xFB, 0xB3, 0x07, 0xD7, 0x80, 0x94, 48 | 0x69, 0xCA, 0x9A, 0xBC, 0xB0, 0x08, 0x2E, 0x4F, 49 | 0x8D, 0x56, 0x51, 0xE4, 0x6D, 0x3C, 0xDB, 0x76, 50 | 0x2D, 0x02, 0xD0, 0xBF, 0x37, 0xC9, 0xE5, 0x92} 51 | }, 52 | //3: random string 53 | { 54 | "dThNFRWWhyG7pINI", 55 | {0x64, 0x13, 0x46, 0x80, 0xDC, 0x26, 0x6E, 0x5D, 56 | 0xFF, 0xE3, 0x83, 0xBD, 0xC4, 0xD1, 0x98, 0xC3, 57 | 0xA3, 0x59, 0x2C, 0x36, 0xB4, 0x78, 0xCE, 0xBE, 58 | 0xD6, 0x6C, 0x15, 0x8F, 0x78, 0x82, 0x5A, 0x28} 59 | }, 60 | //4: longer string 61 | { 62 | "laSQWLJtfvdfSvH9MaJC32tk59jpm3ZOkfQX2E308aUqgyqY" 63 | "Tq2hOyoLJaujn4ULaFDEb65ISERxjSqovIiccU1q8TxsBwm6" 64 | "qodWbY3mUdPL0YuRrN9RggDzkvHQz91XbpoItjPB7mxtzILt" 65 | "lypZtfJY3A3xh0B4ZrsRM2FTtcircLWRfDOpGIGbQcJoXeZq" 66 | "vKdvzrGbs6oG8wKAYKn51j3aQDNmENXGlYR06eRXFyctEU3g" 67 | "HDaXB6shHCa621wAIPn3ZjtaPzkYjFIQv2NwAnmLCSxOlhqs" 68 | "pCoaNVwHfHc6bc3c0Ani6f8Gto3lfrEMwLaPkxOEXuh4SK5w" 69 | "0qWQdahu4LNqoqT7KI7uuwXiMMzw6Y7ySK3u37VJ8msDNI6f" 70 | "0nRHEfROfhK2Yf3FVGItOcNBQDUa4BeuAJgt", 71 | {0xCD, 0x6F, 0x3B, 0x5E, 0x08, 0xC3, 0x41, 0x62, 72 | 0xCB, 0xD5, 0x19, 0x0D, 0xA8, 0xCD, 0x45, 0xF7, 73 | 0x63, 0x7E, 0x15, 0x13, 0x8A, 0x39, 0x62, 0x90, 74 | 0x03, 0x68, 0x97, 0xB3, 0x18, 0x84, 0x26, 0xFE} 75 | }, 76 | //5: 56 spaces 77 | { 78 | " ", 79 | {0xB6, 0x0C, 0x4C, 0x2D, 0x56, 0x5C, 0xD1, 0xF1, 80 | 0x0E, 0xEB, 0x0D, 0xEF, 0xFD, 0xD7, 0xB6, 0x5F, 81 | 0xDF, 0x9D, 0x4F, 0xD3, 0x96, 0x08, 0x68, 0xDA, 82 | 0x68, 0xE3, 0x53, 0x31, 0x59, 0xB7, 0x0B, 0xD8} 83 | } 84 | }; 85 | 86 | //main function 87 | int main () { 88 | //runs through all the hard-coded pairs, then returns 89 | for (int i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) { 90 | unsigned char out[32]; 91 | if (lonesha256(out, pairs[i].in, strlen(pairs[i].in))) 92 | printf("TEST %d: ERROR\n", i); 93 | else if (memcmp(out, pairs[i].out, sizeof(out))) 94 | printf("TEST %d: FAILED\n", i); 95 | else 96 | printf("TEST %d: PASSED\n", i); 97 | } 98 | //return 99 | return 0; 100 | } -------------------------------------------------------------------------------- /lonesha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | lonesha256.h - Portable, endian-proof, single-file, single-function sha256 implementation, originally based on LibTomCrypt 3 | 4 | To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring 5 | rights to this software to the public domain worldwide. This software is distributed without any warranty. 6 | You should have received a copy of the CC0 Public Domain Dedication along with this software. 7 | If not, see . 8 | */ 9 | 10 | /* 11 | lonesha256 supports the following three configurations: 12 | #define LONESHA256_EXTERN 13 | Default, should be used when using lonesha256 in multiple compilation units within the same project. 14 | #define LONESHA256_IMPLEMENTATION 15 | Must be defined in exactly one source file within a project for lonesha256 to be found by the linker. 16 | #define LONESHA256_STATIC 17 | Defines the lonesha256() function as static, useful if lonesha256 is only used in a single compilation unit. 18 | 19 | lonesha256 function: 20 | (static|extern) int lonesha256 (unsigned char out[32], const unsigned char* in, size_t len) 21 | writes the sha256 hash of the first "len" bytes in buffer "in" to buffer "out" 22 | returns 0 on success, may return non-zero in future versions to indicate error 23 | */ 24 | 25 | //header section 26 | #ifndef LONESHA256_H 27 | #define LONESHA256_H 28 | 29 | //process configuration 30 | #ifdef LONESHA256_STATIC 31 | #define LONESHA256_IMPLEMENTATION 32 | #define LSHA256DEF static 33 | #else //LONESHA256_EXTERN 34 | #define LSHA256DEF extern 35 | #endif 36 | 37 | //includes 38 | #include //size_t 39 | 40 | //lonesha256 declaration 41 | LSHA256DEF int lonesha256(unsigned char[32], const unsigned char*, size_t); 42 | 43 | #endif //LONESHA256_H 44 | 45 | //implementation section 46 | #ifdef LONESHA256_IMPLEMENTATION 47 | #undef LONESHA256_IMPLEMENTATION 48 | 49 | //macros 50 | #define S(x, n) (((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((n)&31))|((uint32_t)(x)<<(uint32_t)((32-((n)&31))&31)))&0xFFFFFFFFUL) 51 | #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) 52 | #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) 53 | #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) 54 | #define RND(a,b,c,d,e,f,g,h,i) \ 55 | t0 = h + (S(e, 6) ^ S(e, 11) ^ S(e, 25)) + (g ^ (e & (f ^ g))) + K[i] + W[i]; \ 56 | t1 = (S(a, 2) ^ S(a, 13) ^ S(a, 22)) + (((a | b) & c) | (a & b)); \ 57 | d += t0; \ 58 | h = t0 + t1; 59 | #define STORE32H(x, y) \ 60 | (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ 61 | (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); 62 | #define LOAD32H(x, y) \ 63 | x = ((uint32_t)((y)[0]&255)<<24)|((uint32_t)((y)[1]&255)<<16)|((uint32_t)((y)[2]&255)<<8)|((uint32_t)((y)[3]&255)); 64 | #define STORE64H(x, y) \ 65 | (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ 66 | (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ 67 | (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ 68 | (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); 69 | #define SHA256_COMPRESS(buff) \ 70 | for (int i = 0; i < 8; i++) S[i] = sha256_state[i]; \ 71 | for (int i = 0; i < 16; i++) LOAD32H(W[i], buff + (4*i)); \ 72 | for (int i = 16; i < 64; i++) W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; \ 73 | for (int i = 0; i < 64; i++) { \ 74 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); \ 75 | t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; \ 76 | S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; \ 77 | } \ 78 | for (int i = 0; i < 8; i++) sha256_state[i] = sha256_state[i] + S[i]; 79 | 80 | //includes 81 | #include //uint32_t, uint64_t 82 | #include //memcpy 83 | 84 | //lonesha256 function 85 | LSHA256DEF int lonesha256 (unsigned char out[32], const unsigned char* in, size_t len) { 86 | //writes the sha256 hash of the first "len" bytes in buffer "in" to buffer "out" 87 | //returns 0 on success, may return non-zero in future versions to indicate error 88 | const uint32_t K[64] = { 89 | 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 90 | 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 91 | 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 92 | 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 93 | 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 94 | 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 95 | 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 96 | 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 97 | 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 98 | 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 99 | 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 100 | 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 101 | 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 102 | 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 103 | 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 104 | 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL 105 | }; 106 | uint64_t sha256_length = 0; 107 | uint32_t sha256_state[8] = { 108 | 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 109 | 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL 110 | }, S[8], W[64], t0, t1, t; 111 | unsigned char sha256_buf[64]; 112 | //process input in 64 byte chunks 113 | while (len >= 64) { 114 | SHA256_COMPRESS(in); 115 | sha256_length += 64 * 8; 116 | in += 64; 117 | len -= 64; 118 | } 119 | //copy remaining bytes into sha256_buf 120 | memcpy(sha256_buf, in, len); 121 | //finish up (len now number of bytes in sha256_buf) 122 | sha256_length += len * 8; 123 | sha256_buf[len++] = 0x80; 124 | //pad then compress if length is above 56 bytes 125 | if (len > 56) { 126 | while (len < 64) sha256_buf[len++] = 0; 127 | SHA256_COMPRESS(sha256_buf); 128 | len = 0; 129 | } 130 | //pad up to 56 bytes 131 | while (len < 56) sha256_buf[len++] = 0; 132 | //store length and compress 133 | STORE64H(sha256_length, sha256_buf + 56); 134 | SHA256_COMPRESS(sha256_buf); 135 | //copy output 136 | for (int i = 0; i < 8; i++) { 137 | STORE32H(sha256_state[i], out + 4*i); 138 | } 139 | //return 140 | return 0; 141 | } 142 | 143 | #endif //LONESHA256_IMPLEMENTATION -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | --------------------------------------------------------------------------------