Skip to content

Commit

Permalink
Fix calculation bug and add Convert to Signed
Browse files Browse the repository at this point in the history
A signed output is often needed for Shodan and other favicon searches.
  • Loading branch information
AliceGrey committed Feb 6, 2024
1 parent afcf465 commit cfc8a50
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 23 deletions.
72 changes: 49 additions & 23 deletions src/core/operations/MurmurHash3.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,33 @@ class MurmurHash3 extends Operation {
name: "Seed",
type: "number",
value: 0
},
{
name: "Convert to Signed",
type: "boolean",
value: false
}
];
}

/**
* Calculates the MurmurHash3 hash of the input.
* Based on Gary Court's JS MurmurHash implementation
* @see http://github.com/garycourt/murmurhash-js
* @author AliceGrey [[email protected]]
* @param {string} input ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
/**
* Calculates the MurmurHash3 hash of the input.
* Based on Gary Court's JS MurmurHash implementation
* @see http://github.com/garycourt/murmurhash-js
* @author AliceGrey [[email protected]]
* @param {string} input ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
mmh3(input, seed) {
let h1, h1b, k1, i;
let h1b;
let k1;
const remainder = input.length & 3; // input.length % 4
const bytes = input.length - remainder;
h1 = seed;
let h1 = seed;
const c1 = 0xcc9e2d51;
const c2 = 0x1b873593;
i = 0;
let i = 0;

while (i < bytes) {
k1 =
Expand All @@ -77,16 +83,19 @@ class MurmurHash3 extends Operation {
if (remainder === 3) {
k1 ^= (input.charCodeAt(i + 2) & 0xff) << 16;
}
if (remainder === 2) {

if (remainder === 3 || remainder === 2) {
k1 ^= (input.charCodeAt(i + 1) & 0xff) << 8;
}
if (remainder === 1) {

if (remainder === 3 || remainder === 2 || remainder === 1) {
k1 ^= (input.charCodeAt(i) & 0xff);

k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;

h1 ^= input.length;

Expand All @@ -99,19 +108,36 @@ class MurmurHash3 extends Operation {
return h1 >>> 0;
}

/**
* Converts an unsigned 32-bit integer to a signed 32-bit integer
* @author AliceGrey [[email protected]]
* @param {value} 32-bit unsigned integer
* @return {number} 32-bit signed integer
*/
unsignedToSigned(value) {
if (value & 0x80000000) {
return -0x100000000 + value;
} else {
return value;
}
}

/**
* @param {string} input
* @param {Object[]} args
* @returns {number}
*/
run(input, args) {
let seed;
if (args && args.length > 0) {
seed = args[0];
if (args && args.length >= 1) {
const seed = args[0];
const hash = this.mmh3(input, seed);
if (args.length > 1 && args[1]) {
return this.unsignedToSigned(hash);
}
return hash;
}
return this.mmh3(input, seed);
return this.mmh3(input);
}

}

export default MurmurHash3;
22 changes: 22 additions & 0 deletions tests/operations/tests/MurmurHash3.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,27 @@ TestRegister.addTests([
args: [1337],
},
],
},
{
name: "To MurmurHash3: foo",
input: "foo",
expectedOutput: "4138058784",
recipeConfig: [
{
op: "MurmurHash3",
args: [0],
},
],
},
{
name: "To MurmurHash3: foo signed",
input: "foo",
expectedOutput: "-156908512",
recipeConfig: [
{
op: "MurmurHash3",
args: [0, true],
},
],
}
]);

0 comments on commit cfc8a50

Please sign in to comment.