使用Unicode转义的有效负载生成hmac sha1,oracle plsql

时间:2019-01-10 16:33:34

标签: oracle api unicode sha1 hmac

所以我有一个ORDS端点(Oracle Rest Data Services),该端点从Facebook API接收JSON负载,并在请求的标头中包含一个变量X-Hub-Signature。

我必须验证收到的请求,所以我知道它来自Facebook。

我必须生成一个哈希,以接收Facebook和我共享的有效负载(BLOB)和密钥(字符串)(app_secret),然后将其与X-Hub-Signature的值进行比较,这样我就可以确认这是一个有效的请求。

问题是,Facebook说: “请注意,我们使用有效载荷的转义的unicode版本生成签名,并使用小写的十六进制数字。如果仅根据解码的字节进行计算,则最终将获得不同的签名。例如,字符串äöå应该转义为\ u00e4 \ u00f6 \ u00e5。”

到目前为止,我的哈希值与我收到的有效负载相匹配,但是我尝试使用这些äöå字符,但我不确定它是否有效,因为所有hmac在线编码器看起来都不太好,我也不会不知道(在在线编码器上)如何对它们进行Unicode编码。

到目前为止,我有这个:

FUNCTION validate_payload (p_x_hub_signature      in     varchar2,
                           p_json_payload         in     blob)
RETURN varchar2
IS
    v_app_secret        varchar2(4000) := '2f2f2f2f2f2f2f';
    l_mac               raw(10000);
    v_x_hub_signature   varchar2(4000);

BEGIN

    l_mac := dbms_crypto.mac (src => p_json_payload,
                              typ => dbms_crypto.hmac_sh1,
                              key => UTL_I18N.STRING_TO_RAW (v_app_secret, 'AL32UTF8'));

    v_x_hub_signature := 'sha1='||lower(l_mac);

    return v_x_hub_signature;      

END;

您能对此提供任何反馈吗? 这样对吗?

在此先感谢,不好意思的英语或解释!

3 个答案:

答案 0 :(得分:0)

这是一个PL / SQL解决方案。它比Sentinel的提议所需的编码更少,并且可能更清晰。

declare
    v_app_secret varchar2(100) := 'äaöå ab\ABC';
    escaped varchar2(100);
    item varchar2(6);
begin

    escaped := replace(regexp_replace(ASCIISTR(v_app_secret), '\\([[:xdigit:]]{4})', '\u\1'), '\u005C', '\\');

    for i in 1..regexp_count(escaped, '\\u[[:xdigit:]]{4}') loop
        item := regexp_substr(escaped, '\\u[[:xdigit:]]{4}', 1, i);
        escaped := replace(escaped, item, lower(item));        
    end loop;
    dbms_output.put_line(escaped);

end;


\u00e4a\u00f6\u00e5 ab\\ABC

假设\需要翻译成\\

答案 1 :(得分:0)

从@Wernfried Domscheit使用ASCIISTRregexp_replace的方法开始,可以将其扩展到整个替换列表以获取小写版本:

with sample(str) as (
  select 'äöå ab\ABC' from dual
), patterns(ord, pat, rep) as (
  select 1, '\\A([[:xdigit:]]{3})', '\\a\1' from dual union all
  select 2, '\\B([[:xdigit:]]{3})', '\\b\1' from dual union all
  select 3, '\\C([[:xdigit:]]{3})', '\\c\1' from dual union all
  select 4, '\\D([[:xdigit:]]{3})', '\\d\1' from dual union all
  select 5, '\\E([[:xdigit:]]{3})', '\\e\1' from dual union all
  select 6, '\\F([[:xdigit:]]{3})', '\\f\1' from dual union all
  select 7, '\\([[:xdigit:]])A([[:xdigit:]]{2})', '\\\1a\2' from dual union all
  select 8, '\\([[:xdigit:]])B([[:xdigit:]]{2})', '\\\1b\2' from dual union all
  select 9, '\\([[:xdigit:]])C([[:xdigit:]]{2})', '\\\1c\2' from dual union all
  select 10, '\\([[:xdigit:]])D([[:xdigit:]]{2})', '\\\1d\2' from dual union all
  select 11, '\\([[:xdigit:]])E([[:xdigit:]]{2})', '\\\1e\2' from dual union all
  select 12, '\\([[:xdigit:]])F([[:xdigit:]]{2})', '\\\1f\2' from dual union all
  select 13, '\\([[:xdigit:]]{2})A([[:xdigit:]])', '\\\1a\2' from dual union all
  select 14, '\\([[:xdigit:]]{2})B([[:xdigit:]])', '\\\1b\2' from dual union all
  select 15, '\\([[:xdigit:]]{2})C([[:xdigit:]])', '\\\1c\2' from dual union all
  select 16, '\\([[:xdigit:]]{2})D([[:xdigit:]])', '\\\1d\2' from dual union all
  select 17, '\\([[:xdigit:]]{2})E([[:xdigit:]])', '\\\1e\2' from dual union all
  select 18, '\\([[:xdigit:]]{2})F([[:xdigit:]])', '\\\1f\2' from dual union all
  select 19, '\\([[:xdigit:]]{3})A', '\\\1a' from dual union all
  select 20, '\\([[:xdigit:]]{3})B', '\\\1b' from dual union all
  select 21, '\\([[:xdigit:]]{3})C', '\\\1c' from dual union all
  select 22, '\\([[:xdigit:]]{3})D', '\\\1d' from dual union all
  select 23, '\\([[:xdigit:]]{3})E', '\\\1e' from dual union all
  select 24, '\\([[:xdigit:]]{3})F', '\\\1f' from dual union all
  select 25, '\\([[:xdigit:]]{4})', '\u\1' from dual union all
  select 26, '\\u005c', '\\\\' from dual
), recur(ord, str, tr) as (
  select ord, str
       , REGEXP_REPLACE(asciistr(str), pat, rep)
    from sample
    join patterns
      on ord = 1
  union all
  select recur.ord+1, str
       , REGEXP_REPLACE(tr, pat, rep)
    from recur
    join patterns
      on patterns.ord = recur.ord + 1
)
select * from recur where ord = 26;

