subtest digest

# NB: CockroachDB currently differs from Postgres, since the shaX functions
# return a string in CockroachDB, while Postgres returns bytea.
query BTT nosort
SELECT
  encode(digest('abc', alg), 'hex') = expected, digest(NULL, alg), digest('abc', NULL)
FROM
  (
    VALUES
      ('md5', md5('abc')),
      ('sha1', sha1('abc')),
      ('sha224', sha224('abc')),
      ('sha256', sha256('abc')),
      ('sha384', sha384('abc')),
      ('sha512', sha512('abc'))
  )
    AS v (alg, expected);
----
true  NULL  NULL
true  NULL  NULL
true  NULL  NULL
true  NULL  NULL
true  NULL  NULL
true  NULL  NULL

query T
SELECT digest(NULL, 'made up alg')
----
NULL

statement error pgcode 22023 cannot use "made up alg", no such hash algorithm
SELECT digest('cat', 'made up alg')

subtest end

subtest hmac

# NB: These results were manually confirmed to match the hashed values
# created by Postgres.
query T nosort
SELECT encode(hmac('abc', 'key', alg), 'hex')
FROM (VALUES ('md5'), ('sha1'), ('sha224'), ('sha256'), ('sha384'), ('sha512')) v(alg)
----
d2fe98063f876b03193afb49b4979591
4fd0b215276ef12f2b3e4c8ecac2811498b656fc
f524670b7e34f31467de0aa96593861cf65117d414fb2d86158d760e
9c196e32dc0175f86f4b1cb89289d6619de6bee699e4c378e68309ed97a1a6ab
30ddb9c8f347cffbfb44e519d814f074cf4047a55d6f563324f1c6a33920e5edfb2a34bac60bdc96cd33a95623d7d638
3926a207c8c42b0c41792cbd3e1a1aaaf5f7a25704f62dfc939c4987dd7ce060009c5bb1c2447355b3216f10b537e9afa7b64a4e5391b0d631172d07939e087a

query TTT
SELECT hmac('abc', 'key', NULL), hmac('abc', NULL, 'made up alg'), hmac(NULL, 'key', 'sha256')
----
NULL  NULL  NULL

statement error pgcode 22023 cannot use "made up alg", no such hash algorithm
SELECT hmac('dog', 'key', 'made up alg')

subtest end

subtest gen_random_uuid

query IB
SELECT length(gen_random_uuid()::BYTES), gen_random_uuid() = gen_random_uuid()
----
16 false

subtest end

subtest gen_salt_invalid_algo

statement error pgcode 22023 unknown salt algorithm
SELECT gen_salt('invalid')

statement error pgcode 22023 unknown salt algorithm
SELECT gen_salt('invalid', 0)

subtest end

subtest gen_salt_des

query I
SELECT char_length(gen_salt('des'))
----
2

query I nosort
SELECT char_length(gen_salt('des', rounds))
FROM (VALUES (0), (25)) AS t (rounds)
----
2
2

# invalid rounds
statement error pgcode 22023 invalid number of rounds
SELECT gen_salt('des', 1)

subtest end

subtest gen_salt_xdes

query TI
SELECT substr(salt, 1, 5), char_length(salt)
FROM (SELECT gen_salt('xdes') AS salt)
----
_J9..  9

query TI nosort
SELECT substr(salt, 1, 5), char_length(salt)
FROM (SELECT gen_salt('xdes', rounds) AS salt FROM (VALUES (0), (1), (16777215)) AS t (rounds))
----
_J9..  9
_/...  9
_zzzz  9

# invalid even rounds
statement error pgcode 22023 invalid number of rounds
SELECT gen_salt('xdes', 2)

# invalid min rounds
statement error pgcode 22023 invalid number of rounds
SELECT gen_salt('xdes', -1)

# invalid max rounds
statement error pgcode 22023 invalid number of rounds
SELECT gen_salt('xdes', 16777216)

subtest end

subtest gen_salt_md5

query TI
SELECT substr(salt, 1, 3), char_length(salt)
FROM (SELECT gen_salt('md5') AS salt)
----
$1$ 11

query TI nosort
SELECT substr(salt, 1, 3), char_length(salt)
FROM (SELECT gen_salt('md5', rounds) AS salt FROM (VALUES (0), (1000)) AS t (rounds))
----
$1$ 11
$1$ 11

# invalid rounds
statement error pgcode 22023 invalid number of rounds
SELECT gen_salt('md5', 1)

subtest end

subtest gen_salt_bf

query TI nosort
SELECT substr(salt, 1, 7), char_length(salt)
FROM (SELECT gen_salt('bf', rounds) AS salt FROM (VALUES (0), (4), (31)) AS t (rounds))
----
$2a$06$ 29
$2a$04$ 29
$2a$31$ 29

# invalid min rounds
statement error pgcode 22023 invalid number of salt rounds
SELECT gen_salt('bf', 3)

# invalid max rounds
statement error pgcode 22023 invalid number of salt rounds
SELECT gen_salt('bf', 32)

subtest crypt_invalid_algo

# invalid header
statement error pgcode 22023 invalid salt algorithm
SELECT crypt('password', '')

# invalid header
statement error pgcode 22023 invalid salt algorithm
SELECT crypt('password', '$')

subtest end

subtest crypt_md5

