Oracle 等效于 C# HMACSHA256

Posted

技术标签:

【中文标题】Oracle 等效于 C# HMACSHA256【英文标题】:Oracle Equivalent to C# HMACSHA256 【发布时间】:2020-11-01 17:05:16 【问题描述】:

我正在尝试将 C# 功能移植到 Oracle,但遇到了 HMACSHA256 问题:

甲骨文

function HMACSha256(key in varchar2 default null,  str in varchar2)  return varchar2 is
   l_encryption_object       cp_encrypt.encryption_object;
   l_hashValue               raw(4000);
   l_str_raw raw(4000) := utl_raw.cast_to_raw(str);
   l_key_raw raw(4000) := utl_encode.base64_decode(utl_raw.cast_to_raw(key));
begin
--
   dbms_output.put_line('Key Bytes: '|| l_key_raw);
   dbms_output.put_line('String Bytes: '|| l_str_raw);
--
   l_hashValue :=  dbms_crypto.mac(src => l_str_raw,
                                   key => l_key_raw,
                                   typ => dbms_crypto.HMAC_SH256);
--
   dbms_output.put_line('Hash Bytes: '|| l_hashValue);
--         
return utl_raw.cast_to_varchar2(utl_encode.base64_encode(l_hashValue));
end HMACSha256;

输出

密钥字节:186F3464CC4D32B6AC52EA093090FBFFCEA46C25D8F380E60E12FFE3DEAB7DA2

的字符串字节:37343666663438372D333734332D343334332D613238312D316361383865393336303362504F5354687474707325334125324625324670726570726F64646174616875622E61636365737361636C6F75642E636F6D2532466170706C69636174696F6E2D6170692532467632253246696E7374616E636573313539343432303230383962373465353533376539303438373261643366333431313739363731316539424B70546347334E634D54644C577857672B556759673D3D P>

哈希字节:168248FA2030CFFDAFDE1590BA740F51671E62410A80EA7C17963B0E3A4865A0

C#

internal static string Sha256Hash(string key, string content)
        
            var keyBytes = Convert.FromBase64String(key);
            Console.WriteLine("Key Bytes:" + BitConverter.ToString(keyBytes));

            var contentBytes = Encoding.ASCII.GetBytes(content);
            Console.WriteLine("String Bytes:" + BitConverter.ToString(contentBytes));

            using (var hmac = new HMACSHA256(keyBytes))
            
                var signatureBytes = hmac.ComputeHash(contentBytes);
                Console.WriteLine("Hash Bytes:" + BitConverter.ToString(signatureBytes));
                return Convert.ToBase64String(signatureBytes);
            
        

输出

密钥字节:18-6F-34-64-CC-4D-32-B6-AC-52-EA-09-30-90-FB-FF-CE-A4-6C-25-D8-F3- 80-E6-0E-12-FF-E3-DE-AB-7D-A2

字符串字节数:37-34-36-66-66-34-38-37-2D-33-37-34-33-2D-34-33-34-33-2D-61-32-38- 31-2D-31-63-61-38-38-65-39-33-36-30-33-62-50-4F-53-54-68-74-74-70-73-25-33- 61-25-32-66-25-32-66-70-72-65-70-72-6F-64-64-61-74-61-68-75-62-2E-61-63-63- 65-73-73-61-63-6C-6F-75-64-2E-63-6F-6D-25-32-66-61-70-70-6C-69-63-61-74-69- 6F-6E-2D-61-70-69-25-32-66-76-32-25-32-66-69-6E-73-74-61-6E-63-65-73-31-35- 39-34-34-32-30-32-30-38-39-62-37-34-65-35-35-33-37-65-39-30-34-38-37-32-61- 64-33-66-33-34-31-31-37-39-36-37-31-31-65-39-42-4B-70-54-63-47-33-4E-63-4D- 54-64-4C-57-78-57-67-2B-55-67-59-67-3D-3D

哈希字节:05-54-E0-A0-55-90-E9-03-DE-60-B6-22-A3-52-81-ED-76-C0-6D-B7-02-F4- 96-76-53-AA-1C-09-AD-22-2B-61

所以基本上字符串和键字节在两者中都匹配,但是当我运行 HMACSHA256 哈希时,它们返回不同的值。

是否有任何相当于 C# HMACSHA256 的 Oracle 或者我只是做错了什么?

谢谢!

【问题讨论】:

【参考方案1】:

所以基本上字符串和键字节在两者中都匹配......

没有。

C# 和 Oracle 输出中的字符串字节不匹配。

如果将它们转换回 ASCII 字符串,则会得到以下结果:

甲骨文:746ff487-3743-4343-a281-1ca88e93603bPOSThttps%3A%2F%2Fpreproddatahub.accessacloud.com%2Fapplication-api%2Fv2%2Finstances15944202089b74e5537e904872ad3f3411796711e9BKpTcGWgYgYc=e9BKpTcGWgYgNc= C#: 746ff487-3743-4343-a281-1ca88e93603bPOSThttps%3a%2f%2fpreproddatahub.accessacloud.com%2fapplication-api%2fv2%2finstances15944202089b74e5537e904872ad3f3411796711e9BKpT+UgGNx=W 差异:------------------------------------------------------------^ --^--^----------------------------------^---------- --------^----^

两个字符串中六个字符的 URL 编码不同:Oracle 字符串使用大写字母,C# 字符串使用小写字母。

修复这六个差异,您的 C# 和 Oracle 代码将返回相同的哈希值。

【讨论】:

谢谢!我在 url 字符串上使用了 utl_url.escape,因此需要将其包装在 lower() 中。现在工作完美。好地方!

以上是关于Oracle 等效于 C# HMACSHA256的主要内容,如果未能解决你的问题,请参考以下文章

C#实现HMACSHA256加密算法

c#和java - hmacsha256 hash之间的区别

C# 等效于 Java 标点正则表达式

C# 等效于 AtlEscapeUrl

C# 等效于 Apache HttpAsyncClient

C# 等效于 VB DLL 函数声明 (InternetSetOption)?