1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Add modern SHA-2 based password hashes to pgcrypto.

This adapts the publicly available reference implementation on
https://www.akkadia.org/drepper/SHA-crypt.txt and adds the new hash
algorithms sha256crypt and sha512crypt to crypt() and gen_salt()
respectively.

Author: Bernd Helmle <mailings@oopsware.de>
Reviewed-by: Japin Li <japinli@hotmail.com>
Discussion: https://postgr.es/m/c763235a2757e2f5f9e3e27268b9028349cef659.camel@oopsware.de
This commit is contained in:
Álvaro Herrera
2025-04-05 19:16:58 +02:00
parent e33f2335a9
commit 749a9e20c9
9 changed files with 1114 additions and 2 deletions

View File

@ -185,3 +185,85 @@ _crypt_gensalt_blowfish_rn(unsigned long count,
return output;
}
/*
* Helper for _crypt_gensalt_sha256_rn and _crypt_gensalt_sha512_rn
*/
static char *
_crypt_gensalt_sha(unsigned long count,
const char *input, int size, char *output, int output_size)
{
char *s_ptr = output;
unsigned int result_bufsize = PX_SHACRYPT_SALT_BUF_LEN;
int rc;
/* output buffer must be allocated with PX_MAX_SALT_LEN bytes */
if (PX_MAX_SALT_LEN < result_bufsize)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid size of salt"));
/*
* Care must be taken to not exceed the buffer size allocated for the
* input character buffer.
*/
if ((PX_SHACRYPT_SALT_MAX_LEN != size) || (output_size < size))
ereport(ERROR,
errcode(ERRCODE_INTERNAL_ERROR),
errmsg("invalid length of salt buffer"));
/* Skip magic bytes, set by callers */
s_ptr += 3;
if ((rc = pg_snprintf(s_ptr, 18, "rounds=%ld$", count)) <= 0)
ereport(ERROR,
errcode(ERRCODE_INTERNAL_ERROR),
errmsg("cannot format salt string"));
/* s_ptr should now be positioned at the start of the salt string */
s_ptr += rc;
/*
* Normalize salt string
*
* size of input buffer was checked above to not exceed
* PX_SHACRYPT_SALT_LEN_MAX.
*/
for (int i = 0; i < size; i++)
{
*s_ptr = _crypt_itoa64[input[i] & 0x3f];
s_ptr++;
}
/* We're done */
return output;
}
/* gen_list->gen function for sha512 */
char *
_crypt_gensalt_sha512_rn(unsigned long count,
char const *input, int size,
char *output, int output_size)
{
memset(output, 0, output_size);
/* set magic byte for sha512crypt */
output[0] = '$';
output[1] = '6';
output[2] = '$';
return _crypt_gensalt_sha(count, input, size, output, output_size);
}
/* gen_list->gen function for sha256 */
char *
_crypt_gensalt_sha256_rn(unsigned long count,
const char *input, int size,
char *output, int output_size)
{
memset(output, 0, output_size);
/* set magic byte for sha256crypt */
output[0] = '$';
output[1] = '5';
output[2] = '$';
return _crypt_gensalt_sha(count, input, size, output, output_size);
}