diff --git a/docs/generated/sql/functions.md b/docs/generated/sql/functions.md index 1d4fb35607ed..0f650657ecd0 100644 --- a/docs/generated/sql/functions.md +++ b/docs/generated/sql/functions.md @@ -428,6 +428,8 @@

This function requires an enterprise license on a CCL distribution.

Immutable +gen_random_bytes(count: int) → bytes

Returns count cryptographically strong random bytes. At most 1024 bytes can be extracted at a time.

+
Volatile gen_salt(type: string) → string

Generates a salt for input into the crypt function using the default number of rounds.

Volatile gen_salt(type: string, iter_count: int) → string

Generates a salt for input into the crypt function using iter_count number of rounds.

diff --git a/pkg/sql/logictest/testdata/logic_test/pgcrypto_builtins b/pkg/sql/logictest/testdata/logic_test/pgcrypto_builtins index f7f6d7391227..4a7363557981 100644 --- a/pkg/sql/logictest/testdata/logic_test/pgcrypto_builtins +++ b/pkg/sql/logictest/testdata/logic_test/pgcrypto_builtins @@ -308,3 +308,24 @@ query error pgcode XXC01 decrypt_iv can only be used with a CCL distribution SELECT decrypt_iv('\x91b4ef63852013c8da53829da662b871', 'key', '123', 'aes') subtest end + +subtest gen_random_bytes + +statement error pgcode 22023 length 0 is outside the range +SELECT gen_random_bytes(0) + +statement error pgcode 22023 length 1025 is outside the range +SELECT gen_random_bytes(1025) + +query I +SELECT length(gen_random_bytes(10)) +---- +10 + +# Basic to make sure the same result isn't returned. +query B +SELECT gen_random_bytes(5) = gen_random_bytes(5) +---- +false + +subtest end diff --git a/pkg/sql/sem/builtins/fixed_oids.go b/pkg/sql/sem/builtins/fixed_oids.go index 5dff72bd7031..e2855fb1a599 100644 --- a/pkg/sql/sem/builtins/fixed_oids.go +++ b/pkg/sql/sem/builtins/fixed_oids.go @@ -2457,6 +2457,7 @@ var builtinOidsArray = []string{ 2486: `encrypt_iv(data: bytes, key: bytes, iv: bytes, type: string) -> bytes`, 2487: `decrypt(data: bytes, key: bytes, type: string) -> bytes`, 2488: `decrypt_iv(data: bytes, key: bytes, iv: bytes, type: string) -> bytes`, + 2489: `gen_random_bytes(count: int) -> bytes`, } var builtinOidsBySignature map[string]oid.Oid diff --git a/pkg/sql/sem/builtins/pgcrypto_builtins.go b/pkg/sql/sem/builtins/pgcrypto_builtins.go index 02331b72226b..1cef7f9cf2f0 100644 --- a/pkg/sql/sem/builtins/pgcrypto_builtins.go +++ b/pkg/sql/sem/builtins/pgcrypto_builtins.go @@ -225,6 +225,27 @@ var pgcryptoBuiltins = map[string]builtinDefinition{ "gen_random_uuid": generateRandomUUID4Impl(), + "gen_random_bytes": makeBuiltin( + tree.FunctionProperties{Category: builtinconstants.CategoryCrypto}, + tree.Overload{ + Types: tree.ParamTypes{{Name: "count", Typ: types.Int}}, + ReturnType: tree.FixedReturnType(types.Bytes), + Fn: func(_ context.Context, _ *eval.Context, args tree.Datums) (tree.Datum, error) { + count := int(tree.MustBeDInt(args[0])) + if count < 1 || count > 1024 { + return nil, pgerror.Newf(pgcode.InvalidParameterValue, "length %d is outside the range [1, 1024]", count) + } + bytes, err := getRandomBytes(count) + if err != nil { + return nil, err + } + return tree.NewDBytes(tree.DBytes(bytes)), nil + }, + Info: "Returns `count` cryptographically strong random bytes. At most 1024 bytes can be extracted at a time.", + Volatility: volatility.Volatile, + }, + ), + "gen_salt": makeBuiltin( tree.FunctionProperties{Category: builtinconstants.CategoryCrypto}, tree.Overload{