Hash¶
Hashing is a one way method of converting arbitrary data into a fixed size format. Unlike ciphers, data that is hashed cannot be retrieved from the resulting digest. Hashes can be used to create keys, file identifiers, or store credentials.
Hash function diagram from Wikipedia.
Warning
Avoid storing password hashes if possible. If you must, please make sure to research the state of the art before continuing.
Make¶
To hash a string, use the hash
property on Droplet
.
let digest = try drop.hash.make("vapor") print(digest.makeString())
Checking¶
Some hashing algorithms create different hash digests for the same message. Because of this, it is necessary to check your hashes using the check
method.
let matches = try drop.hash.check("vapor", matchesHash: digest)
CryptoHasher¶
By default, Vapor uses a SHA-256 hasher. You can change this in the configuration files or by giving the Droplet
a different hasher.
Configuration¶
Config/droplet.json
{ ..., "hash": "crypto", ... }
Config/crypto.json
{ "hash": { "method": "sha256", "encoding": "hex", "key": "password" }, ... }
Encoding¶
The CryptoHasher supports three methods of encoding.
hex
base64
plain
Key¶
Supplying a key will cause the hasher to produce keyed hashes using HMAC. Some hashers require a key.
Supported¶
Name | Method | Requires Key |
---|---|---|
SHA-1 | sha1 | no |
SHA-224 | sha224 | no |
SHA-256 | sha256 | no |
SHA-384 | sha384 | no |
SHA-512 | sha512 | no |
MD4 | md4 | no |
MD5 | md5 | no |
RIPEMD-160 | ripemd160 | no |
Whirlpool | whirlpool | yes |
Streebog-256 | streebog256 | yes |
Streebog-512 | streebog512 | yes |
GostR341194 | gostr341194 | yes |
Manual¶
Hashers can be swapped without the use of configuration files.
Hash¶
let hash = CryptoHasher( hash: .sha256, encoding: .hex ) let drop = try Droplet(hash: hash)
HMAC¶
let hash = CryptoHasher( hmac: .sha256, encoding: .hex, key: "password".makeBytes() ) let drop = try Droplet(hash: hash)
BCryptHasher¶
BCrypt is a password hashing function that automatically incorporates salts and offers a configurable cost. The cost can be used to increase the computation required to generate a hash.
Seealso
Learn more about key stretching on Wikipedia.
Configuration¶
To use the BCryptHasher change the "hash"
key in the droplet.json
configuration file.
Config/droplet.json
{ ..., "hash": "bcrypt", ... }
To configure the cost, add a bcrypt.json
file.
Config/bcrypt.json
{ "cost": 8 }
Tip
You can use different BCrypt costs for production and development modes to keep password hashing fast while working on a project.
Manual¶
You can manually assign a BCryptHasher
to drop.hash
.
let hash = BCryptHasher(cost: 8) let drop = try Droplet(hash: hash)
Advanced¶
Custom¶
You can also create your own hasher. You just need to conform to the Hash
protocol.
/// Creates hash digests public protocol HashProtocol { /// Given a message, this method /// returns a hashed digest of that message. func make(_ message: Bytes) throws -> Bytes /// Checks whether a given digest was created /// by the supplied message. /// /// Returns true if the digest was created /// by the supplied message, false otherwise. func check(_ message: Bytes, matchesHash: Bytes) throws -> Bool }