Hashing Guide
Hashing Guide
FraudHosting only accepts hashed identifiers. Never send raw PII—hash it locally using the official algorithm described below.
Algorithm Specification
- Pre-process the value:
- Trim whitespace.
- For most fields: remove internal spaces and lowercase the value.
- For passwords or intentionally case-sensitive fields, skip the lowercase/strip step.
- Prefix with
"fraudhosting-"
. - Apply SHA-1.
- Repeat steps 2–3 a total of 32,000 times.
Pseudocode:
function fraudHostingHash(value, preserveOriginal = false) {
let prepared = value.trim();
if (!preserveOriginal) {
prepared = prepared.replace(/\s+/g, '').toLowerCase();
}
for (let i = 0; i < 32000; i++) {
prepared = sha1('fraudhosting-' + prepared);
}
return prepared;
}
Field Guidelines
Field | Pre-processing | Notes |
---|---|---|
name | lowercase, remove spaces | Combine first+last name before hashing. |
lowercase, remove spaces | Provide variants (email2 , email3 , …) if needed. | |
ip | lowercase (convert IPv6 to canonical form) | Keep dots/colons; do not strip them. |
phone | remove spaces, keep punctuation | Consider normalising + country code. |
password | preserve original | No lowercasing or space removal. |
domain | lowercase, remove protocol | Hash bare domain or subdomain. |
Variable names must be 1–16 characters (a-z
, optional digits at the end, dash allowed). Append suffixes (email2
, email3
) for multiple values with the same key.
Reference Implementations
function fraudhosting_hash(string $value, bool $preserveOriginal = false): string
{
$prepared = trim($value);
if (! $preserveOriginal) {
$prepared = strtolower(str_replace(' ', '', $prepared));
}
for ($i = 0; $i < 32000; $i++) {
$prepared = sha1('fraudhosting-' . $prepared);
}
return $prepared;
}
import hashlib
def fraudhosting_hash(value: str, preserve_original: bool = False) -> str:
prepared = value.strip()
if not preserve_original:
prepared = prepared.replace(" ", "").lower()
for _ in range(32000):
prepared = hashlib.sha1(f"fraudhosting-{prepared}".encode()).hexdigest()
return prepared
#include <algorithm>
#include <cctype>
#include <openssl/sha.h>
#include <iomanip>
#include <sstream>
#include <string>
std::string sha1_hex(const std::string& input)
{
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(reinterpret_cast<const unsigned char*>(input.c_str()), input.size(), hash);
std::ostringstream oss;
for (unsigned char c : hash) {
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c);
}
return oss.str();
}
std::string fraudhosting_hash(std::string value, bool preserveOriginal = false)
{
if (!preserveOriginal) {
// trim
value.erase(0, value.find_first_not_of(" \t\n\r"));
value.erase(value.find_last_not_of(" \t\n\r") + 1);
// remove spaces
value.erase(std::remove_if(value.begin(), value.end(), ::isspace), value.end());
// lowercase
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
}
for (int i = 0; i < 32000; ++i) {
value = sha1_hex("fraudhosting-" + value);
}
return value;
}
package fraudhash
import (
"crypto/sha1"
"encoding/hex"
"strings"
)
func Hash(value string, preserveOriginal bool) string {
prepared := strings.TrimSpace(value)
if !preserveOriginal {
prepared = strings.ReplaceAll(prepared, " ", "")
prepared = strings.ToLower(prepared)
}
for i := 0; i < 32000; i++ {
h := sha1.Sum([]byte("fraudhosting-" + prepared))
prepared = hex.EncodeToString(h[:])
}
return prepared
}
Worked Example
Input -> alan.ross@example.com
Normalise -> alan.ross@example.com (already lowercase, no spaces)
Hash iterations -> apply salted SHA-1 loop 32,000 times
Result -> 34efd0a968b48cbf9a43ac3e73053e4f34323400
Keep the hashing library consistent across languages to avoid subtle differences (especially in Unicode handling). Test conversions once and cache hashes locally to avoid repeated 32k iteration runs where performance matters.