+1 to adding a SHA1 SQL function. Even if it's deprecated, there's plenty of historical usage that I can see it being useful.
Either way, the rest of the refactor can be improved a bit to perform a single palloc() and remove the memcpy(). Attached is a diff for cryptohashfuncs.c that does that by writing the digest final directly to the result. It also removes the digest length arg and determines it in the switch block. There's only one correct digest length for each type so there's no reason to give callers the option to give the wrong one. Regards, -- Sehrope Sarkuni Founder & CEO | JackDB, Inc. | https://www.jackdb.com/
diff --git a/src/backend/utils/adt/cryptohashfuncs.c b/src/backend/utils/adt/cryptohashfuncs.c index d99485f4c6..8dc695e80c 100644 --- a/src/backend/utils/adt/cryptohashfuncs.c +++ b/src/backend/utils/adt/cryptohashfuncs.c @@ -15,6 +15,7 @@ #include "common/cryptohash.h" #include "common/md5.h" +#include "common/sha1.h" #include "common/sha2.h" #include "utils/builtins.h" @@ -68,6 +69,77 @@ md5_bytea(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(cstring_to_text(hexsum)); } +/* + * Internal routine to compute a cryptohash with the given bytea input. + */ +static inline bytea * +cryptohash_internal(pg_cryptohash_type type, bytea *input) +{ + const uint8 *data; + const char *typestr; + int digest_len; + size_t len; + pg_cryptohash_ctx *ctx; + bytea *result; + + switch (type) + { + case PG_MD5: + typestr = "MD5"; + digest_len = MD5_DIGEST_LENGTH; + break; + case PG_SHA1: + typestr = "SHA1"; + digest_len = SHA1_DIGEST_LENGTH; + break; + case PG_SHA224: + typestr = "SHA224"; + digest_len = PG_SHA224_DIGEST_LENGTH; + break; + case PG_SHA256: + typestr = "SHA256"; + digest_len = PG_SHA256_DIGEST_LENGTH; + break; + case PG_SHA384: + typestr = "SHA384"; + digest_len = PG_SHA384_DIGEST_LENGTH; + break; + case PG_SHA512: + typestr = "SHA512"; + digest_len = PG_SHA512_DIGEST_LENGTH; + break; + default: + elog(ERROR, "unsupported digest type %d", type); + } + + result = palloc0(digest_len + VARHDRSZ); + len = VARSIZE_ANY_EXHDR(input); + data = (unsigned char *) VARDATA_ANY(input); + + ctx = pg_cryptohash_create(type); + if (pg_cryptohash_init(ctx) < 0) + elog(ERROR, "could not initialize %s context", typestr); + if (pg_cryptohash_update(ctx, data, len) < 0) + elog(ERROR, "could not update %s context", typestr); + if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result)) < 0) + elog(ERROR, "could not finalize %s context", typestr); + pg_cryptohash_free(ctx); + + SET_VARSIZE(result, digest_len + VARHDRSZ); + + return result; +} + +/* + * SHA-1 + */ +Datum +sha1_bytea(PG_FUNCTION_ARGS) +{ + bytea *result = cryptohash_internal(PG_SHA1, PG_GETARG_BYTEA_PP(0)); + + PG_RETURN_BYTEA_P(result); +} /* * SHA-2 variants @@ -76,28 +148,7 @@ md5_bytea(PG_FUNCTION_ARGS) Datum sha224_bytea(PG_FUNCTION_ARGS) { - bytea *in = PG_GETARG_BYTEA_PP(0); - const uint8 *data; - size_t len; - pg_cryptohash_ctx *ctx; - unsigned char buf[PG_SHA224_DIGEST_LENGTH]; - bytea *result; - - len = VARSIZE_ANY_EXHDR(in); - data = (unsigned char *) VARDATA_ANY(in); - - ctx = pg_cryptohash_create(PG_SHA224); - if (pg_cryptohash_init(ctx) < 0) - elog(ERROR, "could not initialize %s context", "SHA224"); - if (pg_cryptohash_update(ctx, data, len) < 0) - elog(ERROR, "could not update %s context", "SHA224"); - if (pg_cryptohash_final(ctx, buf) < 0) - elog(ERROR, "could not finalize %s context", "SHA224"); - pg_cryptohash_free(ctx); - - result = palloc(sizeof(buf) + VARHDRSZ); - SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); - memcpy(VARDATA(result), buf, sizeof(buf)); + bytea *result = cryptohash_internal(PG_SHA224, PG_GETARG_BYTEA_PP(0)); PG_RETURN_BYTEA_P(result); } @@ -105,28 +156,7 @@ sha224_bytea(PG_FUNCTION_ARGS) Datum sha256_bytea(PG_FUNCTION_ARGS) { - bytea *in = PG_GETARG_BYTEA_PP(0); - const uint8 *data; - size_t len; - pg_cryptohash_ctx *ctx; - unsigned char buf[PG_SHA256_DIGEST_LENGTH]; - bytea *result; - - len = VARSIZE_ANY_EXHDR(in); - data = (unsigned char *) VARDATA_ANY(in); - - ctx = pg_cryptohash_create(PG_SHA256); - if (pg_cryptohash_init(ctx) < 0) - elog(ERROR, "could not initialize %s context", "SHA256"); - if (pg_cryptohash_update(ctx, data, len) < 0) - elog(ERROR, "could not update %s context", "SHA256"); - if (pg_cryptohash_final(ctx, buf) < 0) - elog(ERROR, "could not finalize %s context", "SHA256"); - pg_cryptohash_free(ctx); - - result = palloc(sizeof(buf) + VARHDRSZ); - SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); - memcpy(VARDATA(result), buf, sizeof(buf)); + bytea *result = cryptohash_internal(PG_SHA256, PG_GETARG_BYTEA_PP(0)); PG_RETURN_BYTEA_P(result); } @@ -134,28 +164,7 @@ sha256_bytea(PG_FUNCTION_ARGS) Datum sha384_bytea(PG_FUNCTION_ARGS) { - bytea *in = PG_GETARG_BYTEA_PP(0); - const uint8 *data; - size_t len; - pg_cryptohash_ctx *ctx; - unsigned char buf[PG_SHA384_DIGEST_LENGTH]; - bytea *result; - - len = VARSIZE_ANY_EXHDR(in); - data = (unsigned char *) VARDATA_ANY(in); - - ctx = pg_cryptohash_create(PG_SHA384); - if (pg_cryptohash_init(ctx) < 0) - elog(ERROR, "could not initialize %s context", "SHA384"); - if (pg_cryptohash_update(ctx, data, len) < 0) - elog(ERROR, "could not update %s context", "SHA384"); - if (pg_cryptohash_final(ctx, buf) < 0) - elog(ERROR, "could not finalize %s context", "SHA384"); - pg_cryptohash_free(ctx); - - result = palloc(sizeof(buf) + VARHDRSZ); - SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); - memcpy(VARDATA(result), buf, sizeof(buf)); + bytea *result = cryptohash_internal(PG_SHA384, PG_GETARG_BYTEA_PP(0)); PG_RETURN_BYTEA_P(result); } @@ -163,28 +172,7 @@ sha384_bytea(PG_FUNCTION_ARGS) Datum sha512_bytea(PG_FUNCTION_ARGS) { - bytea *in = PG_GETARG_BYTEA_PP(0); - const uint8 *data; - size_t len; - pg_cryptohash_ctx *ctx; - unsigned char buf[PG_SHA512_DIGEST_LENGTH]; - bytea *result; - - len = VARSIZE_ANY_EXHDR(in); - data = (unsigned char *) VARDATA_ANY(in); - - ctx = pg_cryptohash_create(PG_SHA512); - if (pg_cryptohash_init(ctx) < 0) - elog(ERROR, "could not initialize %s context", "SHA512"); - if (pg_cryptohash_update(ctx, data, len) < 0) - elog(ERROR, "could not update %s context", "SHA512"); - if (pg_cryptohash_final(ctx, buf) < 0) - elog(ERROR, "could not finalize %s context", "SHA512"); - pg_cryptohash_free(ctx); - - result = palloc(sizeof(buf) + VARHDRSZ); - SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); - memcpy(VARDATA(result), buf, sizeof(buf)); + bytea *result = cryptohash_internal(PG_SHA512, PG_GETARG_BYTEA_PP(0)); PG_RETURN_BYTEA_P(result); }