oracle-databaseplsqlsha256

how can I encode string in HMAC-SHA256 using pl/sql?


I'm working on REST API authorization in PL/SQL using Oracle database 11g Express Edition. I have api_key, nonce and signature as IN variables for every procedure.

Signature is a HMAC-SHA256 encoded string containing api_secret stored in my database. I want check if signature matching my api_secret in database.

My question is how can I encode string in HMAC-SHA256 using pl/sql?


Solution

  • sha256.encrypt for Oracle 10g,11g by CruiserX was huge help for my HMAC-SHA256 API authorization in oracle XE.

    Complete source code for my version with hmac-sha256 API authorization in oracle 11g XE you can find in my plsql_hmac-sha256 git project. But to perform HMAC keying we basically need store some basic information like nonce of last user request. And of course some function for hashing in my case (oracle 11gXE) sha256.encrypt . but in newer version oracle did provide better buil-in options for that like dbms_crypto.hash function.

       PROCEDURE HMAC_AUTHORIZATION (i_api_key  IN   VARCHAR2, i_api_nonce IN NUMBER, i_api_sign IN VARCHAR, R OUT NUMBER)
       IS
        p_auth_id                   NUMBER(10);
        p_api_sign_msg              VARCHAR2(500);
        p_api_nonce                 NUMBER(35);
        p_api_sign                  VARCHAR2(500);
        system_sign                 VARCHAR2(500);
    
        BEGIN
        SELECT AUTH_ID, API_NONCE INTO p_auth_id, p_api_nonce FROM USER_AUTH WHERE API_KEY = i_api_key AND AUTH_STATUS = 1 AND API_NONCE < i_api_nonce;
    
        /* User signature */
        p_api_sign_msg := p_auth_id || i_api_key || i_api_nonce;
        p_api_sign := sha256.encrypt(p_api_sign_msg);
    
        /* system signature */
        system_sign := sha256.encrypt(p_auth_id || i_api_key || i_api_nonce);
    
        IF p_api_sign = system_sign THEN
            UPDATE USER_AUTH SET REQUESTS_COUNT = REQUESTS_COUNT+1, API_NONCE = i_api_nonce, LAST_REQUEST = SYSDATE WHERE API_KEY = i_api_key AND AUTH_STATUS = 1 AND AUTH_ID = p_auth_id;
            commit;
            R := 1;
        ELSE
            R :=  0;
        END IF;
    
        EXCEPTION WHEN NO_DATA_FOUND THEN
            R :=  0;
        WHEN OTHERS THEN
           R :=  0;
        END HMAC_AUTHORIZATION;
    

    Thanks for help. Maybe someone will find this useful :)