How to encrypt decrypt image in oracle 11g - oracle

Hye. I'm new in oracle. Currently, I've create a package for encrypt and decrypt the text in the database. Now i want to encrypt and decrypt the image that has been stored in my database.
This is the package that i use for encrypt and decrypt the text.
CREATE OR REPLACE PACKAGE enc_dec
AS
FUNCTION encrypt (p_plainText VARCHAR2) RETURN RAW DETERMINISTIC;
FUNCTION decrypt (p_encryptedText RAW) RETURN VARCHAR2 DETERMINISTIC;
END;
/
CREATE OR REPLACE PACKAGE BODY enc_dec
AS
encryption_type PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_DES
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
/*
ENCRYPT_DES is the encryption algorithem. Data Encryption Standard. Block cipher.
Uses key length of 56 bits.
CHAIN_CBC Cipher Block Chaining. Plaintext is XORed with the previous ciphertext
block before it is encrypted.
PAD_PKCS5 Provides padding which complies with the PKCS #5: Password-Based
Cryptography Standard
*/
encryption_key RAW (32) := UTL_RAW.cast_to_raw('MyEncryptionKey');
-- The encryption key for DES algorithem, should be 8 bytes or more. s3curiTKEY4App
FUNCTION encrypt (p_plainText VARCHAR2) RETURN RAW DETERMINISTIC
IS
encrypted_raw RAW (2000);
BEGIN
encrypted_raw := DBMS_CRYPTO.ENCRYPT
(
src => UTL_RAW.CAST_TO_RAW (p_plainText),
typ => encryption_type,
key => encryption_key
);
RETURN encrypted_raw;
END encrypt;
FUNCTION decrypt (p_encryptedText RAW) RETURN VARCHAR2 DETERMINISTIC
IS
decrypted_raw RAW (2000);
BEGIN
decrypted_raw := DBMS_CRYPTO.DECRYPT
(
src => p_encryptedText,
typ => encryption_type,
key => encryption_key
);
RETURN (UTL_RAW.CAST_TO_VARCHAR2 (decrypted_raw));
END decrypt;
END;
/
So what is the function to encrypt and decrypt the image? can you show me the query?

An image is a binary file. Since those files tend to be larger than 4k bytes, you would use a BLOB datatype most likely. In this case, you can use the procedure DBMS_CRYPTO.encrypt that works with BLOBs.

Related

Cannot Decrypt Varchar2 password using DBMS_CRYPTO.DECRYPT

what i need
i need to decrypt password store in database.
I tried sql
https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_crypto.htm#i1001225
sql
DECLARE
input_string VARCHAR2 (200) := 'Secret Message';
encrypted_answer_raw RAW(2000);
output_string VARCHAR2 (200);
encrypted_raw RAW (2000); -- stores encrypted binary text
decrypted_raw RAW (2000); -- stores decrypted binary text
num_key_bytes NUMBER := 256/8; -- key length 256 bits (32 bytes)
key_bytes_raw RAW (32); -- stores 256-bit encryption key
encryption_type PLS_INTEGER := -- total encryption type
DBMS_CRYPTO.ENCRYPT_AES256
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
BEGIN
DBMS_OUTPUT.PUT_LINE ( 'Original string: ' || input_string);
key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes);
encrypted_raw := DBMS_CRYPTO.ENCRYPT
(
src => UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8'),
typ => encryption_type,
key => key_bytes_raw
);
-- The encrypted value "encrypted_raw" can be used here
debug_msg('encrypted_raw'||encrypted_raw);
Decryption code
Code Works
decrypted_raw := DBMS_CRYPTO.DECRYPT
(
src => encrypted_raw,
typ => encryption_type,
key => key_bytes_raw
);
output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
Code Doesn't works
encrypted_answer_raw:=utl_raw.cast_to_raw('989628CCF16292A73FEB63D4694C8129');
decrypted_raw := DBMS_CRYPTO.DECRYPT
(
src => encrypted_answer_raw,
typ => encryption_type,
key => key_bytes_raw
);
output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);
END;
Error
Error report -
ORA-28817: PL/SQL function returned an error.
ORA-06512: at "SYS.DBMS_CRYPTO_FFI", line 67
ORA-06512: at "SYS.DBMS_CRYPTO", line 44
ORA-06512: at line 25
28817. 00000 - "PL/SQL function returned an error."
*Cause: A PL/SQL function returned an error unexpectedly.
*Action: This is an internal error. Enable tracing to find more
information. Contact Oracle customer support if needed.
*Document: NO
989628CCF16292A73FEB63D4694C8129 is database enrypted password stored in db.
any help is most welcome.
I suspect that instead of doing
encrypted_answer_raw := utl_raw.cast_to_raw('989628CCF16292A73FEB63D4694C8129');
you may want to do
encrypted_answer_raw := hextoraw('989628CCF16292A73FEB63D4694C8129');
I believe the problem is that the password is not really 989628CCF16292A73FEB63D4694C8129, but rather –(Ěńb’§?ëcÔiL) (displayed in win1250 codepage), despite your Oracle client software showing raw columns as hexa strings.
As a sidenote...
All those comments under your question, stating that you should store+compare password hashes instead of encrypting+decrypting them, are valid.

