Index: src/th_main.c ================================================================== --- src/th_main.c +++ src/th_main.c @@ -935,10 +935,11 @@ ** "markdown" = FOSSIL_ENABLE_MARKDOWN ** "unicodeCmdLine" = !BROKEN_MINGW_CMDLINE ** "dynamicBuild" = FOSSIL_DYNAMIC_BUILD ** "mman" = USE_MMAN_H ** "see" = USE_SEE +** "hardenedSha1" = FOSSIL_HARDENED_SHA1 ** ** Specifying an unknown feature will return a value of false, it will not ** raise a script error. */ static int hasfeatureCmd( @@ -951,11 +952,11 @@ int rc = 0; const char *zArg; if( argc!=2 ){ return Th_WrongNumArgs(interp, "hasfeature STRING"); } - zArg = (const char *)argv[1]; + zArg = argv[1]; if(NULL==zArg){ /* placeholder for following ifdefs... */ } #if defined(FOSSIL_ENABLE_SSL) else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){ @@ -1022,10 +1023,15 @@ #endif #if defined(USE_SEE) else if( 0 == fossil_strnicmp( zArg, "see\0", 4 ) ){ rc = 1; } +#endif +#if FOSSIL_HARDENED_SHA1 + else if( 0 == fossil_strnicmp( zArg, "hardenedSha1\0", 13 ) ){ + rc = 1; + } #endif else if( 0 == fossil_strnicmp( zArg, "markdown\0", 9 ) ){ rc = 1; } if( g.thTrace ){ @@ -1032,10 +1038,64 @@ Th_Trace("[hasfeature %#h] => %d
\n", argl[1], zArg, rc); } Th_SetResultInt(interp, rc); return TH_OK; } + +/* +** TH1 command: hash STRING ?ALGORITHM? +** +** Returns the cryptographic hash of the specified string. Possible values +** for the ALGORITHM argument are: +** +** "md5" +** "sha1" +** "sha3-224" +** "sha3-256" +** "sha3-384" +** "sha3-512" +** +** The default algorithm is "sha3-256". Specifying an unknown algorithm +** will raise a script error. +*/ +static int hashCmd( + Th_Interp *interp, + void *p, + int argc, + const char **argv, + int *argl +){ + Blob content; + Blob cksum; + const char *zAlgorithm = "sha3-256"; + if( argc<2 || argc>3 ){ + return Th_WrongNumArgs(interp, "hash STRING ?ALGORITHM?"); + } + blob_init(&content, argv[1], argl[1]); + blob_zero(&cksum); + if( argc>=3 ){ + zAlgorithm = argv[2]; + } + if( 0 == fossil_strnicmp( zAlgorithm, "md5\0", 4 ) ){ + md5sum_blob(&content, &cksum); + }else if( 0 == fossil_strnicmp( zAlgorithm, "sha1\0", 5 ) ){ + sha1sum_blob(&content, &cksum); + }else if( 0 == fossil_strnicmp( zAlgorithm, "sha3-224\0", 9 ) ){ + sha3sum_blob(&content, 224, &cksum); + }else if( 0 == fossil_strnicmp( zAlgorithm, "sha3-256\0", 9 ) ){ + sha3sum_blob(&content, 256, &cksum); + }else if( 0 == fossil_strnicmp( zAlgorithm, "sha3-384\0", 9 ) ){ + sha3sum_blob(&content, 384, &cksum); + }else if( 0 == fossil_strnicmp( zAlgorithm, "sha3-512\0", 9 ) ){ + sha3sum_blob(&content, 512, &cksum); + }else{ + Th_SetResult(interp, "unknown hash algorithm", -1); + return TH_ERROR; + } + Th_SetResult(interp, blob_str(&cksum), -1); + return TH_OK; +} /* ** TH1 command: tclReady ** @@ -2341,10 +2401,11 @@ {"glob_match", globMatchCmd, 0}, {"globalState", globalStateCmd, 0}, {"httpize", httpizeCmd, 0}, {"hascap", hascapCmd, (void*)&zeroInt}, {"hasfeature", hasfeatureCmd, 0}, + {"hash", hashCmd, 0}, {"html", putsCmd, (void*)&aFlags[0]}, {"htmlize", htmlizeCmd, 0}, {"http", httpCmd, 0}, {"insertCsrf", insertCsrfCmd, 0}, {"linecount", linecntCmd, 0}, Index: test/th1.test ================================================================== --- test/th1.test +++ test/th1.test @@ -1696,9 +1696,62 @@ # unversioned content fossil test-th-eval --open-config \ {string length [unversioned content ten.txt]} test th1-unversioned-2 {$RESULT eq {10}} + +############################################################################### + +fossil test-th-eval {hash foo} +test th1-hash-1 {$RESULT eq \ +"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01"} + +############################################################################### + +fossil test-th-eval {hash foo bad} +test th1-hash-2 {$RESULT eq "TH_ERROR: unknown hash algorithm"} + +############################################################################### + +fossil test-th-eval {hash foo md5} +test th1-hash-3 {$RESULT eq "acbd18db4cc2f85cedef654fccc4a4d8"} + +############################################################################### + +fossil test-th-eval {hash foo md5 bad} +test th1-hash-4 {$RESULT eq \ +"TH_ERROR: wrong # args: should be \"hash STRING ?ALGORITHM?\""} + +############################################################################### + +fossil test-th-eval {hash foo sha1} +test th1-hash-5 {$RESULT eq "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"} + +############################################################################### + +fossil test-th-eval {hash foo sha3-224} +test th1-hash-6 {$RESULT eq \ +"f4f6779e153c391bbd29c95e72b0708e39d9166c7cea51d1f10ef58a"} + +############################################################################### + +fossil test-th-eval {hash foo sha3-256} +test th1-hash-7 {$RESULT eq \ +"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01"} + +############################################################################### + +fossil test-th-eval {hash foo sha3-384} +test th1-hash-8 {$RESULT eq [appendArgs \ +665551928d13b7d84ee02734502b018d896a0fb87eed5adb4c87ba91bbd6489410e11b0fbcc06 \ +ed7d0ebad559e5d3bb5]} + +############################################################################### + +fossil test-th-eval {hash foo sha3-512} +test th1-hash-9 {$RESULT eq [appendArgs \ +4bca2b137edc580fe50a88983ef860ebaca36c857b1f492839d6d7392452a63c82cbebc68e3b7 \ +0a2a1480b4bb5d437a7cba6ecf9d89f9ff3ccd14cd6146ea7e7]} ############################################################################### test_cleanup Index: win/fossil.rc ================================================================== --- win/fossil.rc +++ win/fossil.rc @@ -98,10 +98,17 @@ VALUE "DynamicBuild", "Yes\0" #else VALUE "DynamicBuild", "No\0" #endif VALUE "ZlibVersion", "zlib " ZLIB_VERSION "\0" +#if FOSSIL_HARDENED_SHA1 + VALUE "Sha1", "Hardened-SHA1 by Marc Stevens and Dan Shumow\0" +#elif defined(FOSSIL_ENABLE_SSL) + VALUE "Sha1", "OpenSSL-SHA1\0" +#else + VALUE "Sha1", "Legacy-SHA1\0" +#endif /* FOSSIL_HARDENED_SHA1 */ #if defined(BROKEN_MINGW_CMDLINE) VALUE "CommandLineIsUnicode", "No\0" #else VALUE "CommandLineIsUnicode", "Yes\0" #endif /* defined(BROKEN_MINGW_CMDLINE) */ Index: www/th1.md ================================================================== --- www/th1.md +++ www/th1.md @@ -190,10 +190,11 @@ * [getParameter](#getParameter) * [glob\_match](#glob_match) * [globalState](#globalState) * [hascap](#hascap) * [hasfeature](#hasfeature) + * [hash](#hash) * [html](#html) * [htmlize](#htmlize) * [http](#http) * [httpize](#httpize) * [insertCsrf](#insertCsrf) @@ -519,13 +520,32 @@ 1. **markdown** -- _Support for Markdown documentation format._ 1. **unicodeCmdLine** -- _The command line arguments are Unicode._ 1. **dynamicBuild** -- _Dynamically linked to libraries._ 1. **mman** -- _Uses POSIX memory APIs from "sys/mman.h"._ 1. **see** -- _Uses the SQLite Encryption Extension._ + 1. **hardenedSha1** -- _Uses the Hardened-SHA1 implementation._ Specifying an unknown feature will return a value of false, it will not raise a script error. + +TH1 hash Command +--------------------------------- + + * hash STRING ?ALGORITHM? + +Returns the cryptographic hash of the specified string. Possible values +for the ALGORITHM argument are: + + 1. **md5** + 1. **sha1** + 1. **sha3-224** + 1. **sha3-256** + 1. **sha3-384** + 1. **sha3-512** + +The default algorithm is "sha3-256". Specifying an unknown algorithm +will raise a script error. TH1 html Command ----------------------------------- * html STRING