1 /* 2 * ------------------------------------------------------------------------- 3 * Run SHA-3 (NIST FIPS 202) on the given file. 4 * 5 * Call as 6 * 7 * sha3sum 256|384|512 file_path 8 * 9 * See sha3.c for additional details. 10 * 11 * Jun 2018. Andrey Jivsov. crypto@brainhub.org 12 * ---------------------------------------------------------------------- 13 */ 14 module sha3sum; 15 16 17 private static import core.stdc.stdio; 18 private static import core.stdc.stdlib; 19 private static import core.stdc.string; 20 private static import core.stdc.wchar_; 21 private static import core.sys.posix.fcntl; 22 private static import core.sys.posix.sys.mman; 23 private static import core.sys.posix.sys.stat; 24 private static import core.sys.posix.unistd; 25 private static import sha3iuf_d; 26 27 nothrow @nogc @live 28 private void help(scope const char* argv0) 29 30 do 31 { 32 core.stdc.stdio.printf("To call: %s 256|384|512 [-k] file_path.\n", argv0); 33 } 34 35 pure nothrow @nogc @live 36 private void byte_to_hex(ubyte b, ref char[3] s) 37 38 do 39 { 40 s[0] = '0'; 41 s[1] = '0'; 42 s[2] = '\0'; 43 uint i = 1; 44 45 while (b != 0) { 46 uint t = b & 0x0F; 47 assert(i < 2); 48 49 if (t < 10) { 50 s[i] = cast(char)('0' + t); 51 } else { 52 s[i] = cast(char)('a' + t - 10); 53 } 54 55 i--; 56 b >>= 4; 57 } 58 } 59 60 version (Posix) 61 extern (C) 62 nothrow @nogc @live 63 int main(int argc, char** argv) 64 65 do 66 { 67 if ((argc != 3) && (argc != 4)) { 68 .help(argv[0]); 69 70 return 1; 71 } 72 73 int image_size = core.stdc.stdlib.atoi(argv[1]); 74 75 switch (image_size) { 76 case 256: 77 case 384: 78 case 512: 79 break; 80 81 default: 82 .help(argv[0]); 83 84 return 1; 85 } 86 87 const (char)* file_path = argv[2]; 88 bool use_keccak = false; 89 90 if ((argc == 4) && (file_path[0] == '-') && (file_path[1] == 'k')) { 91 use_keccak = true; 92 file_path = argv[3]; 93 } 94 95 if (core.sys.posix.unistd.access(file_path, core.sys.posix.unistd.R_OK) != 0) { 96 core.stdc.stdio.printf("Cannot read file '%s'", file_path); 97 98 return 2; 99 } 100 101 int fd = core.sys.posix.fcntl.open(file_path, core.sys.posix.fcntl.O_RDONLY); 102 103 if (fd == -1) { 104 core.stdc.stdio.printf("Cannot open file '%s' for reading", file_path); 105 106 return 2; 107 } 108 109 core.sys.posix.sys.stat.stat_t st = void; 110 uint i = core.sys.posix.sys.stat.fstat(fd, &st); 111 112 if (i != 0) { 113 core.sys.posix.unistd.close(fd); 114 core.stdc.stdio.printf("Cannot determine the size of file '%s'", file_path); 115 116 return 2; 117 } 118 119 void* p = core.sys.posix.sys.mman.mmap(null, st.st_size, core.sys.posix.sys.mman.PROT_READ, core.sys.posix.sys.mman.MAP_SHARED, fd, 0); 120 core.sys.posix.unistd.close(fd); 121 122 if (p == null) { 123 core.stdc.stdio.printf("Cannot memory-map file '%s'", file_path); 124 125 return 2; 126 } 127 128 sha3iuf_d.sha3_context c = void; 129 130 switch (image_size) { 131 case 256: 132 sha3iuf_d.sha3_Init256(&c); 133 134 break; 135 136 case 384: 137 sha3iuf_d.sha3_Init384(&c); 138 139 break; 140 141 case 512: 142 sha3iuf_d.sha3_Init512(&c); 143 144 break; 145 146 default: 147 assert(false); 148 } 149 150 if (use_keccak) { 151 sha3iuf_d.SHA3_FLAGS flags2 = sha3iuf_d.sha3_SetFlags(&c, sha3iuf_d.SHA3_FLAGS.SHA3_FLAGS_KECCAK); 152 153 if (flags2 != sha3iuf_d.SHA3_FLAGS.SHA3_FLAGS_KECCAK) { 154 core.stdc.stdio.printf("Failed to set Keccak mode"); 155 156 return 2; 157 } 158 } 159 160 sha3iuf_d.sha3_Update(&c, p, st.st_size); 161 const ubyte* hash = cast(const ubyte*)(sha3iuf_d.sha3_Finalize(&c)); 162 163 core.sys.posix.sys.mman.munmap(p, st.st_size); 164 165 for (i = 0; i < (image_size / 8); i++) { 166 char[3] s = void; 167 .byte_to_hex(hash[i], s); 168 core.stdc.stdio.printf("%s", &(s[0])); 169 } 170 171 core.stdc.stdio.printf(" %s\n", file_path); 172 173 return 0; 174 }