Skip to content

Instantly share code, notes, and snippets.

@oliver
Last active December 5, 2021 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oliver/4d9a1686b1530d6ff5256607affa82fe to your computer and use it in GitHub Desktop.
Save oliver/4d9a1686b1530d6ff5256607affa82fe to your computer and use it in GitHub Desktop.
moz_hash.py reimplements the getVerificationHash() method from Mozilla SearchUtils.jsm. fix_search_hash.py uses that to modify the search engine entry.
#!/usr/bin/env python3
#
# Adjusts the metaData.hash value in the supplied search.json.mozlz4 file to match the supplied profile path value.
#
import io
import json
import mozlz4a
import os
import moz_hash
import sys
if __name__ == "__main__":
inputFile = sys.argv[1]
newSearchEngineName = sys.argv[2]
with open(inputFile, "rb") as inFp:
data = mozlz4a.decompress(inFp)
jsonData = json.loads(data.decode("utf8"))
#print("old hash='%s'" % jsonData["metaData"]["hash"])
hashStr = moz_hash.getVerificationHash(os.path.dirname(inputFile), newSearchEngineName)
#print("new hash='%s'" % hashStr)
jsonData["metaData"]["hash"] = hashStr
jsonData["metaData"]["current"] = newSearchEngineName
newJsonData = json.dumps(jsonData)
newCompressedData = mozlz4a.compress(io.BytesIO(newJsonData.encode("utf8")))
with open(inputFile, "wb") as outFp:
outFp.write(newCompressedData)
#!/usr/bin/env python3
#
# Reimplements the getVerificationHash() method from https://hg.mozilla.org/mozilla-central/file/tip/toolkit/components/search/SearchUtils.jsm
#
import base64
import hashlib
import os
import sys
def getVerificationHash(profilePath, nameParam):
# the static disclaimer that is added to the hash
disclaimer = \
"By modifying this file, I agree that I am doing so " + \
"only within $appName itself, using official, user-driven search " + \
"engine selection processes, and in a way which does not circumvent " + \
"user consent. I acknowledge that any attempt to change this file " + \
"from outside of $appName is a malicious act, and will be responded " + \
"to accordingly.";
services_appinfo_name = "Firefox" # some magic value (Services.appinfo.name in Firefox code)
salt = os.path.basename(profilePath.rstrip("/")) + \
nameParam + \
disclaimer.replace("$appName", services_appinfo_name)
data = salt.encode("utf8")
hasher = hashlib.sha256()
hasher.update(data)
hash = hasher.digest()
return base64.encodebytes(hash).strip().decode("ascii")
if __name__ == "__main__":
profilePath = sys.argv[1] # path where profile is stored (this is used so that the hash is different for every profile)
nameParam = sys.argv[2] # the "payload" that shall be hashed
print(getVerificationHash(profilePath, nameParam))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment