Ошибка при использовании функции DBMS_CRYPTO для расшифровки данных CLOB - PullRequest
0 голосов
/ 27 сентября 2019

Мне поручено выполнить две функции Oracle, которые обеспечивают следующее:

  1. Возьмите CLOB в качестве ввода и зашифруйте его с помощью AES-256 и верните Encrypted CLOB
  2. Возьмите зашифрованныйCLOB в качестве входных данных, расшифруйте его, используя AES-256, и верните Decrypted CLOB

Данные CLOB огромны, и функции должны позаботиться об этом.

Я могу получитьчерез первую функцию, и она работает хорошо, то есть шифрование CLOB, с огромными данными:

create or replace 
function F_ENCRYPT_CLOB (ac_input IN CLOB) return CLOB is
l_clob CLOB;
lb_variable BLOB;
v_key RAW (320);
v_encryption_type PLS_INTEGER := DBMS_CRYPTO.AES_CBC_PKCS5; 
v_iv RAW (320);
l_dest_offset  PLS_INTEGER := 1;
l_src_offset   PLS_INTEGER := 1;
l_lang_context PLS_INTEGER := DBMS_LOB.default_lang_ctx;
l_warning      PLS_INTEGER;
l_step PLS_INTEGER := 1998;
begin
    SELECT VALUE
     INTO v_key
     FROM algparameters
     WHERE name = 'key';
   SELECT VALUE
    INTO v_iv
     FROM algparameters
    WHERE name = 'iv';

dbms_lob.createtemporary(lb_variable, true);


 sys.DBMS_CRYPTO.ENCRYPT(
                 dst => lb_variable,
                 src => ac_input,
                 typ => v_encryption_type,
                 key => v_key,
                 iv => v_iv
                 );

  DBMS_LOB.createTemporary(
    lob_loc => l_clob,
    cache   => TRUE);


  FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(lb_variable) - 1 )/l_step) LOOP
        l_clob := l_clob || UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(DBMS_LOB.substr(lb_variable, l_step, i * l_step + 1)));
      END LOOP;
   RETURN l_clob;

end F_ENCRYPT_CLOB;

Но я сталкиваюсь с проблемами при расшифровке ранее зашифрованного значения, используя аналогичные шаги:

create or replace 
function F_DECRYPT_CLOB (ac_input IN CLOB) return CLOB is 
  lb_variable CLOB; 
  l_blob BLOB;
  v_key RAW (320);
  v_encryption_type PLS_INTEGER := DBMS_CRYPTO.AES_CBC_PKCS5;
  v_iv RAW (320);
  l_dest_offset  PLS_INTEGER := 1;
  l_src_offset   PLS_INTEGER := 1;
  l_lang_context PLS_INTEGER := DBMS_LOB.default_lang_ctx;
  l_warning      PLS_INTEGER;

  l_raw     RAW(32767);
  l_amt     NUMBER := 7700;
  l_offset  NUMBER := 1;
  l_temp    VARCHAR2(32767);
  l_step PLS_INTEGER := 7700;

begin 
    SELECT VALUE
     INTO v_key
     FROM algparameters
    WHERE name = 'key';
   SELECT VALUE
     INTO v_iv
     FROM algparameters
    WHERE name = 'iv';

    dbms_lob.createtemporary(l_blob, true);

   FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(ac_input) - 1 )/l_amt) LOOP
      DBMS_LOB.read(ac_input, l_amt, l_offset, l_temp);
      l_offset := l_offset + l_amt;
      l_raw    := UTL_ENCODE.base64_decode(l_temp);
      DBMS_LOB.append (l_blob, TO_BLOB(l_raw));
    END LOOP; 

  dbms_lob.createtemporary(lb_variable, true);

 sys.DBMS_CRYPTO.DECRYPT( 
                 dst => lb_variable, 
                 src => l_blob, 
                 typ => v_encryption_type,--dbms_crypto.des_cbc_pkcs5, 
                 key => v_key,
                 iv => v_iv
                 ); 

   return lb_variable; 
end F_DECRYPT_CLOB;

Выдается ошибка:

ORA-06502: PL / SQL: ошибка с числовым значением или значением: ошибка преобразования в шестнадцатеричное в необработанное
ORA-06512: в "SN_PRE_STAGE_415.F_DECRYPT_CLOB", строка 33
06502. 00000 - «PL / SQL: ошибка числа или значения% s»
* Причина:
* Действие:

1 Ответ

0 голосов
/ 27 сентября 2019

Ошибка исходит из строки 33:

l_raw    := UTL_ENCODE.base64_decode(l_temp);

Функция base64_decode ожидает аргумент RAW, поэтому вы можете преобразовать имеющуюся строку:

l_raw    := UTL_ENCODE.base64_decode(UTL_RAW.cast_to_raw(l_temp));

то есть

   FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(ac_input) - 1 )/l_amt) LOOP
      DBMS_LOB.read(ac_input, l_amt, l_offset, l_temp);
      l_offset := l_offset + l_amt;
      l_raw    := UTL_ENCODE.base64_decode(UTL_RAW.cast_to_raw(l_temp));
      DBMS_LOB.append (l_blob, TO_BLOB(l_raw));
    END LOOP; 

Теперь выдает это

ORA-28817: функция PL / SQL вернула ошибку.
ORA-06512: в "SYS.DBMS_CRYPTO_FFI", строка 110
ORA-06512: в "SYS.DBMS_CRYPTO", строка 64
ORA-06512: в "STACKOVERFLOW.F_DECRYPT_CLOB", строка 39

В строке base-64 есть разрывы строк;те выбрасывают декодер.Вы можете использовать меньший размер чанка с l_amt = 64 и пропустить разрывы строк:

   FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(ac_input) - 1 )/(l_amt + 2)) LOOP
      DBMS_LOB.read(ac_input, l_amt, l_offset, l_temp);
      l_offset := l_offset + l_amt + 2;

, но, вероятно, проще и эффективнее убрать их всех за один раз, через новый l_clobпеременная:

create or replace 
function F_DECRYPT_CLOB (ac_input IN CLOB) return CLOB is 
  lb_variable CLOB; 
  l_clob CLOB;
  l_blob BLOB;
  ... 
begin 
   ...
    dbms_lob.createtemporary(l_blob, true);

   l_clob := replace(replace(ac_input, chr(13), null), chr(10), null);

   FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(l_clob) - 1 )/l_amt) LOOP
      DBMS_LOB.read(l_clob, l_amt, l_offset, l_temp);
      l_offset := l_offset + l_amt;
      l_raw    := UTL_ENCODE.base64_decode(utl_raw.cast_to_raw(l_temp));
      DBMS_LOB.append (l_blob, TO_BLOB(l_raw));
    END LOOP; 
   ...    
end F_DECRYPT_CLOB;
/

полностью:

create or replace 
function F_DECRYPT_CLOB (ac_input IN CLOB) return CLOB is 
  lb_variable CLOB; 
  l_clob CLOB;
  l_blob BLOB;
  v_key RAW (320);
  v_encryption_type PLS_INTEGER := DBMS_CRYPTO.AES_CBC_PKCS5;
  v_iv RAW (320);
  l_dest_offset  PLS_INTEGER := 1;
  l_src_offset   PLS_INTEGER := 1;
  l_lang_context PLS_INTEGER := DBMS_LOB.default_lang_ctx;
  l_warning      PLS_INTEGER;

  l_raw     RAW(32767);
  l_amt     NUMBER := 7700;
  l_offset  NUMBER := 1;
  l_temp    VARCHAR2(32767);
  l_step PLS_INTEGER := 7700;

begin 
    SELECT VALUE
     INTO v_key
     FROM algparameters
    WHERE name = 'key';
   SELECT VALUE
     INTO v_iv
     FROM algparameters
    WHERE name = 'iv';

    dbms_lob.createtemporary(l_blob, true);

   l_clob := replace(replace(ac_input, chr(13), null), chr(10), null);

   FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(l_clob) - 1 )/l_amt) LOOP
      DBMS_LOB.read(l_clob, l_amt, l_offset, l_temp);
      l_offset := l_offset + l_amt;
      l_raw    := UTL_ENCODE.base64_decode(utl_raw.cast_to_raw(l_temp));
      DBMS_LOB.append (l_blob, TO_BLOB(l_raw));
    END LOOP; 

  dbms_lob.createtemporary(lb_variable, true);

 sys.DBMS_CRYPTO.DECRYPT( 
                 dst => lb_variable, 
                 src => l_blob, 
                 typ => v_encryption_type,--dbms_crypto.des_cbc_pkcs5, 
                 key => v_key,
                 iv => v_iv
                 ); 

   return lb_variable; 
end F_DECRYPT_CLOB;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...