Created
March 30, 2023 11:06
-
-
Save wqweto/c069aeaad424091f6b8813bd9d8776de to your computer and use it in GitHub Desktop.
Encode JSON Web Token in MSSQL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
IF OBJECT_ID('fn_sys_GetEncodedJwt') IS NOT NULL DROP FUNCTION fn_sys_GetEncodedJwt | |
GO | |
/* | |
DECLARE @Header NVARCHAR(MAX) = N'{"alg":"HS512","typ":"JWT"}', @Payload NVARCHAR(MAX) = N'{"sub":"1234567890","name":"JohnDoe","iat":1516239022}' | |
SELECT dbo.fn_sys_GetEncodedJwt('HS512', @Header, @Payload, CONVERT(VARBINARY(MAX), 'Password')) | |
*/ | |
CREATE FUNCTION fn_sys_GetEncodedJwt ( | |
@Algo VARCHAR(50) | |
, @Header NVARCHAR(MAX) | |
, @Payload NVARCHAR(MAX) | |
, @Secret VARBINARY(MAX) | |
) RETURNS VARCHAR(MAX) | |
WITH SCHEMABINDING AS | |
BEGIN | |
DECLARE @BlockSize INT | |
, @Idx INT | |
, @Data VARBINARY(MAX) | |
, @InnerPad VARBINARY(MAX) | |
, @OuterPad VARBINARY(MAX) | |
--- data = base64urlEncode( header ) + "." + base64urlEncode( payload ) | |
SET @Data = CONVERT(VARBINARY(MAX), CONVERT(VARCHAR(MAX), @Header COLLATE Latin1_General_100_CI_AI_SC_UTF8)) | |
SET @Header = REPLACE(REPLACE(REPLACE(CONVERT(XML, '').value('xs:base64Binary(sql:variable("@Data"))', 'VARCHAR(MAX)'), '+', '-'), '/', '_'), '=', '') | |
SET @Data = CONVERT(VARBINARY(MAX), CONVERT(VARCHAR(MAX), @Payload COLLATE Latin1_General_100_CI_AI_SC_UTF8)) | |
SET @Payload = REPLACE(REPLACE(REPLACE(CONVERT(XML, '').value('xs:base64Binary(sql:variable("@Data"))', 'VARCHAR(MAX)'), '+', '-'), '/', '_'), '=', '') | |
SET @Data = CONVERT(VARBINARY(MAX), CONVERT(VARCHAR(MAX), COALESCE(@Header + '.', '') + @Payload)) | |
--- hashedData = hash( data, secret ) | |
SET @Algo = CASE @Algo WHEN 'HS512' THEN 'SHA2_512' WHEN 'HS256' THEN 'SHA2_256' ELSE @Algo END | |
SET @BlockSize = CASE @Algo WHEN 'SHA2_512' THEN 128 WHEN 'MD2' THEN 16 ELSE 64 END | |
SET @Secret = CASE WHEN LEN(@Secret) > @BlockSize THEN HASHBYTES(@Algo, @Secret) ELSE @Secret END | |
SELECT @InnerPad = 0x, @OuterPad = 0x, @Idx = 1 | |
WHILE @Idx <= @BlockSize | |
BEGIN | |
SELECT @InnerPad = @InnerPad + CONVERT(VARBINARY(1), SUBSTRING(@Secret, @Idx, 1) ^ 54) | |
, @OuterPad = @OuterPad + CONVERT(VARBINARY(1), SUBSTRING(@Secret, @Idx, 1) ^ 92) | |
, @Idx = @Idx + 1 | |
END | |
SET @Data = HASHBYTES(@Algo, @OuterPad + HASHBYTES(@Algo, @InnerPad + @Data)) | |
--- signature = base64urlEncode( hashedData ) | |
RETURN COALESCE(@Header + '.', '') + @Payload + '.' + REPLACE(REPLACE(REPLACE(CONVERT(XML, '').value('xs:base64Binary(sql:variable("@Data"))', 'VARCHAR(MAX)'), '+', '-'), '/', '_'), '=', '') | |
END | |
GO |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment