1 /** 2 # 3 # Copyright (c) 2018 IoTone, Inc. All rights reserved. 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy of this 6 # software and associated documentation files (the "Software"), to deal in the 7 # Software without restriction, including without limitation the rights to use, 8 # copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 9 # Software, and to permit persons to whom the Software is furnished to do so, subject 10 # 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 IMPLIED, 16 # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 17 # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 18 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 19 # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 # 22 **/ 23 module iotone.libkeccak; 24 25 import core.stdc.config; 26 import core.stdc.stdint; 27 28 29 // 30 // Major code debt/inspiration goes to https://github.com/coruus/keccak-tiny 31 // for the super minified C code library 32 // All data output can be hex encoded using preferred method 33 // 34 enum RET 35 { 36 OK = 0, 37 ERROR_INIT = -1, 38 ERROR_INPUT_INVALID = -2, 39 ERROR_FINALIZE = -3 40 } 41 42 nothrow extern (C) 43 { 44 int shake128(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 45 int shake256(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 46 47 int sha3_224(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 48 int sha3_256(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 49 int sha3_384(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 50 int sha3_512(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 51 52 int keccak_224(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 53 int keccak_256(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 54 int keccak_384(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 55 int keccak_512(uint8_t*, size_t /* bytes */, const uint8_t*, size_t); 56 }; 57 58 59 60 61 unittest { 62 import std.stdio; 63 import std.string; 64 65 // 66 // Including simple+efficient ubyte2hex converter 67 // from https://forum.dlang.org/post/opsfp9hj065a2sq9@digitalmars.com 68 // 69 const char[16] hexdigits = "0123456789abcdef"; 70 char[] hexStringT(ubyte[] d) { 71 char[] result; 72 73 /* No point converting an empty array now is there? */ 74 if (d.length != 0) { 75 ubyte u; 76 uint sz = u.sizeof*2; /* number of chars required to represent one 'u' */ 77 uint ndigits = 0; 78 79 /* pre-allocate space required. */ 80 result = new char[sz*d.length]; 81 82 /* start at end of resulting string, loop back to start. */ 83 for(int i = cast(int)d.length-1; i >= 0; i--) { 84 /*this loop takes the remainder of u/16, uses it as an index 85 into the hexdigits array, then does u/16, repeating 86 till u == 0 87 */ 88 u = d[i]; 89 for(; u; u /= 16) { 90 /* you can use u & 15 or u % 16 below 91 both give you the remainder of u/16 92 */ 93 result[result.length-1-ndigits] = hexdigits[u & 15]; 94 ndigits++; 95 } 96 97 /* Pad each value with 0's */ 98 for(; ndigits < (d.length-i)*sz; ndigits++) 99 result[result.length-1-ndigits] = '0'; 100 } 101 } 102 103 return result; 104 } 105 106 ubyte[28] dataout28; 107 ubyte[32] dataout32; 108 ubyte[48] dataout48; 109 ubyte[56] dataout56; 110 ubyte[64] dataout64; 111 ubyte[128] dataout128; 112 ubyte[256] dataout256; 113 ubyte[] datain = cast(ubyte[])("The quick brown fox jumps over the lazy dog".dup); 114 ubyte[] datain2 = cast(ubyte[])("".dup); 115 ubyte[] datain3 = cast(ubyte[])("The quick brown fox jumps over the lazy dog.".dup); 116 117 118 // A basic example 119 shake256(dataout32.ptr, 32 /* bytes */, datain.ptr, datain.length); 120 assert(dataout32.length == 32); 121 writeln(dataout32); 122 // writeln(hexStringT(dataout32)); 123 assert(hexStringT(dataout32) == "2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca"); 124 125 sha3_512(dataout64.ptr, 64, datain2.ptr, datain2.length); 126 assert(dataout64.length == 64); 127 writeln(dataout64); 128 assert(hexStringT(dataout64) == "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"); 129 130 131 sha3_512(dataout64.ptr, 64, datain.ptr, datain.length); 132 assert(dataout64.length == 64); 133 writeln(dataout64); 134 assert(hexStringT(dataout64) == "01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450"); 135 136 sha3_512(dataout64.ptr, 64, datain3.ptr, datain3.length); 137 assert(dataout64.length == 64); 138 writeln(dataout64); 139 assert(hexStringT(dataout64) == "18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8"); 140 141 sha3_384(dataout48.ptr, 48, datain2.ptr, datain2.length); 142 assert(dataout48.length == 48); 143 writeln(dataout48); 144 assert(hexStringT(dataout48) == "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"); 145 146 sha3_384(dataout48.ptr, 48, datain.ptr, datain.length); 147 assert(dataout48.length == 48); 148 writeln(dataout48); 149 assert(hexStringT(dataout48) == "7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41"); 150 151 sha3_384(dataout48.ptr, 48, datain3.ptr, datain3.length); 152 assert(dataout48.length == 48); 153 writeln(dataout48); 154 assert(hexStringT(dataout48) == "1a34d81695b622df178bc74df7124fe12fac0f64ba5250b78b99c1273d4b080168e10652894ecad5f1f4d5b965437fb9"); 155 156 sha3_256(dataout32.ptr, 32, datain2.ptr, datain2.length); 157 assert(dataout32.length == 32); 158 writeln(dataout32); 159 assert(hexStringT(dataout32) == "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"); 160 161 sha3_256(dataout32.ptr, 32, datain.ptr, datain.length); 162 assert(dataout32.length == 32); 163 writeln(dataout32); 164 assert(hexStringT(dataout32) == "69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04"); 165 166 sha3_256(dataout32.ptr, 32, datain3.ptr, datain3.length); 167 assert(dataout32.length == 32); 168 writeln(dataout32); 169 assert(hexStringT(dataout32) == "a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d"); 170 171 sha3_224(dataout28.ptr, 28, datain2.ptr, datain2.length); 172 assert(dataout28.length == 28); 173 writeln(dataout28); 174 assert(hexStringT(dataout28) == "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"); 175 176 sha3_224(dataout28.ptr, 28, datain.ptr, datain.length); 177 assert(dataout28.length == 28); 178 writeln(dataout28); 179 assert(hexStringT(dataout28) == "d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795"); 180 181 sha3_224(dataout28.ptr, 28, datain3.ptr, datain3.length); 182 assert(dataout28.length == 28); 183 writeln(dataout28); 184 assert(hexStringT(dataout28) == "2d0708903833afabdd232a20201176e8b58c5be8a6fe74265ac54db0"); 185 186 shake128(dataout32.ptr, 32 /* bytes */, datain2.ptr, datain2.length); 187 assert(dataout32.length == 32); 188 writeln(dataout32); 189 assert(hexStringT(dataout32) == "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26"); 190 191 shake256(dataout64.ptr, 64 /* bytes */, datain2.ptr, datain2.length); 192 assert(dataout64.length == 64); 193 writeln(dataout64); 194 assert(hexStringT(dataout64) == "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be"); 195 196 keccak_512(dataout64.ptr, 64, datain2.ptr, datain2.length); 197 assert(dataout64.length == 64); 198 writeln(dataout64); 199 assert(hexStringT(dataout64) == "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e"); 200 201 keccak_512(dataout64.ptr, 64, datain.ptr, datain.length); 202 assert(dataout64.length == 64); 203 writeln(dataout64); 204 assert(hexStringT(dataout64) == "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609"); 205 206 keccak_512(dataout64.ptr, 64, datain3.ptr, datain3.length); 207 assert(dataout64.length == 64); 208 writeln(dataout64); 209 assert(hexStringT(dataout64) == "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760"); 210 211 keccak_384(dataout48.ptr, 48, datain2.ptr, datain2.length); 212 assert(dataout48.length == 48); 213 writeln(dataout48); 214 assert(hexStringT(dataout48) == "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff"); 215 216 keccak_384(dataout48.ptr, 48, datain.ptr, datain.length); 217 assert(dataout48.length == 48); 218 writeln(dataout48); 219 assert(hexStringT(dataout48) == "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3"); 220 221 keccak_384(dataout48.ptr, 48, datain3.ptr, datain3.length); 222 assert(dataout48.length == 48); 223 writeln(dataout48); 224 assert(hexStringT(dataout48) == "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b"); 225 226 keccak_256(dataout32.ptr, 32 /* bytes */, datain2.ptr, datain2.length); 227 assert(dataout32.length == 32); 228 writeln(dataout32); 229 assert(hexStringT(dataout32) == "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); 230 231 keccak_256(dataout32.ptr, 32 /* bytes */, datain.ptr, datain.length); 232 assert(dataout32.length == 32); 233 writeln(dataout32); 234 assert(hexStringT(dataout32) == "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15"); 235 236 keccak_256(dataout32.ptr, 32 /* bytes */, datain3.ptr, datain3.length); 237 assert(dataout32.length == 32); 238 writeln(dataout32); 239 assert(hexStringT(dataout32) == "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d"); 240 241 keccak_224(dataout28.ptr, 28, datain2.ptr, datain2.length); 242 assert(dataout28.length == 28); 243 writeln(dataout28); 244 assert(hexStringT(dataout28) == "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd"); 245 246 keccak_224(dataout28.ptr, 28, datain.ptr, datain.length); 247 assert(dataout28.length == 28); 248 writeln(dataout28); 249 assert(hexStringT(dataout28) == "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe"); 250 251 keccak_224(dataout28.ptr, 28, datain3.ptr, datain3.length); 252 assert(dataout28.length == 28); 253 writeln(dataout28); 254 assert(hexStringT(dataout28) == "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab"); 255 }