我想更新数据库中的所有密码以获得 MD5 哈希密码。以下不能解决我的问题:
UPDATE USERS SET USERPASS = hash('SALT' || USERPASS);
问题是:它返回的散列不是使用 MD5 算法生成的。如何在 Firebird 中实现 md5 哈希算法?
我想更新数据库中的所有密码以获得 MD5 哈希密码。以下不能解决我的问题:
UPDATE USERS SET USERPASS = hash('SALT' || USERPASS);
问题是:它返回的散列不是使用 MD5 算法生成的。如何在 Firebird 中实现 md5 哈希算法?
不幸的是,文档hash
中没有提到该函数的算法......无论如何,您可以将它实现为 UDF 或使用一些第三方 UDF 库来实现它。IBPhoenix 网站上有一个Firebird 的 UDF 库列表,似乎 rFunc 和 FreeAdhocUDF 库都有一个(我只检查了这两个,可能还有其他的)。
Firebird 的下一个版本 Firebird 4 将添加加密哈希函数。引用Firebird 4 Beta 1 发行说明:
追踪票CORE-4436
使用指定算法返回字符串的哈希值。格式为:
HASH( <string> [ USING <algorithm> ] ) algorithm ::= { MD5 | SHA1 | SHA256 | SHA512 }
带有可选
USING
子句的语法在 FB 4.0 中引入,并VARCHAR
以字符集返回字符串OCTETS
。重要的
USING
仍然支持不带子句的语法。它使用非加密 PJW 哈希函数(也称为 ELF64)的 64 位变体:
https
://en.wikipedia.org/wiki/PJW_hash_function ,速度非常快,可用于一般用途(哈希表、等),但它的碰撞质量是次优的。其他散列函数(在 USING 子句中明确指定)应该用于更可靠的散列。例子
select hash(x using sha256) from y; -- select hash(x) from y; -- not recommended
Firebird 4 Beta 1 可以从https://www.firebirdsql.org/en/firebird-4-0-0-beta1/下载进行测试
这是没有UDF的另一种方式,我发现here
/******************************************************************************/
/*** Generated by IBExpert 2018.6.8.1 27.08.2018 16:31:02 ***/
/******************************************************************************/
/******************************************************************************/
/*** Following SET SQL DIALECT is just for the Database Comparer ***/
/******************************************************************************/
SET SQL DIALECT 3;
/******************************************************************************/
/*** Stored procedures ***/
/******************************************************************************/
SET TERM ^ ;
CREATE OR ALTER PROCEDURE MD5 (
SOURCE BLOB SUB_TYPE 1 SEGMENT SIZE 80 CHARACTER SET OCTETS)
RETURNS (
RES CHAR(32) CHARACTER SET OCTETS)
AS
BEGIN
SUSPEND;
END^
CREATE OR ALTER PROCEDURE MD5_F (
A BIGINT,
B BIGINT,
C BIGINT,
D BIGINT,
K INTEGER,
S INTEGER,
T BIGINT,
P INTEGER,
V CHAR(64) CHARACTER SET OCTETS)
RETURNS (
RES BIGINT)
AS
BEGIN
SUSPEND;
END^
CREATE OR ALTER PROCEDURE MD5_INTTOCHAR4 (
V BIGINT)
RETURNS (
RES CHAR(4) CHARACTER SET OCTETS)
AS
BEGIN
SUSPEND;
END^
CREATE OR ALTER PROCEDURE MD5_INTTOHEX (
V BIGINT)
RETURNS (
RES CHAR(8) CHARACTER SET OCTETS)
AS
BEGIN
SUSPEND;
END^
SET TERM ; ^
/******************************************************************************/
/*** Stored procedures ***/
/******************************************************************************/
SET TERM ^ ;
CREATE OR ALTER PROCEDURE MD5 (
SOURCE BLOB SUB_TYPE 1 SEGMENT SIZE 80 CHARACTER SET OCTETS)
RETURNS (
RES CHAR(32) CHARACTER SET OCTETS)
AS
declare variable A bigint = 0X0067452301;
declare variable B bigint = 0X00EFCDAB89;
declare variable C bigint = 0X0098BADCFE;
declare variable D bigint = 0X0010325476;
declare variable AA bigint;
declare variable BB bigint;
declare variable CC bigint;
declare variable DD bigint;
declare variable BUF char(64) character set OCTETS;
declare variable LEN bigint;
declare variable M integer;
declare variable N integer;
begin
len = octet_length(source);
m = 56 - mod(len + 1, 64);
if (m < 0) then m = m + 64;
source = source || rpad(x'80', m+1, x'00') ||
(select res from md5_IntToChar4(bin_and(0x00FFFFFFFF, bin_shl(:len, 3)))) ||
(select res from md5_IntToChar4(bin_shr(:len, 32-3)));
n = 0;
while (n < (len+m+9) / 64) do
begin
AA = A;
BB = B;
CC = C;
DD = D;
buf = substring(source from n * 64 + 1 for 64);
/* Round 1 */
A = (select res from md5_F(:A, :B, :C, :D, 0, 7, 0x00d76aa478, 1, :buf)); /* 1 */
D = (select res from md5_F(:D, :A, :B, :C, 1, 12, 0x00e8c7b756, 1, :buf)); /* 2 */
C = (select res from md5_F(:C, :D, :A, :B, 2, 17, 0x00242070db, 1, :buf)); /* 3 */
B = (select res from md5_F(:B, :C, :D, :A, 3, 22, 0x00c1bdceee, 1, :buf)); /* 4 */
A = (select res from md5_F(:A, :B, :C, :D, 4, 7, 0x00f57c0faf, 1, :buf)); /* 5 */
D = (select res from md5_F(:D, :A, :B, :C, 5, 12, 0x004787c62a, 1, :buf)); /* 6 */
C = (select res from md5_F(:C, :D, :A, :B, 6, 17, 0x00a8304613, 1, :buf)); /* 7 */
B = (select res from md5_F(:B, :C, :D, :A, 7, 22, 0x00fd469501, 1, :buf)); /* 8 */
A = (select res from md5_F(:A, :B, :C, :D, 8, 7, 0x00698098d8, 1, :buf)); /* 9 */
D = (select res from md5_F(:D, :A, :B, :C, 9, 12, 0x008b44f7af, 1, :buf)); /* 10 */
C = (select res from md5_F(:C, :D, :A, :B, 10, 17, 0x00ffff5bb1, 1, :buf)); /* 11 */
B = (select res from md5_F(:B, :C, :D, :A, 11, 22, 0x00895cd7be, 1, :buf)); /* 12 */
A = (select res from md5_F(:A, :B, :C, :D, 12, 7, 0x006b901122, 1, :buf)); /* 13 */
D = (select res from md5_F(:D, :A, :B, :C, 13, 12, 0x00fd987193, 1, :buf)); /* 14 */
C = (select res from md5_F(:C, :D, :A, :B, 14, 17, 0x00a679438e, 1, :buf)); /* 15 */
B = (select res from md5_F(:B, :C, :D, :A, 15, 22, 0x0049b40821, 1, :buf)); /* 16 */
/* Round 2 */
A = (select res from md5_F(:A, :B, :C, :D, 1, 5, 0x00f61e2562, 2, :buf)); /* 17 */
D = (select res from md5_F(:D, :A, :B, :C, 6, 9, 0x00c040b340, 2, :buf)); /* 18 */
C = (select res from md5_F(:C, :D, :A, :B, 11, 14, 0x00265e5a51, 2, :buf)); /* 19 */
B = (select res from md5_F(:B, :C, :D, :A, 0, 20, 0x00e9b6c7aa, 2, :buf)); /* 20 */
A = (select res from md5_F(:A, :B, :C, :D, 5, 5, 0x00d62f105d, 2, :buf)); /* 21 */
D = (select res from md5_F(:D, :A, :B, :C, 10, 9, 0x0002441453, 2, :buf)); /* 22 */
C = (select res from md5_F(:C, :D, :A, :B, 15, 14, 0x00d8a1e681, 2, :buf)); /* 23 */
B = (select res from md5_F(:B, :C, :D, :A, 4, 20, 0x00e7d3fbc8, 2, :buf)); /* 24 */
A = (select res from md5_F(:A, :B, :C, :D, 9, 5, 0x0021e1cde6, 2, :buf)); /* 25 */
D = (select res from md5_F(:D, :A, :B, :C, 14, 9, 0x00c33707d6, 2, :buf)); /* 26 */
C = (select res from md5_F(:C, :D, :A, :B, 3, 14, 0x00f4d50d87, 2, :buf)); /* 27 */
B = (select res from md5_F(:B, :C, :D, :A, 8, 20, 0x00455a14ed, 2, :buf)); /* 28 */
A = (select res from md5_F(:A, :B, :C, :D, 13, 5, 0x00a9e3e905, 2, :buf)); /* 29 */
D = (select res from md5_F(:D, :A, :B, :C, 2, 9, 0x00fcefa3f8, 2, :buf)); /* 30 */
C = (select res from md5_F(:C, :D, :A, :B, 7, 14, 0x00676f02d9, 2, :buf)); /* 31 */
B = (select res from md5_F(:B, :C, :D, :A, 12, 20, 0x008d2a4c8a, 2, :buf)); /* 32 */
/* Round 3 */
A = (select res from md5_F(:A, :B, :C, :D, 5, 4, 0x00fffa3942, 3, :buf)); /* 33 */
D = (select res from md5_F(:D, :A, :B, :C, 8, 11, 0x008771f681, 3, :buf)); /* 34 */
C = (select res from md5_F(:C, :D, :A, :B, 11, 16, 0x006d9d6122, 3, :buf)); /* 35 */
B = (select res from md5_F(:B, :C, :D, :A, 14, 23, 0x00fde5380c, 3, :buf)); /* 36 */
A = (select res from md5_F(:A, :B, :C, :D, 1, 4, 0x00a4beea44, 3, :buf)); /* 37 */
D = (select res from md5_F(:D, :A, :B, :C, 4, 11, 0x004bdecfa9, 3, :buf)); /* 38 */
C = (select res from md5_F(:C, :D, :A, :B, 7, 16, 0x00f6bb4b60, 3, :buf)); /* 39 */
B = (select res from md5_F(:B, :C, :D, :A, 10, 23, 0x00bebfbc70, 3, :buf)); /* 40 */
A = (select res from md5_F(:A, :B, :C, :D, 13, 4, 0x00289b7ec6, 3, :buf)); /* 41 */
D = (select res from md5_F(:D, :A, :B, :C, 0, 11, 0x00eaa127fa, 3, :buf)); /* 42 */
C = (select res from md5_F(:C, :D, :A, :B, 3, 16, 0x00d4ef3085, 3, :buf)); /* 43 */
B = (select res from md5_F(:B, :C, :D, :A, 6, 23, 0x0004881d05, 3, :buf)); /* 44 */
A = (select res from md5_F(:A, :B, :C, :D, 9, 4, 0x00d9d4d039, 3, :buf)); /* 45 */
D = (select res from md5_F(:D, :A, :B, :C, 12, 11, 0x00e6db99e5, 3, :buf)); /* 46 */
C = (select res from md5_F(:C, :D, :A, :B, 15, 16, 0x001fa27cf8, 3, :buf)); /* 47 */
B = (select res from md5_F(:B, :C, :D, :A, 2, 23, 0x00c4ac5665, 3, :buf)); /* 48 */
/* Round 4 */
A = (select res from md5_F(:A, :B, :C, :D, 0, 6, 0x00f4292244, 4, :buf)); /* 49 */
D = (select res from md5_F(:D, :A, :B, :C, 7, 10, 0x00432aff97, 4, :buf)); /* 50 */
C = (select res from md5_F(:C, :D, :A, :B, 14, 15, 0x00ab9423a7, 4, :buf)); /* 51 */
B = (select res from md5_F(:B, :C, :D, :A, 5, 21, 0x00fc93a039, 4, :buf)); /* 52 */
A = (select res from md5_F(:A, :B, :C, :D, 12, 6, 0x00655b59c3, 4, :buf)); /* 53 */
D = (select res from md5_F(:D, :A, :B, :C, 3, 10, 0x008f0ccc92, 4, :buf)); /* 54 */
C = (select res from md5_F(:C, :D, :A, :B, 10, 15, 0x00ffeff47d, 4, :buf)); /* 55 */
B = (select res from md5_F(:B, :C, :D, :A, 1, 21, 0x0085845dd1, 4, :buf)); /* 56 */
A = (select res from md5_F(:A, :B, :C, :D, 8, 6, 0x006fa87e4f, 4, :buf)); /* 57 */
D = (select res from md5_F(:D, :A, :B, :C, 15, 10, 0x00fe2ce6e0, 4, :buf)); /* 58 */
C = (select res from md5_F(:C, :D, :A, :B, 6, 15, 0x00a3014314, 4, :buf)); /* 59 */
B = (select res from md5_F(:B, :C, :D, :A, 13, 21, 0x004e0811a1, 4, :buf)); /* 60 */
A = (select res from md5_F(:A, :B, :C, :D, 4, 6, 0x00f7537e82, 4, :buf)); /* 61 */
D = (select res from md5_F(:D, :A, :B, :C, 11, 10, 0x00bd3af235, 4, :buf)); /* 62 */
C = (select res from md5_F(:C, :D, :A, :B, 2, 15, 0x002ad7d2bb, 4, :buf)); /* 63 */
B = (select res from md5_F(:B, :C, :D, :A, 9, 21, 0x00eb86d391, 4, :buf)); /* 64 */
A = bin_and(0x00FFFFFFFF, AA + A);
B = bin_and(0x00FFFFFFFF, BB + B);
C = bin_and(0x00FFFFFFFF, CC + C);
D = bin_and(0x00FFFFFFFF, DD + D);
n = n + 1;
end
res =
(select res from md5_IntToHex(:a))||
(select res from md5_IntToHex(:b))||
(select res from md5_IntToHex(:c))||
(select res from md5_IntToHex(:d));
suspend;
end^
CREATE OR ALTER PROCEDURE MD5_F (
A BIGINT,
B BIGINT,
C BIGINT,
D BIGINT,
K INTEGER,
S INTEGER,
T BIGINT,
P INTEGER,
V CHAR(64) CHARACTER SET OCTETS)
RETURNS (
RES BIGINT)
AS
declare variable FF bigint;
declare variable R bigint;
declare variable X bigint;
begin
X = bin_or(ascii_val(substring(V from k*4 + 1 for 1)),
bin_shl(ascii_val(substring(V from k*4 + 2 for 1)), 8),
bin_shl(ascii_val(substring(V from k*4 + 3 for 1)),16),
bin_shl(ascii_val(substring(V from k*4 + 4 for 1)),24));
if (p = 1) then /* f */
ff = bin_or(bin_and(b, c), bin_and(bin_not(b), d));
if (p = 2) then /* g */
ff = bin_or(bin_and(b, d), bin_and(bin_not(d), c));
if (p = 3) then /* h */
ff = bin_xor(b, c, d);
if (p = 4) then /* i */
ff = bin_xor(c, bin_or(bin_not(d), b));
r = bin_and(0x00FFFFFFFF, a + ff + x + t);
r = bin_and(0x00FFFFFFFF, b + bin_or(bin_shl(r, s), bin_shr(r, 32 - s)));
res = r;
suspend;
end^
CREATE OR ALTER PROCEDURE MD5_INTTOCHAR4 (
V BIGINT)
RETURNS (
RES CHAR(4) CHARACTER SET OCTETS)
AS
begin
res = ascii_char(bin_and(0xFF, V))||
ascii_char(bin_and(0xFF, bin_shr(V, 8)))||
ascii_char(bin_and(0xFF, bin_shr(V, 16)))||
ascii_char(bin_and(0xFF, bin_shr(V, 24)));
suspend;
end^
CREATE OR ALTER PROCEDURE MD5_INTTOHEX (
V BIGINT)
RETURNS (
RES CHAR(8) CHARACTER SET OCTETS)
AS
declare variable H char(16) = '0123456789ABCDEF';
begin
res = substring(h from bin_and(0x0F, bin_shr(V, 4))+1 for 1) ||
substring(h from bin_and(0x0F, V)+1 for 1)||
substring(h from bin_and(0x0F, bin_shr(V, 12))+1 for 1)||
substring(h from bin_and(0x0F, bin_shr(V, 8))+1 for 1)||
substring(h from bin_and(0x0F, bin_shr(V, 20))+1 for 1)||
substring(h from bin_and(0x0F, bin_shr(V, 16))+1 for 1)||
substring(h from bin_and(0x0F, bin_shr(V, 28))+1 for 1)||
substring(h from bin_and(0x0F, bin_shr(V, 24))+1 for 1);
suspend;
end^
SET TERM ; ^