c2e25edbf8c48361a71398664ec0c279d5fc58f5
braney
  Sat Sep 19 18:11:31 2026 -0700
hmacTest: pin the signature hgLogin puts on a pending social identity

hgLogin signs a pending social identity with hmacMd5(login.cookieSalt, fields)
and hands the signature to the browser in the account chooser, so a forgeable
signature lets an attacker choose whose account the chooser links to.  Nothing
about the page looks different either way.

Before #37984 that signature was a plain MD5 of the salt concatenated in front
of the same fields, and a hash of a secret followed by attacker-chosen text is
the wrong shape for the job.  boundaryMoves() is the case that says so: with
concatenation, hmacMd5("a", "bc") and hmacMd5("ab", "c") hash the same bytes
and sign the same, while HMAC keeps them apart.

Known answers are RFC 2202 test case 2 for MD5 and SHA1, cross-checked here
with the openssl command line.  Only the string-keyed vectors from the RFC can
be used, since this interface takes key and data as C strings.

Watched to fail and then pass: putting hmacMd5 back to the concatenation shape
turns the known answer red and makes the two boundary cases identical, both of
which the test catches.  Recorded as sandbox-ab in utils/testRegistry.

refs #37984, refs #38391

diff --git src/lib/tests/makefile src/lib/tests/makefile
index 20bbd0ecd38..6af34921040 100644
--- src/lib/tests/makefile
+++ src/lib/tests/makefile
@@ -1,39 +1,47 @@
 kentSrc = ../..
 include ../../inc/common.mk
 
 MYLIBDIR = ../../lib/${MACHTYPE}
 MYLIBS = ${MYLIBDIR}/jkweb.a
 BIN_DIR = bin/${MACHTYPE}
 
 pipelineTester = ${BIN_DIR}/pipelineTester
 
 test: errCatchTest htmlPageTest htmlExpandUrlTest htmlSanitizeTest pipelineTests dyStringTest \
     mimeTests base64Tests quotedPTests safeTest hashTest fetchUrlTest gff3Test \
     tabixTest vcfTest hacTreeTest mmHashTest testSumDoubles jsonQueryTest \
-    dnaCodonTest pathSimplifyTest faSpeedReadTest cgiParseTest cgiCookieTest
+    dnaCodonTest pathSimplifyTest faSpeedReadTest cgiParseTest cgiCookieTest \
+    hmacTest
 	rm -r output fetchUrlTest testSumDoubles
 	@echo tested all
 
 
 mkdirs:
 	${MKDIR} output ${BIN_DIR}
 
 testSumDoubles: testSumDoubles.o ${MYLIBS}
 	@${MKDIR} $(dir $@)
 	${CC} ${COPT} -o ./testSumDoubles testSumDoubles.o ${MYLIBS} ${L}
 
+hmacTest: hmacTest.o ${MYLIBS} mkdirs
+	@${MKDIR} $(dir $@)
+	${CC} ${COPT} -o ${BIN_DIR}/hmacTest hmacTest.o ${MYLIBS} ${L}
+	${STRIP} ${BIN_DIR}/hmacTest${EXE}
+	${BIN_DIR}/hmacTest > output/hmacTest
+	diff expected/hmacTest output/hmacTest
+
 pathSimplifyTest: pathSimplifyTest.o ${MYLIBS} mkdirs
 	@${MKDIR} $(dir $@)
 	${CC} ${COPT} -o ${BIN_DIR}/pathSimplifyTest pathSimplifyTest.o ${MYLIBS} ${L}
 	${STRIP} ${BIN_DIR}/pathSimplifyTest${EXE}
 	${BIN_DIR}/pathSimplifyTest > output/pathSimplifyTest
 	diff expected/pathSimplifyTest output/pathSimplifyTest
 
 faSpeedReadTest: faSpeedReadTest.o ${MYLIBS} mkdirs
 	@${MKDIR} $(dir $@)
 	${CC} ${COPT} -o ${BIN_DIR}/faSpeedReadTest faSpeedReadTest.o ${MYLIBS} ${L}
 	${STRIP} ${BIN_DIR}/faSpeedReadTest${EXE}
 	${BIN_DIR}/faSpeedReadTest > output/faSpeedReadTest
 	diff expected/faSpeedReadTest output/faSpeedReadTest
 
 dnaCodonTest: dnaCodonTest.o ${MYLIBS} mkdirs