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;
/
Related
I am editing some Oracle code that includes DBMS_Obfuscation_Toolkit references. I read that the DBMS_Obfuscation_Toolkit package is de-supported as of Oracle 10.2, and that I should upgrade my code to instead be use DMBS_Crypto.
I have this code...
dbms_obfuscation_toolkit.DES3Encrypt(
input => UTL_I18N.STRING_TO_RAW(v_input, 'AL32UTF8'),
key => UTL_I18N.STRING_TO_RAW(v_key, 'AL32UTF8'),
encrypted_data => v_temp_raw
);
--039053190040155118183231113102022222017082162099111241054160152245207112101203096142122226097245
v_temp := UTL_RAW.CAST_TO_VARCHAR2(v_temp_raw);
...which expects length v_input to be evenly-divisible by 8, and yields a 96 character result ("039053...").
The DBMS_Obfuscation_Toolkit documentation says that "Oracle's implementation of 3DES" defaults to the 2-key implementation, "in outer cipher-block-chaining (CBC) mode". But when I attempt to write a DBMS_Crypto.encrypt() equivalent...
--050127133161074179059208056044163133102098061207107114089045105193049199029095204025170130139068
v_temp := UTL_RAW.CAST_TO_VARCHAR2(
DBMS_Crypto.encrypt(
src => UTL_I18N.STRING_TO_RAW(v_input, 'AL32UTF8'), -- Cleartext
typ => DBMS_Crypto.ENCRYPT_3DES_2key + DBMS_Crypto.CHAIN_CBC + DBMS_Crypto.PAD_NONE,
key => UTL_I18N.STRING_TO_RAW(v_key, 'AL32UTF8') -- Key
)
);
...I get back a different 96 character result ("050127...").
For the purposes of above, v_input ('Trees sway into 25MPH winds! ') and v_key ('STACKOVERFLOW123456PSRV235KGNKNVEFHEF3404757543MNVOVCNALADNC6579') are the same.
To get the same result with DBMS_Crypto.encrypt(), what parameters should I be passing? What is the DBMS_Crypto.encrypt() equivalent of DBMS_Obfuscation_Toolkit.DES3Encrypt()?
You need to supply a matching initialization vector (IV). If there was no original IV, then use DBMS_CRYPTO.LEGACY_DEFAULT_IV = 0123456789ABCDEF:
declare
v_input char(32) :=
'Trees sway into 25MPH winds! ';
v_temp_raw raw(32);
v_key varchar2(64) :=
'STACKOVERFLOW123456PSRV235KGNKNVEFHEF3404757543MNVOVCNALADNC6579';
begin
sys.dbms_obfuscation_toolkit.DES3Encrypt(
input => UTL_I18N.STRING_TO_RAW ( v_input, 'AL32UTF8' ),
key => UTL_I18N.STRING_TO_RAW ( v_key, 'AL32UTF8' ),
encrypted_data => v_temp_raw
);
dbms_output.put_line ( v_temp_raw );
v_temp_raw := sys.DBMS_Crypto.encrypt (
src => UTL_I18N.STRING_TO_RAW ( v_input , 'AL32UTF8' ),
typ => DBMS_Crypto.ENCRYPT_3DES_2key + DBMS_Crypto.CHAIN_CBC + DBMS_Crypto.PAD_NONE,
key => UTL_I18N.STRING_TO_RAW ( v_key , 'AL32UTF8' ),
iv => hextoraw ( '0123456789ABCDEF' )
);
dbms_output.put_line ( v_temp_raw );
end;
/
2735BE289B76B7E7716616DE1152A2636FF136A098F5CF7065CB608E7AE261F5
2735BE289B76B7E7716616DE1152A2636FF136A098F5CF7065CB608E7AE261F5
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.
I created a Concurrent Program that creates an Excel File from a long, parametrized query using PL/SQL.
Once the Program successfully completes, the file is placed in the remote server's directory and is usually around 4 MB in Size.
I'm thinking of an approach to notify the requestor and enable him/her to save the file to their local directory.
However, I cannot use UTL_MAIL to attach and send the file via email due to the 32 Kilobyte Limitation. (Does UTL_MAIL have an attachment limit of 32k).
In the same post, Tom Kyte preferred approach would be to:
store the attachment to the database.
email a very small email with a link. the link points to my database - using a URL.
With that, i was thinking taking the same approach and use the block below to notify the requestor and enable him/her to download the said Excel file:
declare
l_url_link varchar2(100); -- how can i get the URL of the File?
BEGIN
UTL_MAIL.SEND(sender => 'xxx#oracle.com'
, recipients => 'Migs.Isip.23#Gmail.com'
, subject => 'Testmail'
, message => 'Your File is Ready to be downloaded, click the link here: '||l_url_link);
END;
My Questions would be:
How can i generate the "URL" of the Remote file using PL/SQL?
Do the users need to be granted access to the remote server to download the file?
Thank you!
Oracle Database Version:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
"CORE 11.2.0.4.0 Production"
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
Here is a pl/sql function I wrote to retrieve the URL of either the concurrent log file or output file. If you write your Excel file to the concurrent output, this should work fine. Let me know how you get on. I have not checked to see if this will give the correct mime-type or extension - not sure how EBS handles this but the function itself will definitely compile as is for 12.1.3.
Spec
FUNCTION get_concurrent_url (p_file_type IN VARCHAR2
,p_request_id IN NUMBER
,p_expiry IN NUMBER)
RETURN VARCHAR2;
Body
/* Get a URL to view the log/output
File Type is LOG or OUT
Request ID is the concurrent request ID
Expiry is in minutes */
FUNCTION get_concurrent_url (p_file_type IN VARCHAR2
,p_request_id IN NUMBER
,p_expiry IN NUMBER)
RETURN VARCHAR2
IS
CURSOR c_gwyuid
IS
SELECT profile_option_value
FROM fnd_profile_options FPO
,fnd_profile_option_values FPOV
WHERE FPO.profile_option_name = 'GWYUID'
AND FPO.application_id = FPOV.application_id
AND FPO.profile_option_id = FPOV.profile_option_id;
CURSOR c_two_task
IS
SELECT profile_option_value
FROM fnd_profile_options FPO
,fnd_profile_option_values FPOV
WHERE FPO.profile_option_name = 'TWO_TASK'
AND FPO.application_id = FPOV.application_id
AND FPO.profile_option_id = FPOV.profile_option_id;
l_request_id NUMBER;
l_file_type VARCHAR2 (3 BYTE);
l_expiry NUMBER;
l_two_task VARCHAR2 (100 BYTE);
l_gwyuid VARCHAR2 (100 BYTE);
l_url VARCHAR2 (1024 BYTE);
BEGIN
l_request_id := p_request_id;
l_file_type := p_file_type;
l_expiry := p_expiry;
FOR i IN c_gwyuid LOOP
l_gwyuid := i.profile_option_value;
END LOOP;
FOR i IN c_two_task LOOP
l_two_task := i.profile_option_value;
END LOOP;
IF l_file_type = 'LOG' THEN
l_url := fnd_webfile.get_url
(file_type => fnd_webfile.request_log
,id => l_request_id
,gwyuid => l_gwyuid
,two_task => l_two_task
,expire_time => l_expiry);
ELSE
l_url := fnd_webfile.get_url
(file_type => fnd_webfile.request_out
,id => l_request_id
,gwyuid => l_gwyuid
,two_task => l_two_task
,expire_time => l_expiry);
END IF;
RETURN l_url;
END get_concurrent_url;
I was able to find a solution for this using a (slightly different) method using the FND_GFM File Uploader Package in Oracle EBS.
FND_GFM is a package usually used in Oracle EBS when uploading files from the front-end application pages.
First, generate the Excel file (xlsx) using the code from the previous post: Create an Excel File (.xlsx) using PL/SQL,
Then the file is inserted into FND_LOBS and removed the from the OS (for good housekeeping), and finally sent as an email using UTL_FILE:
procedure generate_and_send_excel
is
l_content varchar2(250);
l_file_url varchar2(4000);
l_directory varchar2(250);
l_filename varchar2(250);
l_message clob;
l_instance varchar2(100);
l_ebs_url varchar2(100);
begin
/* your excel generation code here */
l_content := 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
l_directory := 'EXT_TAB_DATA';
l_filename := 'report.xlsx';
select instance_name
into l_instance
from v$instance;
select home_url
into l_ebs_url
from icx_parameters;
IMPORT_TO_LOB (p_file_name => l_filename -- this is the actual filename of the saved OS File
, p_directory => l_directory -- should be a defined directory in the Database
, p_content_type => l_content -- standard for Excel Files
, p_program_name => 'your prog here'
, p_program_tag => 'your prog here'
, p_file_url => l_file_url); -- this will be the generated URL of your File
utl_file.fremove(l_directory, l_filename);
l_message := l_message||'<h2 style="color: #5e9ca0;">'||l_title||'</h2>';
l_message := l_message||'<h3 style="color: #2e6c80;">Report is Ready for Download: '||l_filename||'</h3>';
l_message := l_message||'<p>File was generated on '|| sysdate ||' from '||l_instance||'</p>';
l_message := l_message||'<strong>Regards,</strong><br/><strong>Sample Team</strong>';
l_message := l_message||'<br/>Sample#sample.com';
UTL_MAIL.SEND(sender => 'SAMPLE#SAMPLE.com'
, recipients => 'Migs.Isip.23#gmail.com'
, subject => 'Hello message'
, message => l_message
, mime_type => 'text/html; charset=us-ascii');
end generate_and_send_excel;
Procedure below to insert into FND_LOBS (there's no available seeded API):
Procedure IMPORT_TO_LOB (p_file_name IN FND_LOBS.FILE_NAME%TYPE
, p_directory IN dba_directories.directory_name%type
, p_content_type IN FND_LOBS.file_content_type%type
, p_program_name IN FND_LOBS.program_name%type
, p_program_tag IN FND_LOBS.program_tag%type
, p_language IN FND_LOBS.language%type default 'US'
, p_file_format IN FND_LOBS.file_format%type default 'binary'
, p_file_url OUT varchar2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
lBlob BLOB;
lFile BFILE := BFILENAME(p_directory, p_file_name);
L_ORA_CHARSET VARCHAR2(100);
P_COUNT NUMBER;
BEGIN
SELECT value
into l_ora_charset
FROM nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
insert into FND_LOBS
(
file_id
, file_name
, file_content_type
, file_data
, upload_date
, expiration_date
, program_name
, program_tag
, LANGUAGE
, oracle_charset
, file_format
)
values
(
fnd_lobs_s.NEXTVAL -- FILE_ID
, p_file_name -- FILE_NAME
, p_content_type -- FILE_CONTENT_TYPE
, EMPTY_BLOB() -- FILE_DATA
, sysdate -- UPLOAD_DATE
, NULL -- EXPIRATION_DATE
, p_program_name -- PROGRAM_NAME
, p_program_tag -- PROGRAM_TAG
, p_language -- LANGUAGE
, l_ora_charset -- ORACLE_CHARSET
, p_file_format -- FILE_FORMAT
)
RETURNING file_data INTO lBlob;
DBMS_LOB.OPEN(lFile, DBMS_LOB.LOB_READONLY);
DBMS_LOB.OPEN(lBlob, DBMS_LOB.LOB_READWRITE);
DBMS_LOB.LOADFROMFILE(DEST_LOB => lBlob,
SRC_LOB => lFile,
AMOUNT => DBMS_LOB.GETLENGTH(lFile));
DBMS_LOB.CLOSE(lFile);
DBMS_LOB.CLOSE(lBlob);
commit;
p_file_url := fnd_gfm.construct_download_url (fnd_web_config.gfm_agent, fnd_lobs_s.currval);
END IMPORT_TO_LOB;
Note that this is an AUTONOMOUS_TRANSACTION so it needs to be committed before returning to the calling package/block.
Hope that Helps!
I am being given a large encrypted file containing 10 million rows of data.
I need to load this into an oracle database (in it's encrypted form) and then decrypt it in the database using pl/sql and the oracle built-in dbms_crypto.
I then need to process the unencrypted LOB to seperate out the 10 Million rows.
I will have the public key for the file. The file will be about 5GB in size.
Is this possible using just pl/sql? (and the oracle built-ins)
Has anyone had any experience of doing this sort of thing? - any pointers will be most welcome.
Thanks
this works for me.
SYS has to:
GRANT EXECUTE ON DBMS_CRYPTO TO <user>
in user :
CREATE OR REPLACE DIRECTORY
CRYPTDIR AS
'<crypted files directory>';
CREATE TABLE TESTCRYPT (ID INTEGER, E BLOB, D BLOB);
CREATE OR REPLACE FUNCTION load_Blob_FromFile(p_file_name VARCHAR2)
RETURN BLOB
AS
dest_loc BLOB := empty_blob();
src_loc BFILE := BFILENAME('CRYPTDIR', p_file_name);
BEGIN
-- Open source binary file from OS
DBMS_LOB.OPEN(src_loc, DBMS_LOB.LOB_READONLY);
-- Create temporary LOB object
DBMS_LOB.CREATETEMPORARY(
lob_loc => dest_loc
, cache => true
, dur => dbms_lob.session
);
-- Open temporary lob
DBMS_LOB.OPEN(dest_loc, DBMS_LOB.LOB_READWRITE);
-- Load binary file into temporary LOB
DBMS_LOB.LOADFROMFILE(
dest_lob => dest_loc
, src_lob => src_loc
, amount => DBMS_LOB.getLength(src_loc));
-- Close lob objects
DBMS_LOB.CLOSE(dest_loc);
DBMS_LOB.CLOSE(src_loc);
-- Return temporary LOB object
RETURN dest_loc;
END;
/
INSERT INTO TESTCRYPT
(ID, E)
SELECT 1, LOAD_BLOB_FROMFILE('EncryptedFile') FROM DUAL;
CREATE OR REPLACE FUNCTION DCRYPT2(TO_DECRYPT IN BLOB) RETURN BLOB
IS
DECRYPTED BLOB;
v_key PLS_INTEGER :=
DBMS_CRYPTO.ENCRYPT_AES128 +
DBMS_CRYPTO.CHAIN_ECB +
DBMS_CRYPTO.PAD_PKCS5;
BEGIN
dbms_lob.createtemporary(DECRYPTED,true);
DBMS_CRYPTO.DECRYPT(DECRYPTED,
TO_DECRYPT,
v_key,
'<Hex-Key>'
);
RETURN DECRYPTED;
END;
UPDATE TESTCRYPT SET D = DCRYPT2(E) WHERE ID=1;
CREATE OR REPLACE FUNCTION PADIS_MASTER.blob2clob (p_in blob) RETURN clob IS
v_clob clob;
v_varchar VARCHAR2(32767);
v_start PLS_INTEGER := 1;
v_buffer PLS_INTEGER := 32767;
BEGIN
dbms_lob.createtemporary(v_clob, TRUE);
FOR i IN 1..CEIL(dbms_lob.getlength(p_in) / v_buffer)
LOOP
v_varchar := utl_raw.cast_to_varchar2(dbms_lob.SUBSTR(p_in, v_buffer, v_start));
dbms_lob.writeappend(v_clob, LENGTH(v_varchar), v_varchar);
v_start := v_start + v_buffer;
END LOOP;
RETURN v_clob;
END;
/
SELECT BLOB2CLOB(D) FROM TESTCRYPT WHERE ID = 1;
for example Oracle 11 compiles with this key: 'b1b7adc285e82db81ea17f7be706e4f7'
at last the encryption function:
CREATE OR REPLACE FUNCTION ECRYPT(TO_CRYPT IN BLOB) RETURN BLOB
IS
CRYPTED BLOB;
v_key PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_AES128
+ DBMS_CRYPTO.CHAIN_ECB
+ DBMS_CRYPTO.PAD_PKCS5;
BEGIN
dbms_lob.createtemporary(AUSGABE,true);
DBMS_CRYPTO.ENCRYPT(CRYPTED,
TO_CRYPT,
v_key,
'b1b7adc285e82db81ea17f7be706e4f7'
);
RETURN CRYPTED;
END;
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.