Skip to content

[API Proposal]: Support Balloon Hashing #116263

@tats-u

Description

@tats-u

Background and motivation

#105745

PBKDF2 has no tolerance toward the offline attack using GPUs.
Unlike Argon2 (#19933), Balloon Hashing can be combined with existing standard hash functions like SHA-2.
Additional hash functions like Blake2 (#80900) to be implemented are unnecessary.

https://crypto.stanford.edu/balloon/

Used to be mentioned in the previous revision (3) of the draft of the next version of NIST SP 800-63B.

API Proposal

namespace System.Security.Cryptography;

public partial class BalloonHasher
{
    public HashAlgorithmName HashAlgorithm { get; }

    public BalloonHasher(HashAlgorithmName hashAlgorithm, int sCost, int tCost, int nThreads);
    public BalloonHahser(HashAlgorithmName hashAlgorithm, BalloonParameters parameters);

    public int SCost { get; set; }
    public int TCost { get; set; }
    public int NThreads { get; set; }

    public byte[] GetBytes(string passowrd, byte[] salt);
    public byte[] GetBytes(byte[] passowrd, byte[] salt);

    public byte[] GetBytes(ReadOnlySpan<char> password, ReadOnlySpan<byte> salt);
    public byte[] GetBytes(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt);

    public void GetBytes(ReadOnlySpan<char> password, ReadOnlySpan<byte> salt, Span<byte> hash);
    public void GetBytes(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, Span<byte> hash);
}

public partial class BalloonHahser
{
    public static byte[] Balloon(
        byte[] password,
        byte[] salt,
        HashAlgorithmName hashAlgorithm,
        BalloonParameters parameters);

    public static byte[] Balloon(
        ReadOnlySpan<byte> password,
        ReadOnlySpan<byte> salt,
        HashAlgorithmName hashAlgorithm,
        BalloonParameters parameters);

    public static void Balloon(
        ReadOnlySpan<byte> password,
        ReadOnlySpan<byte> salt,
        Span<byte> destination,
        HashAlgorithmName hashAlgorithm,
        BalloonParameters parameters);

    public static byte[] Balloon(
        string password,
        byte[] salt,
        HashAlgorithmName hashAlgorithm,
        BalloonParameters parameters);

    public static byte[] Balloon(
        ReadOnlySpan<char> password,
        ReadOnlySpan<byte> salt,
        HashAlgorithmName hashAlgorithm,
        BalloonParameters parameters);

    public static void Balloon(
        ReadOnlySpan<char> password,
        ReadOnlySpan<byte> salt,
        Span<byte> destination,
        HashAlgorithmName hashAlgorithm,
        BalloonParameters parameters);
}

public record struct BalloonParameters(
    int SCost,
    int TCost,
    int NThreads
);

API Usage

using System.Security.Cryprography;

// From https://docs.rs/balloon-hash/latest/balloon_hash/struct.Params.html#fields
var balloon = new BalloonHasher(HashAlgorithmName.SHA256, new BalloonParameters(1024, 3, 1));
var salt = RandomNumberGenerator.GetBytes(16);
var hash = balloon.GetBytess("P@$$w0rD", salt);

Alternative Designs

  • PBKDF2: requires huge number of iterations (100K+); no GPU attack tolerance (i.e. not memory-hard at all)
  • Argon2: best, but requires an additional hash functions to be implemented (Add support to blake2 and blake3 cryptographic hash functions #80900) and has not been approved by NIST
  • bcrypt: a little bit legacy, and has a input length limit and the same issues in Argon2
  • Yescrypt: has not been mentioned by NIST (apparently approved though). Only used by some recent Linux distributions (e.g. Ubuntu 22.04+, RHEL 10+, Arch, Fedora)

Risks

No risks other than runtime size increase.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions