feat(core): Add BLF-CRYPT scheme.

Dovecot promotes the use of BLF-CRYPT as a hashing scheme [1].
However, as not all libc-crypt() implementations support this scheme,
use the implementation added in a previous commit.

Also, update the references to the dovecot implementation and a small
test case for testing the blowfish implementation.

[1] https://doc.dovecot.org/configuration_manual/authentication/password_schemes/

Fixes #4958
This commit is contained in:
Nicolas Höft authored and Nicolas Höft committed 2020-05-15 07:43:38 +02:00
1 parent 562f81f21f
commit 8c612fc0a2
4 files changed
+89 -6

No files matched your search

+1
View File
@@ -53,6 +53,7 @@
- (NSData *) asCryptUsingSalt: (NSData *) theSalt;
- (NSData *) asMD5CryptUsingSalt: (NSData *) theSalt;
- (NSData *) asBlowfishCryptUsingSalt: (NSData *) theSalt;
- (NSData *) extractSalt: (NSString *) theScheme;
+58 -1
View File
@@ -1,6 +1,6 @@
/* NSData+Crypto.m - this file is part of SOGo
*
* Copyright (C) 2012 Nicolas Höft
* Copyright (C) 2012, 2020 Nicolas Höft
* Copyright (C) 2012-2020 Inverse inc.
* Copyright (C) 2012 Jeroen Dekkers
*
@@ -50,6 +50,7 @@
#endif
#include "aes.h"
#include "crypt_blowfish.h"
#include "lmhash.h"
#import <Foundation/NSArray.h>
@@ -62,6 +63,12 @@ static BOOL check_gnutls_init(void);
static void _nettle_md5_compress(uint32_t *digest, const uint8_t *input);
#endif
#define BLF_CRYPT_DEFAULT_COMPLEXITY (5)
#define BLF_CRYPT_SALT_LEN (16)
#define BLF_CRYPT_BUFFER_LEN (128)
#define BLF_CRYPT_PREFIX_LEN (7+22+1) /* $2.$nn$ + salt */
#define BLF_CRYPT_PREFIX "$2y"
@implementation NSData (SOGoCryptoExtension)
@@ -245,6 +252,10 @@ static void _nettle_md5_compress(uint32_t *digest, const uint8_t *input);
{
return [self asSHA512CryptUsingSalt: theSalt];
}
else if ([passwordScheme caseInsensitiveCompare: @"blf-crypt"] == NSOrderedSame)
{
return [self asBlowfishCryptUsingSalt: theSalt];
}
else if ([[passwordScheme lowercaseString] hasPrefix: @"sym"])
{
// We first support one sym cipher, AES-128-CBC. If something else is provided
@@ -764,6 +775,52 @@ static void _nettle_md5_compress(uint32_t *digest, const uint8_t *input);
return [NSData dataWithBytes: buf length: strlen(buf)];
}
/**
* Hash the data using blowfish-crypt
* @param theSalt The salt to be used must not be nil, if empty, one will be generated
*/
- (NSData *) asBlowfishCryptUsingSalt: (NSData *) theSalt
{
NSString *cleartext;
char hashed_password[BLF_CRYPT_BUFFER_LEN];
char magic_salt[BLF_CRYPT_PREFIX_LEN]; // contains $2.$nn$ + salt
if ([theSalt length] == 0)
{
// generate a salt with default complexity if none was provided
NSData* salt = [NSData generateSaltForLength: BLF_CRYPT_SALT_LEN];
if (_crypt_gensalt_blowfish_rn(BLF_CRYPT_PREFIX, BLF_CRYPT_DEFAULT_COMPLEXITY,
[salt bytes], BLF_CRYPT_SALT_LEN,
magic_salt, BLF_CRYPT_PREFIX_LEN) == NULL)
return nil;
}
else
{
const char* salt = [theSalt bytes];
if ([theSalt length] < BLF_CRYPT_PREFIX_LEN ||
salt[0] != '$' || salt[1] != '2' ||
salt[2] < 'a' || salt[2] > 'z' ||
salt[3] != '$')
{
return nil;
}
memcpy(magic_salt, salt, BLF_CRYPT_PREFIX_LEN);
}
cleartext = [[NSString alloc] initWithData: self encoding: NSUTF8StringEncoding];
const char* password = [cleartext UTF8String];
char* bf_res = _crypt_blowfish_rn(password, magic_salt,
hashed_password, BLF_CRYPT_BUFFER_LEN);
[cleartext autorelease];
if (bf_res == NULL)
return nil;
return [NSData dataWithBytes: hashed_password length: strlen(hashed_password)];
}
/**
* Get the salt from a password encrypted with a specied scheme
*