Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Usenet -> c.d.o.misc -> Encrypting CLOBs with DBMS_CRYPTO
had a lot of problems using DBMS_CRYPTO with the express goal of
starting out with an unencrypted clob and ending up with an encrypted
clob. Why their stupid algorithm returns blobs instead of clobs is
really beyond me. Any way, I could not find my solution online so I
thought I'd post it here to help people that have the same problem.
These two procs encrypt and decrypt clobs in a test table, you have to use utl_encode.base64_encode and utl_encode.base64_decode to make the move from clob and blob and vise/versa.
CREATE OR REPLACE
PROCEDURE ENCRYPT_CLOB
( intval IN tst_clob_tbl.id_col%type)
IS
-- This proc gets a clob out of a table, encrypts it, and then puts it
back...
CLOB1 clob; -- select from table CLOB2 clob; -- temporary clob BLOB1 BLOB; -- temporary blob
Buffer_in RAW(32000);
Buffer_out varchar2(32000); -- allow for expansion
len number;
l number;
steps number;
left number;
chunksize number;
chunksize_hex varchar2(4);
offset number;
BEGIN
--encrypt the clob
sys.dbms_crypto.encrypt(dst => BLOB1,
src=> CLOB1,
typ => dbms_crypto.des_cbc_pkcs5,
key => l_key);
len := DBMS_LOB.GETLENGTH(BLOB1);
dbms_output.put_line('lenght encrypted blob : '||len);
steps := floor(len/amount);
left := mod(len,amount); -- this is the remainder chunk smaller than
amount
buffer_out:=utl_raw.cast_to_varchar2(utl_encode.base64_encode(buffer_in));
chunksize := length(buffer_out);
chunksize_hex := lpad(trim(to_char(chunksize,'XXXX')),4,'0000');
dbms_output.put_line(chunksize||' = '||chunksize_hex);
dbms_lob.writeappend(lob_loc => CLOB2, amount=> 4, buffer =>
chunksize_hex);
dbms_lob.writeappend(lob_loc => CLOB2, amount=>chunksize, buffer =>
buffer_out);
end loop;
if left > 0 then
buffer_in := dbms_lob.substr(BLOB1,left,len-left+1); -- last piece
buffer_out:=utl_raw.cast_to_varchar2(utl_encode.base64_encode(buffer_in));
chunksize := length(buffer_out);
chunksize_hex := lpad(trim(to_char(chunksize,'XXXX')),4,'0000'); dbms_output.put_line(chunksize||' = '||chunksize_hex);
dbms_lob.writeappend(lob_loc => CLOB2, amount=> 4, buffer =>
chunksize_hex);
dbms_lob.writeappend(lob_loc => CLOB2, amount=>chunksize, buffer =>
buffer_out);
end if;
-- write terminator
buffer_out := 'FFFF';
dbms_lob.writeappend(lob_loc => CLOB2, amount => 4, buffer =>
buffer_out);
CREATE OR REPLACE
PROCEDURE DECRYPT_CLOB
( intval IN tst_clob_tbl.id_col%type)
IS
-- This proc gets a clob out of a table, decrypts it, and then puts it
back...
CLOB1 clob; -- select from table CLOB2 clob; -- temporary clob BLOB1 BLOB; -- tempory blob
v_offset number;
chunksize number;
chunksize_hex varchar2(4);
v_done boolean := false;
BEGIN
v_offset:=1;
chunksize_hex := dbms_lob.substr(lob_loc => CLOB1,amount => 4,offset
=> v_offset);
chunksize := to_number(chunksize_hex,'XXXX');
if chunksize_hex <> 'FFFF' then
v_offset:=v_offset+4;
buffer_in := dbms_lob.substr(lob_loc => CLOB1,amount => chunksize,
offset => v_offset);
v_amount:=length(buffer_in);
buffer_out :=
utl_encode.base64_decode(utl_raw.cast_to_raw(buffer_in));
v_amount:=utl_raw.length(buffer_out);
begin
dbms_lob.writeappend(lob_loc => BLOB1,
amount => v_amount,
buffer => buffer_out);
exception
when others then
dbms_output.put_line('error in dbms_lob.writeappend');
dbms_output.put_line('v_amount : '||v_amount);
raise;
end;
v_offset := v_offset+chunksize;
else
v_done := true;
dbms_output.put_line('done, found terminator');
end if;
end loop;
len := DBMS_LOB.GETLENGTH(BLOB1);
dbms_output.put_line('lenght encrypted blob : '||len);
sys.dbms_crypto.decrypt(DST => CLOB2,
SRC => BLOB1, typ => dbms_crypto.des_cbc_pkcs5, key => l_key);
![]() |
![]() |