Skip to content

Commit 749a9e2

Browse files
committed
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
1 parent e33f233 commit 749a9e2

File tree

9 files changed

+1114
-2
lines changed

9 files changed

+1114
-2
lines changed

contrib/pgcrypto/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ OBJS = \
1111
crypt-des.o \
1212
crypt-gensalt.o \
1313
crypt-md5.o \
14+
crypt-sha.o \
1415
mbuf.o \
1516
openssl.o \
1617
pgcrypto.o \
@@ -43,7 +44,7 @@ REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
4344
sha2 des 3des cast5 \
4445
crypt-des crypt-md5 crypt-blowfish crypt-xdes \
4546
pgp-armor pgp-decrypt pgp-encrypt pgp-encrypt-md5 $(CF_PGP_TESTS) \
46-
pgp-pubkey-decrypt pgp-pubkey-encrypt pgp-info
47+
pgp-pubkey-decrypt pgp-pubkey-encrypt pgp-info crypt-shacrypt
4748

4849
ifdef USE_PGXS
4950
PG_CONFIG = pg_config

contrib/pgcrypto/crypt-gensalt.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,85 @@ _crypt_gensalt_blowfish_rn(unsigned long count,
185185

186186
return output;
187187
}
188+
189+
/*
190+
* Helper for _crypt_gensalt_sha256_rn and _crypt_gensalt_sha512_rn
191+
*/
192+
static char *
193+
_crypt_gensalt_sha(unsigned long count,
194+
const char *input, int size, char *output, int output_size)
195+
{
196+
char *s_ptr = output;
197+
unsigned int result_bufsize = PX_SHACRYPT_SALT_BUF_LEN;
198+
int rc;
199+
200+
/* output buffer must be allocated with PX_MAX_SALT_LEN bytes */
201+
if (PX_MAX_SALT_LEN < result_bufsize)
202+
ereport(ERROR,
203+
errcode(ERRCODE_SYNTAX_ERROR),
204+
errmsg("invalid size of salt"));
205+
206+
/*
207+
* Care must be taken to not exceed the buffer size allocated for the
208+
* input character buffer.
209+
*/
210+
if ((PX_SHACRYPT_SALT_MAX_LEN != size) || (output_size < size))
211+
ereport(ERROR,
212+
errcode(ERRCODE_INTERNAL_ERROR),
213+
errmsg("invalid length of salt buffer"));
214+
215+
/* Skip magic bytes, set by callers */
216+
s_ptr += 3;
217+
if ((rc = pg_snprintf(s_ptr, 18, "rounds=%ld$", count)) <= 0)
218+
ereport(ERROR,
219+
errcode(ERRCODE_INTERNAL_ERROR),
220+
errmsg("cannot format salt string"));
221+
222+
/* s_ptr should now be positioned at the start of the salt string */
223+
s_ptr += rc;
224+
225+
/*
226+
* Normalize salt string
227+
*
228+
* size of input buffer was checked above to not exceed
229+
* PX_SHACRYPT_SALT_LEN_MAX.
230+
*/
231+
for (int i = 0; i < size; i++)
232+
{
233+
*s_ptr = _crypt_itoa64[input[i] & 0x3f];
234+
s_ptr++;
235+
}
236+
237+
/* We're done */
238+
return output;
239+
}
240+
241+
/* gen_list->gen function for sha512 */
242+
char *
243+
_crypt_gensalt_sha512_rn(unsigned long count,
244+
char const *input, int size,
245+
char *output, int output_size)
246+
{
247+
memset(output, 0, output_size);
248+
/* set magic byte for sha512crypt */
249+
output[0] = '$';
250+
output[1] = '6';
251+
output[2] = '$';
252+
253+
return _crypt_gensalt_sha(count, input, size, output, output_size);
254+
}
255+
256+
/* gen_list->gen function for sha256 */
257+
char *
258+
_crypt_gensalt_sha256_rn(unsigned long count,
259+
const char *input, int size,
260+
char *output, int output_size)
261+
{
262+
memset(output, 0, output_size);
263+
/* set magic byte for sha256crypt */
264+
output[0] = '$';
265+
output[1] = '5';
266+
output[2] = '$';
267+
268+
return _crypt_gensalt_sha(count, input, size, output, output_size);
269+
}

0 commit comments

Comments
 (0)