How to encrypt nvarchar column in oracle?

I have a table containing nvarchar datatype columns (contains text in different languages). I want to encrypt data before inserting into table and decrypt the same while fetching records.
Please suggest how i can achieve this.
Encryption and decryption should be done through a private key.
Hoping, my question is clear. Please confirm if i need to provide more information.
Note that it is probably wiser to crypt and decrypt your data directly in your application rather than in the database.
You can use Oracle's DBMS_CRYPTO package. There is an example in the middle of the documentation page.
First you need to make a package to access the cipher type from SQL expression. Let's say you want AES256 in CBC mode with padding:
CREATE PACKAGE pkg_so_42979606
AS
FUNCTION cipher_type RETURN PLS_INTEGER;
END pkg_so_42979606;
/
CREATE PACKAGE BODY pkg_so_42979606
AS
ctype CONSTANT PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_AES256
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
FUNCTION cipher_type RETURN PLS_INTEGER
IS
BEGIN
RETURN ctype;
END;
END pkg_so_42979606;
/
Then you will need a key. You can ask Oracle to generate one. To easily handle it I'll move it in Base64. Let's draw one:
DECLARE
key_bytes_raw RAW(32);
key_char NVARCHAR2(64);
BEGIN
key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES(32);
key_char := UTL_I18N.RAW_TO_CHAR(UTL_ENCODE.BASE64_ENCODE(key_bytes_raw), 'AL32UTF8');
DBMS_OUTPUT.PUT_LINE('Key: ' || key_char);
END;
/
Key: pMV3D4xhyfNxp3YyfLWzAErGcKkIjK3X6uc/WIeVTls=
Thus the cipher key I'll use is pMV3D4xhyfNxp3YyfLWzAErGcKkIjK3X6uc/WIeVTls=.
Now I'll use a test table
CREATE TABLE so_42979606 (
id NUMBER PRIMARY KEY,
data NVARCHAR2(2000));
You can insert encrypted data:
INSERT INTO so_42979606
VALUES (1,
DBMS_CRYPTO.ENCRYPT(UTL_I18N.STRING_TO_RAW('My clear data', 'AL32UTF8'),
pkg_so_42979606.cipher_type(),
UTL_ENCODE.BASE64_DECODE(UTL_I18N.STRING_TO_RAW('pMV3D4xhyfNxp3YyfLWzAErGcKkIjK3X6uc/WIeVTls=', 'AL32UTF8'))));
And retrieve the encrypted data in clear.
SELECT id, UTL_I18N.RAW_TO_NCHAR(DBMS_CRYPTO.DECRYPT(data,
pkg_so_42979606.cipher_type(),
UTL_ENCODE.BASE64_DECODE(UTL_I18N.STRING_TO_RAW('pMV3D4xhyfNxp3YyfLWzAErGcKkIjK3X6uc/WIeVTls=', 'AL32UTF8'))),
'AL32UTF8') data
FROM so_42979606;
ID DATA
-- ----------------------
1 My clear data

