/* * One-Clause BSD License ("1BSD") * * Copyright 2022 Kaz Kylheku * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following condition is * met: * * 1. The source code distribution retains the above copyright notice, * this condition, and the following disclaimer. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef JP_HASH_H #define JP_HASH_H #ifdef __cplusplus extern "C" { #endif void jp_hash(char *out, const char *in); #ifdef __cplusplus } #endif #if JP_HASH_IMPL #include #include #include #include #include #define elof(array) ((int)(sizeof(array)/sizeof(array[0]))) static const char *mora[] = { "a", "i", "u", "e", "o", "ya", "yu", "yo", "wa", "ka", "ki", "ku", "ke", "ko", "ga", "gi", "gu", "ge", "go", "sa", "shi", "su", "se", "so", "za", "ji", "zu", "ze", "zo", "ta", "chi", "tsu", "te", "to", "da", "de", "do", "na", "ni", "nu", "ne", "no", "ha", "hi", "fu", "he", "ho", "pa", "pi", "pu", "pe", "po", "ba", "bi", "bu", "be", "bo", "ma", "mi", "mu", "me", "mo", "ra", "ri", "ru", "re", "ro", "kya", "kyu", "kyo", "gya", "gyu", "gyo", "sha", "shu", "sho", "ja", "ju", "jo", "cha", "chu", "cho", "nya", "nyu", "nyo", "hya", "hyu", "hyo", "pya", "pyu", "pyo", "bya", "byu", "byo", "mya", "myu", "myo", "rya", "ryu", "ryo" }; static const char *digit[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const char *symbol[] = { "!", "#", "@", "$", "%", "^", "&", "*", "?", "/" }; void jp_hash(char *out, const char *in) { unsigned char hash[32]; uint16_t word[9]; const char *ms[6]; const char *sym; const char *dig; char *ms0; int i; SHA256((const unsigned char *) in, strlen(in), hash); for (i = 0; i < elof(word); i++) word[i] = hash[2*i] | (((uint16_t) hash[2*i + 1]) << 8); for (i = 0; i < elof(ms); i++) ms[i] = mora[word[i] % elof(mora)]; dig = digit[word[6] % elof(digit)]; sym = symbol[word[7] % elof(symbol)]; ms0 = strdup(ms[0]); ms0[0] = toupper((unsigned char) ms0[0]); ms[0] = ms0; switch (word[8] & 7) { case 0: snprintf(out, 32, "%s%s%s%s%s%s%s%s", ms[0], ms[1], ms[2], sym, ms[3], ms[4], ms[5], dig); break; case 1: snprintf(out, 32, "%s%s%s%s%s%s%s%s", sym, ms[0], ms[1], ms[2], dig, ms[3], ms[4], ms[5]); break; case 2: snprintf(out, 32, "%s%s%s%s%s%s%s%s", ms[0], ms[1], sym, ms[2], ms[3], dig, ms[4], ms[5]); break; case 3: snprintf(out, 32, "%s%s%s%s%s%s%s%s", ms[0], ms[1], dig, ms[2], ms[3], sym, ms[4], ms[5]); break; case 4: snprintf(out, 32, "%s%s%sn%s%s%s%s%s", ms[0], ms[1], ms[2], sym, ms[3], ms[4], ms[5], dig); break; case 5: snprintf(out, 32, "%s%s%s%s%s%s%s%sn", sym, ms[0], ms[1], ms[2], dig, ms[3], ms[4], ms[5]); break; case 6: snprintf(out, 32, "%s%sn%s%s%s%s%s%s", ms[0], ms[1], sym, ms[2], ms[3], dig, ms[4], ms[5]); break; case 7: snprintf(out, 32, "%s%s%s%s%s%s%s%sn", ms[0], ms[1], dig, ms[2], ms[3], sym, ms[4], ms[5]); break; } free(ms0); } #if JP_HASH_MAIN int main(int argc, char **argv) { char jph[32]; if (argc != 2) { if (argc) fprintf(stderr, "%s: one argument required\n", argv[0]); return EXIT_FAILURE; } jp_hash(jph, argv[1]); puts(jph); return 0; } #endif // JP_HASH_MAIN #endif // JP_HASH_IMPL #endif // JP_HASH_H