Skip to content

Commit 536569a

Browse files
committed
add sha1_hex UDF and SP - deterministic 40-character hash
select sha1_hex('test') from sysibm.sysdummy1 call sha1_hex('test', ?) output same as: echo -n "test" |openssl dgst -sha1
1 parent c0be057 commit 536569a

File tree

9 files changed

+126
-1
lines changed

9 files changed

+126
-1
lines changed

db2hash.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,40 @@ void SQL_API_FN sha256hex(SQLUDF_CHAR *in,
335335
return;
336336
}
337337

338+
/*
339+
+----------------------------------------------------------------------+
340+
| function sha1hex: sha-1 40-character hex output (no salt) |
341+
| |
342+
| input : varchar (password) |
343+
| output: char (hash) |
344+
+----------------------------------------------------------------------+
345+
*/
346+
347+
#ifdef __cplusplus
348+
extern "C"
349+
#endif
350+
void SQL_API_FN sha1hex(SQLUDF_CHAR *in,
351+
SQLUDF_CHAR out[41],
352+
SQLUDF_SMALLINT *innull,
353+
SQLUDF_SMALLINT *outnull,
354+
SQLUDF_TRAIL_ARGS)
355+
{
356+
char *t;
357+
358+
if (*innull != 0)
359+
{
360+
*outnull = -1;
361+
return;
362+
}
363+
364+
t = mk_hash(ALG_SHA1HEX, in, NULL);
365+
strcpy(out, t);
366+
free(t);
367+
368+
*outnull = 0;
369+
return;
370+
}
371+
338372
/*
339373
+----------------------------------------------------------------------+
340374
| function sha512: sha-512 |

drop.ddl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ DROP FUNCTION apr_sha256;
66
DROP SPECIFIC FUNCTION UDF_SHA256;
77
DROP SPECIFIC FUNCTION UDF_SHA256S;
88
DROP FUNCTION sha256_hex;
9+
DROP FUNCTION sha1_hex;
910
DROP SPECIFIC FUNCTION UDF_SHA512;
1011
DROP SPECIFIC FUNCTION UDF_SHA512S;
1112
DROP FUNCTION bcrypt;
@@ -19,6 +20,7 @@ DROP PROCEDURE apr_sha256;
1920
DROP SPECIFIC PROCEDURE SP_SHA256;
2021
DROP SPECIFIC PROCEDURE SP_SHA256S;
2122
DROP PROCEDURE sha256_hex;
23+
DROP PROCEDURE sha1_hex;
2224
DROP SPECIFIC PROCEDURE SP_SHA512;
2325
DROP SPECIFIC PROCEDURE SP_SHA512S;
2426
DROP PROCEDURE bcrypt;

hash.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,15 @@ char* mk_hash(int alg, const char *passwd, const char *mysalt)
130130
unsigned char digest[APR_MD5_DIGESTSIZE];
131131
apr_md5_ctx_t context;
132132
char md5str[33];
133+
133134
SHA256_CTX context256;
134135
apr_byte_t digest256[SHA256_DIGEST_LENGTH];
135136
char sha256str[65];
137+
138+
apr_sha1_ctx_t context1;
139+
apr_byte_t digest1[APR_SHA1_DIGESTSIZE];
140+
char sha1str[41];
141+
136142
int i;
137143
char *r;
138144

@@ -235,7 +241,7 @@ char* mk_hash(int alg, const char *passwd, const char *mysalt)
235241
sha256str[0] = '\0';
236242

237243
apr__SHA256_Init(&context256);
238-
apr__SHA256_Update(&context256, passwd, strlen(passwd));
244+
apr__SHA256_Update(&context256, (const apr_byte_t *)passwd, strlen(passwd));
239245
apr__SHA256_Final(digest256, &context256);
240246
for (i = 0, r = sha256str; i < SHA256_DIGEST_LENGTH; i++, r += 2)
241247
{
@@ -246,6 +252,22 @@ char* mk_hash(int alg, const char *passwd, const char *mysalt)
246252
apr_cpystrn(cpw, sha256str, sizeof(sha256str));
247253
memset(sha256str, '\0', strlen(sha256str));
248254
break;
255+
256+
case ALG_SHA1HEX:
257+
sha1str[0] = '\0';
258+
259+
apr_sha1_init(&context1);
260+
apr_sha1_update(&context1, passwd, strlen(passwd));
261+
apr_sha1_final(digest1, &context1);
262+
for (i = 0, r = sha1str; i < APR_SHA1_DIGESTSIZE; i++, r += 2)
263+
{
264+
sprintf(r, "%02x", digest1[i]);
265+
}
266+
*r = '\0';
267+
268+
apr_cpystrn(cpw, sha1str, sizeof(sha1str));
269+
memset(sha1str, '\0', strlen(sha1str));
270+
break;
249271
}
250272

251273
result = (char*)malloc((strlen(cpw)+1)*sizeof(char));
@@ -308,6 +330,22 @@ int validate_hash(const char *password, const char *hash)
308330
}
309331
}
310332

333+
if (strlen(hash) == 40 && (hash[0] != '$'))
334+
{
335+
tmphash = mk_hash(ALG_SHA1HEX, password, NULL);
336+
337+
if (apr_strnatcmp(hash, tmphash) == 0)
338+
{
339+
free(tmphash);
340+
return TRUE;
341+
}
342+
else
343+
{
344+
free(tmphash);
345+
return FALSE;
346+
}
347+
}
348+
311349
status = apr_password_validate(password, hash);
312350

313351
if (status == APR_SUCCESS)

hash.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ bcrypt
99
sha256
1010
sha256s
1111
sha256hex
12+
sha1hex
1213
sha512
1314
sha512s
1415
validate

hash.exp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ bcrypt
77
sha256
88
sha256s
99
sha256hex
10+
sha1hex
1011
sha512
1112
sha512s
1213
validate

hash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#define ALG_APSHA256 7
6060
#define ALG_BCRYPT 8
6161
#define ALG_SHA256HEX 9
62+
#define ALG_SHA1HEX 10
6263

6364
#define APR_SHA256PW_ID "{SHA256}"
6465
#define APR_SHA256PW_IDLEN 8

register.ddl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ BEGIN
1111
EXECUTE IMMEDIATE 'DROP SPECIFIC FUNCTION UDF_SHA256';
1212
EXECUTE IMMEDIATE 'DROP SPECIFIC FUNCTION UDF_SHA256S';
1313
EXECUTE IMMEDIATE 'DROP FUNCTION sha256_hex';
14+
EXECUTE IMMEDIATE 'DROP FUNCTION sha1_hex';
1415
EXECUTE IMMEDIATE 'DROP SPECIFIC FUNCTION UDF_SHA512';
1516
EXECUTE IMMEDIATE 'DROP SPECIFIC FUNCTION UDF_SHA512S';
1617
EXECUTE IMMEDIATE 'DROP FUNCTION bcrypt';
@@ -24,6 +25,7 @@ BEGIN
2425
EXECUTE IMMEDIATE 'DROP SPECIFIC PROCEDURE SP_SHA256';
2526
EXECUTE IMMEDIATE 'DROP SPECIFIC PROCEDURE SP_SHA256S';
2627
EXECUTE IMMEDIATE 'DROP PROCEDURE sha256_hex';
28+
EXECUTE IMMEDIATE 'DROP PROCEDURE sha1_hex';
2729
EXECUTE IMMEDIATE 'DROP SPECIFIC PROCEDURE SP_SHA512';
2830
EXECUTE IMMEDIATE 'DROP SPECIFIC PROCEDURE SP_SHA512S';
2931
EXECUTE IMMEDIATE 'DROP PROCEDURE bcrypt';
@@ -126,6 +128,18 @@ CREATE FUNCTION sha256_hex(VARCHAR(4096))
126128
PARAMETER STYLE SQL
127129
EXTERNAL NAME 'hash!sha256hex' @
128130

131+
CREATE FUNCTION sha1_hex(VARCHAR(4096))
132+
SPECIFIC UDF_SHA1HEX
133+
RETURNS VARCHAR(40)
134+
NOT FENCED
135+
DETERMINISTIC
136+
NO SQL
137+
NO EXTERNAL ACTION
138+
LANGUAGE C
139+
RETURNS NULL ON NULL INPUT
140+
PARAMETER STYLE SQL
141+
EXTERNAL NAME 'hash!sha1hex' @
142+
129143
CREATE FUNCTION sha512(VARCHAR(4096))
130144
SPECIFIC UDF_SHA512
131145
RETURNS VARCHAR(98)
@@ -270,6 +284,18 @@ CREATE PROCEDURE sha256_hex(IN in VARCHAR(4096), OUT hash CHAR(64))
270284
PROGRAM TYPE SUB
271285
EXTERNAL NAME 'hash!sha256hex' @
272286

287+
CREATE PROCEDURE sha1_hex(IN in VARCHAR(4096), OUT hash CHAR(40))
288+
SPECIFIC SP_SHA1HEX
289+
DYNAMIC RESULT SETS 0
290+
NO SQL
291+
DETERMINISTIC
292+
LANGUAGE C
293+
PARAMETER STYLE SQL
294+
NO DBINFO
295+
NOT FENCED
296+
PROGRAM TYPE SUB
297+
EXTERNAL NAME 'hash!sha1hex' @
298+
273299
CREATE PROCEDURE sha512(IN in VARCHAR(4096), OUT hash CHAR(98))
274300
SPECIFIC SP_SHA512
275301
DYNAMIC RESULT SETS 0

test_hash.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ int main( int argc, char *argv[] )
7272
printf( "\nsha256_hex -> %s", hash);
7373
free(hash);
7474

75+
hash = mk_hash( ALG_SHA1HEX, clear, NULL );
76+
printf( "\nsha1_hex -> %s", hash);
77+
free(hash);
78+
7579
#if BCRYPT_ALGO_SUPPORTED
7680
hash = mk_hash( ALG_BCRYPT, clear, NULL );
7781
printf( "\nbcrypt -> %s", hash);

tests/tests.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ CREATE OR REPLACE PROCEDURE TEST_SHA256_HEX()
124124
CALL DB2UNIT.ASSERT_STRING_EQUALS(EXPECTED, ACTUAL);
125125
END @
126126

127+
CREATE OR REPLACE PROCEDURE TEST_SHA1_HEX()
128+
BEGIN
129+
DECLARE EXPECTED VARCHAR(40);
130+
DECLARE ACTUAL VARCHAR(40);
131+
SET EXPECTED = '98ef0758e6aac6f9a9e1197548c8190b72c9581d';
132+
SET ACTUAL = DB2INST1.SHA1_HEX('testpwd');
133+
CALL DB2UNIT.ASSERT_STRING_EQUALS(EXPECTED, ACTUAL);
134+
END @
135+
127136
CREATE OR REPLACE PROCEDURE TEST_SHA512()
128137
BEGIN
129138
DECLARE LOGGER_ID SMALLINT;
@@ -304,4 +313,13 @@ CREATE OR REPLACE PROCEDURE TEST_VALIDATE_PW7()
304313
CALL DB2UNIT.ASSERT_INT_EQUALS(EXPECTED, ACTUAL);
305314
END @
306315

316+
CREATE OR REPLACE PROCEDURE TEST_VALIDATE_PW8()
317+
BEGIN
318+
DECLARE EXPECTED INTEGER;
319+
DECLARE ACTUAL INTEGER;
320+
SET EXPECTED = 1;
321+
SET ACTUAL = DB2INST1.VALIDATE_PW('testpwd', '98ef0758e6aac6f9a9e1197548c8190b72c9581d');
322+
CALL DB2UNIT.ASSERT_INT_EQUALS(EXPECTED, ACTUAL);
323+
END @
324+
307325
CALL DB2UNIT.REGISTER_MESSAGE(CURRENT SCHEMA) @

0 commit comments

Comments
 (0)