query T nosort
SELECT crypt(password, '$1$aRnqRmeP')
FROM (VALUES
  (''),
  ('0'),
  ('password'),
  (repeat('a', 50))
) AS t (password)
----
$1$aRnqRmeP$.GKS2A8uOS7cKSGtb33BL0
$1$aRnqRmeP$zSsYGTxby0DLjRezdRBT50
$1$aRnqRmeP$79.GOqWdD1jolSFx6PGg5.
$1$aRnqRmeP$Qtrye90cHoHamBO08sQKC1

# salt is truncated to 11 chars
query TB
SELECT hash1, hash1 = hash2
FROM (SELECT
  crypt('password', '$1$aRnqRmeP') as hash1,
  crypt('password', '$1$aRnqRmePextra') as hash2
) as t
----
$1$aRnqRmeP$79.GOqWdD1jolSFx6PGg5.  true

# random salt can be less than 8 characters
query T
SELECT crypt('password', '$1$')
----
$1$$I2o9Z7NcvQAKp7wyCTlia0

subtest end

subtest crypt_bf

query T nosort
SELECT crypt(password, '$2a$06$Ukv6DxN3PpZo4YboQRrIVO')
FROM (VALUES
  (''),
  ('0'),
  ('password'),
  (repeat('a', 50))
) AS t (password)
----
$2a$06$Ukv6DxN3PpZo4YboQRrIVOXwHbf79QsnJ4GoQyYv5vZozGSILtNUu
$2a$06$Ukv6DxN3PpZo4YboQRrIVOBxB6sdGuSnn.PViRLXxUFUiihB30ukm
$2a$06$Ukv6DxN3PpZo4YboQRrIVO6UrBIvyPUuhsGQvYZyAvmsIjt02Ze3O
$2a$06$Ukv6DxN3PpZo4YboQRrIVO9DZGS27nWDW5eSzsL/ckOByIGwpxf0a

# password is truncated to 72 chars
query TBB
SELECT hash72, hash71 != hash72, hash72 = hash73
FROM (SELECT
  crypt(repeat('a', 71), salt) as hash71,
  crypt(repeat('a', 72), salt) as hash72,
  crypt(repeat('a', 73), salt) as hash73
  FROM (SELECT '$2a$06$Ukv6DxN3PpZo4YboQRrIVO' as salt) as s
) as t
----
$2a$06$Ukv6DxN3PpZo4YboQRrIVOIQPDI39RHxEgW32.ICmqRFFBxkR8ddC  true  true

# salt is truncated to 29 chars
query TB
SELECT hash1, hash1 = hash2
FROM (SELECT
  crypt('password', '$2a$06$Ukv6DxN3PpZo4YboQRrIVO') as hash1,
  crypt('password', '$2a$06$Ukv6DxN3PpZo4YboQRrIVOextra') as hash2
) as t
----
$2a$06$Ukv6DxN3PpZo4YboQRrIVO6UrBIvyPUuhsGQvYZyAvmsIjt02Ze3O  true

# test min and average num rounds (large num rounds take too long to run for a test)
query T nosort
SELECT crypt('password', concat('$2a$', rounds, '$Ukv6DxN3PpZo4YboQRrIVO'))
FROM (VALUES ('04'), ('10')) AS t (rounds)
----
$2a$04$Ukv6DxN3PpZo4YboQRrIVOSgyjUD9vDt2W.RjRVhm7XC2QTQrtLSK
$2a$10$Ukv6DxN3PpZo4YboQRrIVOwLm63.TplP3REdrq258BBo3lUBnEbrm

# invalid salt length
statement error pgcode 22023 invalid salt length
SELECT crypt('password', '$2a$06$')

# invalid salt length
statement error pgcode 22023 invalid salt length
SELECT crypt('password', '$2a$06$Ukv6DxN3PpZo4YboQRrIV')

# invalid round syntax
statement error pgcode 22023 invalid salt rounds
SELECT crypt('password', '$2a$AA$Ukv6DxN3PpZo4YboQRrIVO')

# invalid min rounds
statement error pgcode 22023 invalid number of salt rounds
SELECT crypt('password', '$2a$03$Ukv6DxN3PpZo4YboQRrIVO')

# invalid max rounds
statement error pgcode 22023 invalid number of salt rounds
SELECT crypt('password', '$2a$32$Ukv6DxN3PpZo4YboQRrIVO')

# invalid salt formatting
statement error pgcode 22023 invalid salt format
SELECT crypt('password', '$2a$06AUkv6DxN3PpZo4YboQRrIVO')

# invalid salt encoding
statement error pgcode 22023 invalid salt encoding
SELECT crypt('password', '$2a$06$#kv6DxN3PpZo4YboQRrIVO')

subtest end

subtest ccl_functions

skipif config enterprise-configs
query error pgcode XXC01 encrypt can only be used with a CCL distribution
SELECT encrypt('abc', 'key', 'aes')

skipif config enterprise-configs
query error pgcode XXC01 encrypt_iv can only be used with a CCL distribution
SELECT encrypt_iv('abc', 'key', '123', 'aes')

skipif config enterprise-configs
query error pgcode XXC01 decrypt can only be used with a CCL distribution
SELECT decrypt('\xdb5f149a7caf0cd275ca18c203a212c9', 'key', 'aes')

skipif config enterprise-configs
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