如果您希望执行PL / SQL函数,则可以嵌套一系列转换并将其放入函数中。如果您不希望将\ u005c最终转换为\,只需删除外部的regexp_replace:

create or replace function Escape_Unicode(pCLOB clob) RETURN clob is
BEGIN
  return  regexp_replace(
            regexp_replace(
              regexp_replace(
                regexp_replace(
                  regexp_replace(
                    regexp_replace(
                      regexp_replace(
                        regexp_replace(
                          regexp_replace(
                            regexp_replace(
                              regexp_replace(
                                regexp_replace(
                                  regexp_replace(
                                    regexp_replace(
                                      regexp_replace(
                                        regexp_replace(
                                          regexp_replace(
                                            regexp_replace(
                                              regexp_replace(
                                                regexp_replace(
                                                  regexp_replace(
                                                    regexp_replace(
                                                      regexp_replace(
                                                        regexp_replace(
                                                          regexp_replace(
                                                            regexp_replace(
                                                              asciistr(pClOB)
                                                              , '\\A([[:xdigit:]]{3})'
                                                              , '\\a\1'
                                                            )
                                                            , '\\B([[:xdigit:]]{3})'
                                                            , '\\b\1'
                                                          )
                                                          , '\\C([[:xdigit:]]{3})'
                                                          , '\\c\1'
                                                        )
                                                        , '\\D([[:xdigit:]]{3})'
                                                        , '\\d\1'
                                                      )
                                                      , '\\E([[:xdigit:]]{3})'
                                                      , '\\e\1'
                                                    )
                                                    , '\\F([[:xdigit:]]{3})'
                                                    , '\\f\1'
                                                  )
                                                  , '\\([[:xdigit:]])A([[:xdigit:]]{2})'
                                                  , '\\\1a\2'
                                                )
                                                , '\\([[:xdigit:]])B([[:xdigit:]]{2})'
                                                , '\\\1b\2'
                                              )
                                              , '\\([[:xdigit:]])C([[:xdigit:]]{2})'
                                              , '\\\1c\2'
                                            )
                                            , '\\([[:xdigit:]])D([[:xdigit:]]{2})'
                                            , '\\\1d\2'
                                          )
                                          , '\\([[:xdigit:]])E([[:xdigit:]]{2})'
                                          , '\\\1e\2'
                                        )
                                        , '\\([[:xdigit:]])F([[:xdigit:]]{2})'
                                        , '\\\1f\2'
                                      )
                                      , '\\([[:xdigit:]]{2})A([[:xdigit:]])'
                                      , '\\\1a\2'
                                    )
                                    , '\\([[:xdigit:]]{2})B([[:xdigit:]])'
                                    , '\\\1b\2'
                                  )
                                  , '\\([[:xdigit:]]{2})C([[:xdigit:]])'
                                  , '\\\1c\2'
                                )
                                , '\\([[:xdigit:]]{2})D([[:xdigit:]])'
                                , '\\\1d\2'
                              )
                              , '\\([[:xdigit:]]{2})E([[:xdigit:]])'
                              , '\\\1e\2'
                            )
                            , '\\([[:xdigit:]]{2})F([[:xdigit:]])'
                            , '\\\1f\2'
                          )
                          , '\\([[:xdigit:]]{3})A'
                          , '\\\1a'
                        )
                        , '\\([[:xdigit:]]{3})B'
                        , '\\\1b'
                      )
                      , '\\([[:xdigit:]]{3})C'
                      , '\\\1c'
                    )
                    , '\\([[:xdigit:]]{3})D'
                    , '\\\1d'
                  )
                  , '\\([[:xdigit:]]{3})E'
                  , '\\\1e'
                )
                , '\\([[:xdigit:]]{3})F'
                , '\\\1f'
              )
              , '\\([[:xdigit:]]{4})'
              , '\u\1'
            )
            , '\\u005c'
            , '\\\\'
          );
end;
/
select escape_unicode('äöå ab\ABCd') from dual;

答案 2 :(得分:0)

我刚刚意识到,我可能已使您误入歧途。正如Sentinel所述,v_app_secret不需要翻译,只需翻译p_json_payload(这是一个BLOB)即可。

到目前为止,我已经提出了这个建议:您认为可以吗?我没有办法确定:/

FUNCTION validate_payload (p_x_hub_signature      in     varchar2,
                           p_json_payload         in     blob)
RETURN varchar2
IS
    v_app_secret        varchar2(4000) := '3f2f2f2f23f23f23';
    l_mac               raw(10000);
    v_x_hub_signature   varchar2(4000);
BEGIN
    l_mac := dbms_crypto.mac (src => UTL_I18N.STRING_TO_RAW (utl_raw.cast_to_varchar2 (p_json_payload),'AL32UTF8'),
                              typ => dbms_crypto.hmac_sh1,
                              key => UTL_I18N.STRING_TO_RAW (v_app_secret, 'AL32UTF8'));

    v_x_hub_signature := 'sha1='||lower(l_mac);

    dbms_output.put_line(v_x_hub_signature);

    return v_x_hub_signature;      

END;