Hashes and Salts. You may of heard of them, but you may not know what they are. So here I will be explaining to you what hashes and salts are.
Disclaimer: if you do not know what hashes or salts are, I recommend these 2 videos:
Hashes Explained and Salts explained.
The purpose of Hashes
Moving on, first we need to know what the purposes of hashes and salts are.
Lets say, You have an account system on your website. You will of course need to store your user’s passwords. But how should you do it?
That is where Hashes come to play. Their purpose is to convert strings into what may look like a random line of numbers and letters, a hash. But here is the catch. Hashes cannot be converted back to their original string.
So how can they be useful to store? You may ask. Well, when the User inputs their password, it would be hashed and then compared to the stored hash for that user. If the hashes are the same, then the password will be the same, allowing the user to enter.
The purpose of Salts
Salts are just a random string of letters and characters that are attached and unique to the user. An example salt would be: iaih124naow240124
. Instead of hashing the password, it hashes the password+the salt. so a password like password123!
would be password123!iaih124naow240124
, which would make it longer, and thus more secure.
A basic diagram of how it works:
How to make it in Roblox:
DISCLAIMER
This is not a proper hashing algorithm, but just a cashe-backed string asigner. I will update this with a proper bit32-orientated algorithm into my SimpleBit Module.
As of making this, Roblox does not have a built-in hashing fuction. So here I will be showing you how to make a simple hash function.
Step 1: What to create
First, we will need to make a RemoteEvent
object.
Lets parent it to ReplicatedStorage and name it: HashEvent
Step 2: Create the script
We will create a Script
object.
It will be parented to ServerScriptService. Lets name it HashScript
Step3: Creating a hash system.
Unlike regular hashing algorithms, that usually have hundreds to thousands of line, we will be making a more simpler hashing system. Inputed strings are hashed and then their hash is stored.
To get the first things out of the way. We need to add some variables.
local HashFunction = game.ReplicatedStorage.HashEvent -- The Event object that we will use to connect to the client.
local StoredHashes = {} -- This table stores all of the hashes.
local HashLengh = 5 -- how long our hash will be in terms of characters
Next, we would need a function to generate hashes.
local function GenerateHash(player:Player,Input:string) -- this will generate a random hash we can assign to our string
local LegalCharacters = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz123456789" -- the characters that our hash will consist of
local Hash = ""
for HashStepsDone=1,HashLengh do
local RandomNumber = math.random(1,LegalCharacters) -- creates a random number for a character
local RandomCharacter = string.sub(LegalCharacters,RandomNumber,RandomNumber) -- gets the character
Hash..=RandomCharacter -- adds the random character onto our hash
end
if not HashLengh[Hash] then
HashLengh[Hash] = Input
HashEvent:FireClient(player,Hash)
else
GenerateHash(Input)
end
end
Just incase there are any errors, we will pcall
the function.
local LegalCharacters = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz123456789"
A list of characters that the hash can consist of.
for HashStepsDone=1,HashLengh do
local RandomNumber = math.random(1,#LegalCharacters) -- creates a random number for a character
local RandomCharacter = string.sub(LegalCharacters,RandomNumber,RandomNumber) -- gets the character
Hash..=RandomCharacter -- adds the random character onto our hash
end
Adds a specified amount of random character from the list of characters to the hash.
if not StoredHashes[Hash] then
HashLengh[Hash] = Input
HashEvent:FireClient(player,Hash)
else
GenerateHash(Input)
end
Checks if there is already a value with the same hash.
This may look good already, but there is one thing that we need to add.
You see, every time a hash is added, even if the value is same, it will still make a seperate hash. To combat this, we will add this loop:
for hash, stringValue in pairs(StoredHashes) do -- checks if there is already a hash for that object
task.wait()
if stringValue == Input then
HashEvent:FireClient(player,hash)
end
end
It goes through the stored hashes and checks if there is a hash with the same value. And if there is, it returns that hash.
We would also have to modify our hash checker, to check if the same hash has the same value.
if not StoredHashes[Hash] then
if StoredHashes[Hash] == Input then
HashEvent:FireClient(player,Hash)
end
else
if StoredHashes[Hash] == Input then
HashEvent:FireClient(player,Hash)
else
GenerateHash(Input)
end
end
And of course, we would need to connect our function to the RemoteEvent
HashEvent.OnServerEvent:Connect(GenerateHash)
Output example:
"abc123"
→ "8ph7v"
Entire script
local HashEvent = game.ReplicatedStorage.HashEvent -- The function object that we will use to connect to the client.
local StoredHashes = {} -- This table stores all of the hashes.
local HashLengh = 5 -- how long our hash will be in terms of characters
function GenerateHash(player:Player,Input:string) -- this will generate a random hash we can assign to our string
local success, errorMessage = pcall(function()
local LegalCharacters = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz123456789" -- the characters that our hash will consist of
local Hash = ""
for hash, stringValue in pairs(StoredHashes) do -- checks if there is already a hash for that object
task.wait()
if stringValue == Input then
HashEvent:FireClient(player,hash)
end
end
for HashStepsDone=1,HashLengh do
local RandomNumber = math.random(1,#LegalCharacters) -- creates a random number for a character
local RandomCharacter = string.sub(LegalCharacters,RandomNumber,RandomNumber) -- gets the character
Hash..=RandomCharacter -- adds the random character onto our hash
end
if not StoredHashes[Hash] then
StoredHashes[Hash] = Input
HashEvent:FireClient(player,Hash)
else
if StoredHashes[Hash] == Input then
HashEvent:FireClient(player,Hash)
else
GenerateHash(player,Input)
end
end
end)
if not success then warn(errorMessage) end
end
HashEvent.OnServerEvent:Connect(GenerateHash)
REMEMBER!
Like I said, this is a cashe-backed up string assigner and should NOT be used for security.
It is mainly just to showcase what simple Hashes would look like.
I will be making a new updated tutorial on a proper hashing algorithm that would work on the lua Bit32 libary.