17

I'm trying to find a bcrypt implementation I can use in Delphi. About the only useful thing that Googling brings me is this download page, containing translated headers for a winapi unit called bcrypt.h. But when I look at the functionality it provides, bcrypt.h doesn't appear to actually contain any way to use the Blowfish algorithm to hash passwords!

I've found a few bcrypt implementations in C that I could build a DLL from and link to, except they seem to all require *nix or be GCC-specific, so that won't work either!

This is sorta driving me up the wall. I'd think that it would be easy to find an implementation, but that doesn't seem to be the case at all. Does anyone know where I could get one?

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • 2
    Are you prepared to contemplate the Windows bcrypt introduced in Vista? JEDI has a header translation: JwaBCrypt.pas – David Heffernan Mar 14 '12 at 22:11
  • @David: This appears to be another translation of the `bcrypt.h` winapi header I mentioned in the question, the one that doesn't actually appear to contain a Blowfish password-hashing implementation. (Or am I missing something?) – Mason Wheeler Mar 14 '12 at 22:21
  • Rudy's header is the origin of the JEDI one, http://blog.delphi-jedi.net/2008/03/10/new-and-additional-header-files-from-rudy/ – LU RD Mar 14 '12 at 22:33
  • The header translations provide access to bcrypt.dll. You can either acquire a copy of that DLL, or you can build it yourself. If the source code you find for it only works with GCC, then you can acquire GCC and build it; otherwise, use the C compiler of your choice. There's no shortage of them. – Rob Kennedy Mar 15 '12 at 04:26
  • There are plenty of libraries that implement Blowfish algorithm in Delphi: http://www.torry.net/pages.php?id=519 – Torbins Mar 15 '12 at 10:43
  • Isn't BCRYPT just a Mime64 encrypted (ascii) hash using Blowfish? – Warren P Mar 15 '12 at 13:07
  • 1
    @rob the DLL is a Windows system DLL – David Heffernan Mar 15 '12 at 22:11

1 Answers1

24

Okay, so i wrote it.

Usage:

hash: string;
hash := TBCrypt.HashPassword('mypassword01');

returns something like:

$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm 

The useful thing about this (OpenBSD) style password hash is:

  • that it identifies the algorithm (2a = bcrypt)
  • the salt is automatically created for you, and shipped with the hash (Ro0CUfOqk6cXEKf3dyaM7O)
  • the cost factor parameter is also carried with the hash (10).

To check a password is correct:

isValidPassword: Boolean;
isValidPassword := TBCrypt.CheckPassword('mypassword1', hash);

BCrypt uses a cost factor, which determines how many iterations the key setup will go though. The higher the cost, the more expensive it is to compute the hash. The constant BCRYPT_COST contains the default cost:

const
   BCRYPT_COST = 10; //cost determintes the number of rounds. 10 = 2^10 rounds (1024)

In this case a cost of 10 means the key will be expanded and salted 210=1,024 rounds. This is the commonly used cost factor at this point in time (early 21st century).

It is also interesting to note that, for no known reason, OpenBSD hashed passwords are converted to a Base-64 variant that is different from the Base64 used by everyone else on the planet. So TBCrypt contains a custom base-64 encoder and decoder.

It's also useful to note that the hash algorithm version 2a is used to mean:

  • bcrypt
  • include the password's null terminator in the hashed data
  • unicode strings are UTF-8 encoded

So that is why the HashPassword and CheckPassword functions take a WideString (aka UnicodeString), and internally convert them to UTF-8. If you're running this on a version of Delphi where UnicodeString is a reserved word, then simply define out:

type
   UnicodeString = WideString;

i, as David Heffernan knows, don't own Delphi XE 2. i added the UnicodeString alias, but didn't include compilers.inc and define away UnicodeString (since i don't know the define name, nor could i test it). What do you want from free code?

The code comprises of two units:

  • Bcrypt.pas (which i wrote, with embedded DUnit tests)
  • Blowfish.pas (which Dave Barton wrote, which i adapted, extended, fixed some bugs and added DUnit tests to).

Where on the intertubes can i put some code where it can live in perpetuity?

Update 1/1/2015: It was placed onto GitHub some time ago: BCrypt for Delphi.

Bonus 4/16/2015: There is now Scrypt for Delphi

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 3
    Perpetuity? Nowhere really. But SourceForge, Google Code, GitHub, or BitBucket are good candidates that should be around for a good long while. – afrazier May 04 '12 at 04:16
  • For now the filenames in the answer (`bcrypt.pas`, `blowfish.pas`) link to pastebin. – Ian Boyd May 04 '12 at 13:26
  • Really should put this on Bitbucket! – Warren P Sep 27 '12 at 03:01
  • 1
    @WarrenP Now i remember why i didn't use BitBucket. In order to upload the code i have to register, and download their source control client? It's just two files! – Ian Boyd Sep 28 '12 at 20:39
  • You can either fork that one, if you create a bitbucket account, or you can send me your email and I'll add you on that one, if you ever find a bug you want to fix. And it's more than 2 files if you want users to be able to just open a project group containing a demo and a unit test project. Which I think is worth doing, so I added those. – Warren P Sep 29 '12 at 14:23
  • A bit late, +1 for the nice answer and great work. I'll be using your units from now to hash passwords. – jachguate Apr 17 '13 at 23:18