Oracle BLOB to base64 CLOB

Can I convert an oracle BLOB to Base64 CLOB in One go?
like:
CREATE TABLE test
(
image BLOB,
imageBase64 CLOB
);
INSERT INTO test(image)
VALUES (LOAD_FILE('/full/path/to/new/image.jpg'));
UPDATE test SET imageBase64 = UTL_ENCODE.base64_encode(image);
commit;
I know I can add functions/Stored proc to do the work. Performance aspect is very important,so I am asking if there is a way to overcome the 32K limitation by directly pushing the data into a CLOB.
This function got from here should do the job.
CREATE OR REPLACE FUNCTION base64encode(p_blob IN BLOB)
RETURN CLOB
-- -----------------------------------------------------------------------------------
-- File Name : http://oracle-base.com/dba/miscellaneous/base64encode.sql
-- Author : Tim Hall
-- Description : Encodes a BLOB into a Base64 CLOB.
-- Last Modified: 09/11/2011
-- -----------------------------------------------------------------------------------
IS
l_clob CLOB;
l_step PLS_INTEGER := 12000; -- make sure you set a multiple of 3 not higher than 24573
BEGIN
FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(p_blob) - 1 )/l_step) LOOP
l_clob := l_clob || UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(DBMS_LOB.substr(p_blob, l_step, i * l_step + 1)));
END LOOP;
RETURN l_clob;
END;
/
Then the update can look like
UPDATE test SET imageBase64 = base64encode(image);
Note that maybe the function should be optimized with the function DBMS_LOB.APPEND instead of that concatenation operator. Try that if you have performance problems.
Provided that stored procs would despite be a viable alternative for you, here's one possible solution to your problem ...
First, let's make that nice base64encode() function of Tim Hall's into a procedure ...
create or replace procedure base64encode
( i_blob in blob
, io_clob in out nocopy clob )
is
l_step pls_integer := 22500; -- make sure you set a multiple of 3 not higher than 24573
l_converted varchar2(32767);
l_buffer_size_approx pls_integer := 1048576;
l_buffer clob;
begin
dbms_lob.createtemporary(l_buffer, true, dbms_lob.call);
for i in 0 .. trunc((dbms_lob.getlength(i_blob) - 1 )/l_step) loop
l_converted := utl_raw.cast_to_varchar2(utl_encode.base64_encode(dbms_lob.substr(i_blob, l_step, i * l_step + 1)));
dbms_lob.writeappend(l_buffer, length(l_converted), l_converted);
if dbms_lob.getlength(l_buffer) >= l_buffer_size_approx then
dbms_lob.append(io_clob, l_buffer);
dbms_lob.trim(l_buffer, 0);
end if;
end loop;
dbms_lob.append(io_clob, l_buffer);
dbms_lob.freetemporary(l_buffer);
end;
The "trick" here is to directly use the persistent LOB locators in calls to procedures/functions. Why "persistent"? Because if you create a function that returns a LOB, then there's a temporary LOB created in background and this means some TEMP disk/memory usage and LOB content copying involved. For large LOBs this may imply a performance hit. In order to satisfy your requirement of making this the most performing possible, you should avoid this TEMP space usage. Hence, for this approach, a stored procedure instead of a function must be used.
Then, of course, the procedure must be fed with persistent LOB locators. You have to do that, again, with a stored procedure, where you e.g. insert an empty LOB (effectively creating a new LOB locator) to a table first, and then supplying that newly created LOB locator to the base64 encoding routine ...
create or replace procedure load_and_encode_image
( i_file_name in varchar2 )
is
l_input_bfile bfile := bfilename('DIR_ANYTHING', i_file_name);
l_image_base64_lob test.imageBase64%type;
l_image_raw test.image%type;
begin
insert into test(image, imageBase64)
values (empty_blob(), empty_clob())
returning image, imageBase64
into l_image_raw, l_image_base64_lob;
begin
dbms_lob.fileopen(l_input_bfile);
dbms_lob.loadfromfile(
dest_lob => l_image_raw,
src_lob => l_input_bfile,
amount => dbms_lob.getlength(l_input_bfile)
);
dbms_lob.fileclose(l_input_bfile);
exception
when others then
if dbms_lob.fileisopen(l_input_bfile) = 1 then
dbms_lob.fileclose(l_input_bfile);
end if;
raise;
end;
base64encode(
i_blob => l_image_raw,
io_clob => l_image_base64_lob
);
end;
Note: Of course, if you base64-encode only small files (the actual size depends on your PGA settings, I guess; a question for a DBA, this is), then the function-based approach may be equally performing than this procedure-based one. Base64-encoding a 200MB file on my laptop took 55 seconds with the function+update approach, 14 seconds with the procedure approach. Not exactly a speed demon, so choose what suits your needs.
Note: I believe this procedure-based approach may be further speeded up by reading the file to inmemory chunks in loop, base64-encoding the chunks to another inmemory chunks and appending them both to the target persistent LOBs. That way you should make the workload even easier by avoiding re-reading the full test.image LOB contents by the base64encode() procedure.
I solved this same problem at work by using a Java stored procedure. There is no chunking/contatenation of VARCHAR2s involved in such an approach, since the ability to encode/decode base64 is natively built into Java, simply writing an Oracle function that thinly wraps the Java method works well and is high-performance since as soon as you've executed it a few times, the HotSpot JVM compiles the Java proc into low-level code (high performance just like a C stored function). I'll edit this answer later and add the details about that Java code.
But to step back just one step, question why are you storing this data as both a BLOB and base64 encoded (CLOB)? Is it because you have clients that want to consume the data in the latter format? I'd really prefer to only store the BLOB format. One reason why is that the base64 encoded version can be double the size of the original binary BLOB, so storing them both means possibly 3x the storage.
One solution, the one I implemented at work, to create your own Java stored function base64_encode() that encodes binary --> base64 and then use that function to encode base64 on the fly at query time (it's not expensive). From the application/client side, you would query something like SELECT base64_encode(image) FROM test WHERE ...
If the application code can't be touched (ie COTS application) or if your developers aren't thrilled about using a function, you could abstract this for them (since you are using 11g+) by using a VIRTUAL (computed) column on the table which contains the computed base64_encode(image). It would function like a view, in that it wouldn't physically store the encoded CLOBs, but would generate them at query time. To any client, they would not be able to tell they are not reading a physical column. The other benefit is that if you ever update the jpg (BLOB), the virtual CLOB is immediately and automatically updated. If you ever have to insert/update/delete a huge batch of BLOBs, you'd save 66% of the redo/archivelog volume from not having to process all the CLOBs.
Lastly, for performance, make very sure you are using SecureFile LOBs (both for BLOBs and CLOBs). They really are much faster and better in just about every way.
UPDATE - I found my code, at least the version that uses a Java Stored Procedure to do the opposite (converting a base64 encoded CLOB to its binary BLOB version). It would not be that difficult to write the inverse.
--DROP FUNCTION base64_decode ;
--DROP java source base64;
-- This is a PLSQL java wrapper function
create or replace
FUNCTION base64_decode (
myclob clob)
RETURN blob
AS LANGUAGE JAVA
NAME 'Base64.decode (
oracle.sql.CLOB)
return oracle.sql.BLOB';
/
-- The Java code that base64 decodes a clob and returns a blob.
create or replace and compile java source named base64 as
import java.sql.*;
import java.io.*;
import oracle.sql.*;
import sun.misc.BASE64Decoder;
import oracle.jdbc.driver.*;
public class Base64 {
public static oracle.sql.BLOB decode(oracle.sql.CLOB myBase64EncodedClob)
{
BASE64Decoder base64 = new BASE64Decoder();
OutputStream outstrm = null;
oracle.sql.BLOB myBlob = null;
ByteArrayInputStream instrm = null;
try
{
if (!myBase64EncodedClob.equals("Null"))
{
Connection conn = new OracleDriver().defaultConnection();
myBlob = oracle.sql.BLOB.createTemporary(conn, false,oracle.sql.BLOB.DURATION_CALL);
outstrm = myBlob.getBinaryOutputStream();
ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
InputStream in = myBase64EncodedClob.getAsciiStream();
int c;
while ((c = in.read()) != -1)
{
byteOutStream.write((char) c);
}
instrm = new ByteArrayInputStream(byteOutStream.toByteArray());
try // Input stream to output Stream
{
base64.decodeBuffer(instrm, outstrm);
}
catch (Exception e)
{
e.printStackTrace();
}
outstrm.close();
instrm.close();
byteOutStream.close();
in.close();
conn.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return myBlob;
} // Public decode
} // Class Base64
;
/
The easiest way that I found, that works with special characters (in your case you don't have this problem), is using dbms_lob.converttoclob.
Create encapsulated Procedure:
CREATE OR REPLACE FUNCTION blob2clob(blob_i IN BLOB) RETURN CLOB IS
l_clob CLOB;
l_dest_offset NUMBER := 1;
l_src_offset NUMBER := 1;
l_amount INTEGER := dbms_lob.lobmaxsize;
l_clob_csid NUMBER := nls_charset_id('WE8ISO8859P15'); --dbms_lob.default_csid;
l_lang_context INTEGER := dbms_lob.default_lang_ctx;
l_warning INTEGER;
BEGIN
---------------------------
-- Create Temporary BLOB --
---------------------------
dbms_lob.createtemporary(lob_loc => l_clob,
cache => TRUE);
--------------------------
-- Convert CLOB to BLOB --
--------------------------
dbms_lob.converttoclob(dest_lob => l_clob,
src_blob => blob_i,
amount => l_amount,
dest_offset => l_dest_offset,
src_offset => l_src_offset,
blob_csid => l_clob_csid,
lang_context => l_lang_context,
warning => l_warning);
--
RETURN l_clob;
END blob2clob;
Then you can use:
blob2clob(utl_encode.base64_encode(image))

Encrypt (& decrypt) a number column in Oracle

How to do for encrypting a number
column in Oracle 11 (and also be able to decrypt them back) so that the same column stores crypted numbers along with (unencrypted ones (based on a boolean saved elsewhere)?
I actually did a function like this that takes a number to produce a crypted number and it worked fine in Oracle 10 but now it doesn't work anymore in ORACLE 11:
function crypt (key varchar2, n number) return number
raw_input RAW(128);
encrypted_raw RAW(2048);
raw_key_ RAW(128) := UTL_RAW.CAST_TO_RAW(CONVERT(key,'AL32UTF8','US7ASCII'));
begin
raw_input_ := UTL_RAW.cast_from_number (n);
encrypted_raw := dbms_crypto.Encrypt(src => raw_input_, typ =>DBMS_CRYPTO.DES3_CBC_PKCS5, KEY=>raw_key_);
return UTL_RAW.cast_to_number(encrypted_raw);
end;
it throws this error with no explanations:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "SYS.UTL_RAW", line 388
...
Thank you
Looks like you're trying to cast the encrypted raw to a number. If I understand what you want this function to do, it seems you want to test that the input number = returned number (that you can encrypt and decrypt successfully). If you wanted to just encrypt, you would return a raw, not a number.
Anyway, you should be casting the decrypted raw value to a number to test that the input number = returned number. Something like:
create or replace function test_crypt(k varchar2, n number)
return number as
raw_input_ RAW(128);
encrypted_raw RAW(2000);
decrypted_raw RAW (2000);
raw_key_ RAW(128) := UTL_RAW.CAST_TO_RAW(k);
begin
raw_input_ := UTL_RAW.cast_from_number (n);
encrypted_raw := dbms_crypto.Encrypt(src => raw_input_, typ =>DBMS_CRYPTO.DES3_CBC_PKCS5, KEY=>raw_key_);
--return UTL_RAW.cast_to_number(encrypted_raw);
-- use dbms_crypto to decrypt and return (hopefully same) number
decrypted_raw := DBMS_CRYPTO.DECRYPT
(
src => encrypted_raw,
typ => DBMS_CRYPTO.DES3_CBC_PKCS5,
key => raw_key_
);
return UTL_RAW.cast_to_number(decrypted_raw);
end;
On my system anyway, the input number = returned number (key is from dbms_crypto.randombytes(32) ). For example:
select test_crypt('50610FB89D98C7D906CB0A9917413221E4FE6FA62A9604302EE2C8F63E6BAD91', 234.21) from dual;
Output:
234.21

Encrypt/Decrypt Password in Oracle Function

Due to previously poorly designed structure, the current database that I have to work with stores users' password as text.
Now, I am building a front end part that has to use those passwords and I certainly don't want to be sending passwords unencrypted.
My idea is to write an Oracle function to encrypt and decrypt text password and use those functions in the stored procedures that will return encrypted data.
What would be the best approach in Oracle to do so?
If you want to write your own functions to encrypt and decrypt data, you would simply want to call the DBMS_CRYPTO encrypt and decrypt methods with appropriate parameters (i.e. pick your encryption algorithm, your key, etc.).
Of course, if you write your own routines, assuming that you store the key in the database or somewhere the database has access to, you're not doing much for security. It's bad to send passwords unencrypted over the network but it is generally much worse to store unencrypted passwords in the database (or encrypted passwords if there is a decrypt method in the database that has access to the key to decrypt the data). It's generally a lot easier to steal data from a database than it is to sniff data getting sent over the network in order to find a password.
The right answer, of course, would be to rearchitect the system so that you don't store the passwords at all. You should be storing password hashes (which you can also generate using the DBMS_CRYPTO package) which are non-reversible.
Take a look at DBMS_CRYPTO
It has methods to encrypt and decrypt data built in. Better than writing your own.
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_crypto.htm
Or you could use the password hashing algorithm pbkdf2 like this http://mikepargeter.wordpress.com/2012/11/26/pbkdf2-in-oracle/
I verified the outcome with the rfc https://www.ietf.org/rfc/rfc6070.txt and it works fine.
Check this link for minimal iterations and key_size: PBKDF2 recommended key size?
Note that the result is double the length, because it is hex-encoded.
we store these columns in the db
PASSWORD_HASH VARCHAR2(512 BYTE),
PASSWORD_SALT VARCHAR2(256 BYTE),
PASSWORD_ITERATIONS NUMBER(10),
PASSWORD_HASH_METHOD VARCHAR2(30 BYTE),
PASSWORD_CHANGED_DT DATE
the hash, salt and iterations are to feed the pbkdf2 algorithm
the hash_method is for migration purposes
and the changed_dt is to expire passwords
Here's a packaged function (successful implementation) for encrypting passwords using (DBMS_CRYPTO)-
CREATE OR REPLACE
PACKAGE BODY encrypt_paswd
AS
G_CHARACTER_SET VARCHAR2(10) := 'AL32UTF8';
G_STRING VARCHAR2(32) := '12345678901234567890123456789012';
G_KEY RAW(250) := utl_i18n.string_to_raw
( data => G_STRING,
dst_charset => G_CHARACTER_SET );
G_ENCRYPTION_TYPE PLS_INTEGER := dbms_crypto.encrypt_aes256
+ dbms_crypto.chain_cbc
+ dbms_crypto.pad_pkcs5;
------------------------------------------------------------------------
--Encrypt a password
--Salt the password
------------------------------------------------------------------------
FUNCTION encrypt_val( p_val IN VARCHAR2 ) RETURN RAW
IS
l_val RAW(32) := UTL_I18N.STRING_TO_RAW( p_val, G_CHARACTER_SET );
l_encrypted RAW(32);
BEGIN
l_val := utl_i18n.string_to_raw
( data => p_val,
dst_charset => G_CHARACTER_SET );
l_encrypted := dbms_crypto.encrypt
( src => l_val,
typ => G_ENCRYPTION_TYPE,
key => G_KEY );
RETURN l_encrypted;
END encrypt_val;
END encrypt_paswd;
This uses encrypt_aes256 -"Advanced Encryption Standard. Block cipher. Uses 256-bit key size." , chain_cbc- "Cipher Block Chaining. Plaintext is XORed with the previous ciphertext block before it is encrypted." and pad_pkcs5 - "Provides padding which complies with the PKCS #5: Password-Based Cryptography Standard".
In addition to this You can create a similar function to decrypt. like -
FUNCTION decrypt_val( p_val IN RAW ) RETURN VARCHAR2
IS
l_decrypted RAW(32);
l_decrypted_string VARCHAR2(32);
l_user VARCHAR2(32);
BEGIN
SELECT user
INTO l_user
FROM dual;
if l_user = 'ADMIN' -- you can restrict usage of decrypt to certain db users only.
then
l_decrypted := dbms_crypto.decrypt
( src => p_val,
typ => G_ENCRYPTION_TYPE,
key => G_KEY );
l_decrypted_string := utl_i18n.raw_to_char
( data => l_decrypted,
src_charset => G_CHARACTER_SET );
RETURN l_decrypted_string;
else
RAISE_APPLICATION_ERROR(-20101, 'You are not authorized to use this function - decrypt_val()');
end if;
RETURN 'Unknown';
END decrypt_val;
You may also consider wrapping the package before compiling it in the database using wrap iname=package_name.pkb and then compiling the resulting plb.
user this code definitely work
create or replace PACKAGE "PKG_LOGI_PWD_REG"
AS
function ENCRYPT_VAL( P_VAL in varchar2 ) return varchar2;
function DECRYPT_VAL( P_VAL in raw ) return varchar2;
end;
/
create or replace PACKAGE BODY "PKG_LOGI_PWD_REG"
as
FUNCTION decrypt_val( p_val IN RAW ) RETURN VARCHAR2
IS
l_decrypted RAW(32);
l_decrypted_string VARCHAR2(32);
L_USER varchar2(32);
L_CHARACTER_SET varchar2(10);
L_STRING varchar2(32);
L_KEY raw(250);
L_ENCRYPTION_TYPE PLS_INTEGER;
BEGIN
L_KEY := UTL_I18N.STRING_TO_RAW
( data => '98345678901234567890123456789012',
DST_CHARSET => 'AL32UTF8' );
L_ENCRYPTION_TYPE := dbms_crypto.encrypt_aes256
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
l_decrypted := dbms_crypto.decrypt
( SRC => P_VAL,
TYP => L_ENCRYPTION_TYPE,
key => L_KEY );
l_decrypted_string := utl_i18n.raw_to_char
( data => l_decrypted ,
src_charset => 'AL32UTF8' );
RETURN l_decrypted_string;
end DECRYPT_VAL;
FUNCTION encrypt_val( p_val IN VARCHAR2 ) RETURN VARCHAR2
is
L_VAL RAW(32);
L_ENCRYPTED raw(32);
L_CHARACTER_SET varchar2(10);
L_STRING varchar2(32);
L_KEY RAW(250);
L_ENCRYPTION_TYPE PLS_INTEGER;
begin
L_KEY := UTL_I18N.STRING_TO_RAW
( data => '98345678901234567890123456789012',
DST_CHARSET => 'AL32UTF8' );
L_ENCRYPTION_TYPE := dbms_crypto.encrypt_aes256
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
L_VAL := utl_i18n.string_to_raw
( data => p_val,
dst_charset => 'AL32UTF8' );
L_ENCRYPTED := dbms_crypto.encrypt
( SRC => L_VAL,
TYP => L_ENCRYPTION_TYPE,
key => L_KEY );
return L_ENCRYPTED;
EXCEPTION when OTHERS then
RETURN SQLCODE||'-'||SQLERRM;
end ENCRYPT_VAL;
end PKG_LOGI_PWD_REG;
/

Resources