Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, LOUIS.

Asked: May 22, 2001 - 11:44 pm UTC

Last updated: July 27, 2009 - 8:35 pm UTC

Version: 8.1.7

Viewed 10K+ times! This question is

You Asked

Hi tom,

I am in the process of testing a web application. However
I am trying to use your example about DBMS_OBFUSCATION_TOOLKIT but
you used bind variables. So, I am running into a problem. I need to incrypt and most important descrypt the credit card field. So, I guess I need to use the DBMS_OBFUSCATION_TOOLKIT in a procedure or function. Can you help me please or tell me the best way to do this?? I will appreciate it so much, without a doubt I will take to you lunch when you are in new york....


Louis Lugo
DBA

and Tom said...

Here is the same example from
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:791026226790 <code>
written as procedures. Bind variables are simply replaced with formal parameters (thats the only change I've made)...

Here it is:


ops$tkyte@DEV816> variable x varchar2(25)

ops$tkyte@DEV816> exec :x := 'How Now Brown Cow';
PL/SQL procedure successfully completed.


X
--------------------------------
How Now Brown Cow

ops$tkyte@DEV816> create or replace procedure crypt( p_str in out varchar2 )
2 as
3 l_data varchar2(255);
4 begin
5 l_data := rpad( p_str, (trunc(length(p_str)/8)+1)*8, chr(0) );
6
7 dbms_obfuscation_toolkit.DESEncrypt
8 ( input_string => l_data,
9 key_string => 'MagicKey',
10 encrypted_string=> p_str );
11 end;
12 /
Procedure created.

ops$tkyte@DEV816> create or replace procedure decrypt( p_str in out varchar2 )
2 as
3 l_data varchar2(255);
4 begin
5 dbms_obfuscation_toolkit.DESDecrypt
6 ( input_string => p_str,
7 key_string => 'MagicKey',
8 decrypted_string=> l_data );
9
10 p_str := rtrim( l_data, chr(0) );
11 end;
12 /
Procedure created.

ops$tkyte@DEV816> set autoprint on
ops$tkyte@DEV816> exec crypt( :x )

PL/SQL procedure successfully completed.


X
--------------------------------
Rr=p]w]pSWq:]PtJ?T,

ops$tkyte@DEV816> exec decrypt( :x )

PL/SQL procedure successfully completed.


X
--------------------------------
How Now Brown Cow


follow up to comment one.

Well, I guess I would write a FUNCTION then. Something like this:

2 function crypt( p_str in varchar2 ) return varchar2
3 as
4 l_data varchar2(255);
5 begin
6 l_data := rpad( p_str, (trunc(length(p_str)/8)+1)*8, chr(0) );
7
8 dbms_obfuscation_toolkit.DESEncrypt
9 ( input_string => l_data,
10 key_string => 'MagicKey',
11 encrypted_string=> l_data );
12
13 return l_data;
14 end;
15 /

Function created.

scott@DEV816>
scott@DEV816> create or replace
2 function decrypt( p_str in varchar2 ) return varchar2
3 as
4 l_data varchar2(255);
5 begin
6 dbms_obfuscation_toolkit.DESDecrypt
7 ( input_string => p_str,
8 key_string => 'MagicKey',
9 decrypted_string=> l_data );
10
11 return rtrim( l_data, chr(0) );
12 end;
13 /
Function created.

scott@DEV816> column decrypt format a30
scott@DEV816> drop table t;

Table dropped.

scott@DEV816> create table t ( data varchar2(32) );
Table created.


scott@DEV816> insert into t values ( crypt( 'Hello World' ) );
1 row created.

scott@DEV816> select data, decrypt(data) decrypt from t;

DATA DECRYPT
-------------------------------- ------------------------------
7??-,?P I{CK??! Hello World

scott@DEV816>





Rating

  (27 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

"DBMS_OBFUSCATION_TOOLKIT", version 8.1.7

Louis Lugo, May 25, 2001 - 1:04 am UTC

Thanks tom for your prompt response. However, how am I going to use this example with let's say encrypting
a table field?

Excellent - how to hide the key though?

Doug Cowles, November 16, 2001 - 5:04 pm UTC

Very useful. How do we hide the key though. A bind variable will help with tkprof, but it will have to be defined in the code somewhere which will allow it to be seen in all_source. Other ideas?

Little modification required....

Kiran Shah, March 25, 2004 - 5:56 am UTC

Dear Tom,
The procedures for encrypting/decrypting are very helpful.
But as per my understanding it requires one little change.

The procedure for encrypting string contains following statement...

l_data := rpad( p_str, (trunc(length(p_str)/8)+1)*8, chr(0) );

The purpose of this statement is to make the length of input string to be in multiples of eight bytes.

BUT this will also add another eight chr(0) characters when the input string size is exactly eight or in multiplies of eight bytes...(And when the input size is eight or in multiples of eight bytes, we do not need to append any more characters...)

So following if condition is needed to make it perfect...

if mod(length(p_str),8) <> 0 then
l_data := rpad( p_str, (trunc(length(p_str)/8)+1)*8, chr(0) );
else
l_data := p_str;
end if;

Pl. tell me if I am wrong...

Thanks,
Kiran.


Tom Kyte
March 25, 2004 - 9:19 am UTC

(i didn't really care about 8bytes honestly, was going for shortest, easiest code)

use ceil() instead of trunc()+1

Titi Ala'ilima, June 22, 2004 - 6:16 pm UTC

All you need to do to get around the adding 8 extra bytes problem is to use ceil(length(p_str)/8)*8

Difference in oracle 8i and 91 in dbms_obfuscation_toolkit

Arvind, October 12, 2004 - 11:58 pm UTC

Dear Tom,

Hello,

I am developing a web application using vb.net. In development environment i have used Oracle 8i as backend and there encryption and decryption is working fine. But my implementation enviroment uses oracle 9i and there this package doesn't work there. it is giving some binary data after doing decryption. can you tell me is there any difference bewteen these two versions my code is


create or replace package c_encryption
IS
FUNCTION ENCRYPT_DATA(passwd VARCHAR2, str_key VARCHAR2) RETURN VARCHAR2;
FUNCTION DECRYPT_DATA(passwd VARCHAR2, str_key VARCHAR2) RETURN VARCHAR2;
END c_encryption;

create or replace package body c_encryption
IS
FUNCTION ENCRYPT_DATA(passwd VARCHAR2, str_key VARCHAR2) RETURN VARCHAR2 IS
v_text VARCHAR2(16);
v_enc VARCHAR2(2048);
v_key VARCHAR2(8);
BEGIN
v_text := RPAD( LTRIM(RTRIM(passwd)), (TRUNC(LENGTH(LTRIM(RTRIM(passwd)))/8)+1)*8, chr(0));
v_key := RPAD( LTRIM(RTRIM(str_key)),8,CHR(0));
SYS.DBMS_OBFUSCATION_TOOLKIT.DESENCRYPT(
input_string => v_text,
key_string => v_key,
encrypted_string=>v_enc);
RETURN v_enc;
END ENCRYPT_DATA;

FUNCTION DECRYPT_DATA(passwd VARCHAR2, str_key VARCHAR2) RETURN VARCHAR2 IS
v_text VARCHAR2(2048);
v_key VARCHAR2(8);
BEGIN
v_key := RPAD( str_key,8,CHR(0));
SYS.DBMS_OBFUSCATION_TOOLKIT.DESDECRYPT(
input_string => passwd,
key_string => v_key,
decrypted_string=> v_text);
RETURN RTRIM(v_text,chr(0));
END DECRYPT_DATA;
END c_encryption;


Regards
Arvind


Tom Kyte
October 13, 2004 - 8:15 am UTC

I should pull all of my examples that use varchar's

way way dangerous with character set conversion.


I would strongly encourage to you

a) convert the string to be encrypted to raw using utl_raw.cast_to_raw
b) use the RAW encryption routines
c) store the encrypted data in RAW
d) decrypte the RAW to RAW and use utl_raw.cast_to_varchar2 to convert back

voice of experience speaking -- using varchar2 with encrypted data is an accident waiting to happen.

(search for

DBMS_OBFUSCATION_TOOLKIT characterset

on this site for examples)


Or, is the problem you are having to do with decrypting 8i encrypted data using 9i? they fixed a "key ordering" problem between 8i and 9i:
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:791026226790#8473587738442 <code>


Securing password over LAN

Sanji, February 25, 2005 - 2:08 am UTC

Greetings Tom !!!

We are in the process of developing an application that requires a secured connection to the database(10g).
The passwords would be stored in the database in encrypted form using obfuscation toolkit.
The idea is to connect through a proxy user and get the encrypted password for the user, privileged to insert data into the table. This proxy user wouldn't have create session privileges and neither would have any other system/ object privileges.
What i intend to confirm is how do i get the password SECURED over LAN (client machine) from the database.
The encrypted password is to be decrypted by the proxy user using stored procs(obfuscation toolkit).
The layout is like

1> The database has a table with encrypted password of the user through obfuscation toolkit.
2> From the client machine the Proxy user connects to the database. The password for this user is to be hard coded.
3> The Proxy user cannot access any other schema or objects other than the table with encrypted password.
4> The Proxy user gets the decrypted password for the privileged user which has to do inserts for the application.
5> The Proxy user feeds this decrypted password to the application.

Is this decrypted password secure over the LAN and if not what is the way to maintain integrity of the password.

Can you suggest any other methodology if this doesn't sound efficient ?

Thanks and Regards
Sanji

Tom Kyte
February 25, 2005 - 5:01 pm UTC

<quote>
The passwords would be stored in the database in encrypted form using
obfuscation toolkit.
</quote>

thats not secure you know. store a hash, that is secure. You never NEED to decode the password. search for

storing passwords

on this site.


Not sure why you even have a password issue here at all. You seem to be missing the point of the proxy account.

Each user would have an account

They would supply their credentials to the middle tier.

The middle tier would be authenticated to the database using IT's own credentials "Y".

The middle tier would say "Hey, George just gave me password X" to the database and the database would verify that is correct.

The middle tier would then say "call this procedure to enable georges roles" (these would be secure application roles. only available IF george connects via the middle tier proxy account "Y". Meaning, George cannot have these privs in sqlplus)

You might click on "links I like" above and get the Knox book on security if you want to read a single book on all of the possibilities.

secured password

Sanji, February 28, 2005 - 3:07 am UTC

Tom, this application wouldn't be a part of 3 tier architecture. It'd be a 2 tier client server architecture.
From the review i understand that dbms_obfuscation_tookit is not "secure". Why would anyone use this toolkit then ?

I believe i misquoted the term "proxy user". It isn't a proxy user in literal terms. It'd be a restricted access to the database for the purpose of decoding the password and feeding it to the application. This is to avoid hard coding of passwords (privileged users passwords) in the application code.

Thanks and Regards
Sanji

Tom Kyte
February 28, 2005 - 7:44 am UTC

where did you get this idea that it is not "secure"?


I am merely stating that you need not store a password if you want to authenticate someone. You can (like oracle, unix, etc) store a digest, a one way HASH (using the md5 routine contained in that same packge for example). Then, when a user presents you their credentials, you digest it and verify the stored digest you have matches the digest you just produced.

That way, you need not worry about someone getting the passwords (all they would need is the key see).


Why do you need to decode the password?
And an account that can decrypt passwords is one of the most powerful accounts in the world isn't it?

secure passwords

Sanji, February 28, 2005 - 6:18 am UTC

Sorry tom for the obfuscation toolkit remark. It indeed is required at times. What do i do for the password hard coding issue in case of 2 tier architecture. This pertains to my earlier post.
Thanks
Sanji

Tom Kyte
February 28, 2005 - 7:58 am UTC

don't hardcode? why are you storing passwords? are you trying to build a "single sign on" (you can buy standard ones...)

managing password

Sanji, March 01, 2005 - 8:41 am UTC

Tom, i completely understand what you are suggesting, BUT i have a big doubt. I believe i'm missing a point here in explaining the scenario.
In a 2 tier architecture, from the client machine, the application provides a login screen, where the user enters the username and the password.
All i want to know is authentication of this username/ password.
In the application code, this username and password would be captured and this information would be passed onto the database. How is this password capturing taken care of, is my question.
The development is in dot net (which apparently i know of nothing). I assume that the application code would take care of masking the password field, BUT this field's value has to be passed to the database along with corresponding username, for authentication.
The application is executing at the client machine.

Thanks and Regards
Sanji

Tom Kyte
March 01, 2005 - 8:49 am UTC

<quote>
All i want to know is authentication of this username/ password.
</quote>

then all you need in the database is a very very safe digest, not the encrypted password.

You take the user input,
you digest the password (hash it)
you compare to what you have stored

(that is how Oracle does it for example, dba_users has a password column, it is one way hashed, you cannot reverse it. Safer than encryption, easier for you to implement, no nasty key management issues)



But, how do we get this to perform?

Shawn Brockway, April 12, 2005 - 3:40 pm UTC

I've reviewed a number of threads on your site that discuss DMBS_OBFUSCATION_TOOLKIT, but I've yet to see a thread that speaks to encrypting effeciently.  I know there will be a performance hit (there's no way around it), but how do we minimize it?

Consider:
create table my_object
 (owner varchar2(30),
  object_name varchar2(128),
  enc_object_name varchar2(128));

SQL> insert into my_object(owner, object_name) select owner, object_name from dba_objects;

87263 rows created.

Elapsed: 00:00:00.97

This action happens in about 1 second.  Now I add encryption.

create or replace trigger my_object_trg
  before insert on my_object
  for each row
begin
  :new.enc_object_name := encrypt(:new.object_name,'MAGICKEY');
end my_object_trg;
/

encrypt is defined as (This should look familar):

function encrypt(v_string varchar2, v_key varchar2)
    return varchar2 as
    l_data  varchar2(255);
    v_encrypted varchar2(255);
  begin
    l_data := rpad( v_string, (trunc(length(v_string)/8)+1)*8, chr(0) );
    dbms_obfuscation_toolkit.DESEncrypt
                    ( input_string => l_data,
                      key_string   => v_key,
                      encrypted_string=> v_encrypted );
    return v_encrypted;
  end encrypt;

insert into my_object(owner, object_name) select owner, object_name from dba_objects;

87264 rows created.
Elapsed: 00:00:10.06

OUCH!  1 second operation just became 10.  I ran things through dbms_profiler...
     RUNID UNIT_NUMBER UNIT_NAME                              TIME
---------- ----------- -------------------------------- ----------
         7           1 DBMS_PROFILER                         .0001
         7           2 <anonymous>                               0
         7           3 MY_OBJECT_TRG                         .4949
         7           4 
ENCRYPT                         1.3398
         7           5 DBMS_OBFUSCATION_TOOLKIT              .8643
         7           6 UTL_RAW                              2.0674
         7           7 <anonymous>                               0

I'll need to process millions of rows a day with each of these rows needing 1 or 2 columns encrypted before being stored in the database.  Where do I focus my attention in trying to get this to perform better?  Or, do I want to take a different approach? 

Tom Kyte
April 13, 2005 - 8:48 am UTC

it is a binary thing here, you either

a) encrypt
b) don't encrypt

it is a black box. Triggers will be a low performing approach as opposed to doing it directly.

do not put encrypted data into a varchar2, experience has shown that to be a horribly bad bad idea.

You must use RAW.

Trigger will be slow

Vinayak, April 13, 2005 - 1:42 pm UTC

As Tom said, trigger will be low performing.

just did a test with trigger and directly. 22% difference

vmahajan@ECADEV> truncate table vm1 ;

Table truncated.

Elapsed: 00:00:01.43
vmahajan@ECADEV> insert into vm1 select 1,encrypt(object_name,'MAGICKEY') from all_objects ;

14611 rows created.

Elapsed: 00:00:10.71
vmahajan@ECADEV> /

14611 rows created.

Elapsed: 00:00:10.59
vmahajan@ECADEV> /

14611 rows created.

Elapsed: 00:00:10.69
vmahajan@ECADEV> create or replace trigger my_trig
2 before insert on vm1
3 for each row
4 begin
5 :new.nm := encrypt(:new.nm,'MAGICKEY') ;
6 end my_trig;
7 /

Trigger created.

Elapsed: 00:00:00.09
vmahajan@ECADEV> insert into vm1 select 1,object_name from all_objects ;

14612 rows created.

Elapsed: 00:00:13.82
vmahajan@ECADEV> /

14612 rows created.

Elapsed: 00:00:13.80
vmahajan@ECADEV> /

14612 rows created.

Elapsed: 00:00:13.84

(Without encryption the same statement took 6.21 seconds)

Performance of DBMS_OBFUSCATION_TOOLKIT

Shawn Brockway, April 14, 2005 - 9:26 am UTC

Thanks for the feedback (Both Tom and Vinayak). In looking at how to trim seconds off of the process, I never even considered removing the trigger from the equation. Sometimes you just get so focused on how to make a solution work you forget to evaluate alternatives. I ran the same test as above with the trigger and observed insert times averaging 9.4 seconds. I removed the trigger and made a function call within the insert statement and observed times averaging 6.6 seconds. Definitely a nice step in the right direction.

Tom - I had noticed in another thread you commented on not using varchar2 and to use RAW instead. In my work while waiting for some feedback, I'd already converted to RAWs.

Again, thanks.

DBMS_OBFUSCATION_TOOLKIT

A reader, July 05, 2005 - 1:28 am UTC

I am implementing a program in Java which encrypts a text using DES Algorithm. This will be sent to the Oracle Database.
Can this be decrypted using DBMS_OBFUSCATION_TOOLKIT in Oracle to get the original text.Thanks for the same

Tom Kyte
July 05, 2005 - 7:31 am UTC

You'll have to test - I've never tried and the question of whether DES implemented by API "x" and API "y" need to yield the same thing or not is something I don't know.

DBMS_OBFUSCATION_TOOLKIT

Max Reid, August 12, 2005 - 10:36 am UTC

I think I now understand how it works. Here are my questions.

I have been asked to look into encrypting one of the tables which gets updated by a PowerBuilder 7 application. From what I gather, I will need to create a stored proc which will encrypt each column on that table and another stored proc to decrypt each column when the table is needed by the application. Is that correct or is there a way that the table can be encrypted but still used by the PB application?

Thanks

Max

Tom Kyte
August 13, 2005 - 8:56 am UTC

well, one needs to understand fully the goal you hope to achieve by encrypting this.

from whom are you trying to protect the data?

Encryption Credit Card (CC) Use Raw Datatype

Xiaohua Zheng, September 16, 2005 - 10:26 am UTC

Hi, Tom, My boss printed this thread and handed it to me to study the other day. He would like to do encryption using RAW after he read your comments in this thread.  I originally did use RAW but I had to switch to VARCHAR2 because of a snag I ran into.  Let me detail it below.

1) The names for encrypt/decrpt credit card are named sdp_e/sdp_d. These 2 function alone works fine;
2) The table(column) I need to encrypt is called online_user_test(ccard_num) and I define it as raw(64);
3) The encryption routine is implemented exists trigger;
4) The problem is only for american express CC (15 digits), when encryption is happened inside trigger, the outcome of decrption will have a extra leading '0'; (We really want to implemented this through trigger to minimize application code change and utilize currently exists triggers)
5) I belive it has something to do Orace implicit data type conversion when we use RAW datatype for ccard_num;

SQL> INSERT INTO ONLINE_USER_TEST(USER_iD, PASSWORD, CAND_SEQ,CCARD_NUM,CCARD_TYPE,LOCKED,ORDER_SEQ,
 LOGGED_IN)
  2  VALUES('6666669','WHATEVER','66666669','412345678910111','A','N',1,'N');
kstring 777A6A393938373670726320353433646F67343379883609

1 row created.

SQL> select sdp_d(ccard_num) from online_user_Test;

0412345678910111

*****remove sdp_e from trigger****
SQL> truncate table online_user_Test;

Table truncated.
SQL> INSERT INTO ONLINE_USER_TEST(USER_iD, PASSWORD, CAND_SEQ,CCARD_NUM,CCARD_TYPE,LOCKED,ORDER_SEQ,
 LOGGED_IN)
  2  VALUES('6666669','WHATEVER','66666669',sdp_e('412345678910111'),'A','N',1,'N');
kstring 777A6A393938373670726320353433646F67343379883609

1 row created.

SQL> select sdp_d(ccard_num) from online_user_Test;

412345678910111

Are there any alternatives?  How bad really is if we had to use VARCHAR2?  The encryption is only going to take place inside database and decryption will only take place in application server, not any individual client PCs, correct? Plus credit card number are just straight numbers, I just have to be careful picking the character for padding.  What you think?  



   
 

Tom Kyte
September 16, 2005 - 1:43 pm UTC

what type does sdp_d return here?

Xiaohua Zheng, September 16, 2005 - 4:05 pm UTC

Function SDP_D returns VARCHAR2.  It is simply return the OUT parameter from procedure (SDP_E) inside package (PKG_SDP) using DBMS_OBFUSCATION_TOOLKIT. 

SQL> DESC PKG_SDP
PROCEDURE SDP_D
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 ENCRYPTED_CARD_ID              RAW                     IN
 PLAIN_CARD_ID                  VARCHAR2                OUT
PROCEDURE SDP_E
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 PLAIN_CARD_ID                  VARCHAR2                IN
 ENCRYPTED_CARD_ID              RAW                     OUT

Thanks for your response.  I didn't think it will work.  I posted so my boss will be happy :-) 

Tom Kyte
September 16, 2005 - 4:15 pm UTC

well, the leading zero looks like a "raw to varchar2" conversion (hex code).

Can we see the "code"

Xiaohua Zheng, September 19, 2005 - 2:51 pm UTC

I am out of my office this week. I will post the code as soon as I return to office.

I agree it is the conversion of RAW to VARCHAR2 add the leading 0. But the problem is at not at the code, it is at the stage of insert (actually before insert takes place), Oracle converts CCARD_NUM (412345678910111) to (041234567810111) before encryption take place inside the trigger because of we define CCARD_NUM as raw(64). In another word, inside the trigger, it does sdp_e(0412345678910111) and store in CCARD_NUM, and natually, the result of descrypt(sdp_d) is '0412345678910111'. I don't know how code modification can get around of this problem. Thank you very much for your time.

Xiaohua Zheng, September 29, 2005 - 11:48 pm UTC

Hi, Tom, I am so convinced that the leading '0' was added outside of encryption/decryption codes, so I didn't bother to post the codes and waste your time. I had to define credit card number to VARCHAR2 data type instead of RAW since we want to implemente encryption through triggers. Everything works for now.

Also, I 'discovered' by mistake that I can take a 'mixed' approach. I can use RAW(hexcode) in DBMS_OBFUSCATION_TOOLKIT to encrypt/decrypt credit card number with credit card number column defined as VARCHAR2 in database. I know it sounds so wrong but actually work rather nicely. This 'mixed' approach avoids the leading zero with pure RAW and potential character set conversion problem caused by pure VARCHAR2 approach.

Thanks.


Mutli Byte Characterset and Obfuscation Toolkit

Devopam Mittra, October 18, 2005 - 12:15 am UTC

Hi Tom,
I went through the inputs in this thread as well as few others.
Definitely helpful in making a start.

Needed some inputs on the multi-byte character handling of the package.
As pointed out earlier in this post also, why is the encrypted value different for different character sets.
e.g I tried with AMERICAN_AMERICA.UTF8 and few other compatible charsets. The results were pretty surprising . Not only did the RAW value changed but the length of the string varied exceptionally high .

Could not understand the behavior properly .
Is it because of the charset , the input string is parsed differently by the encryption algo or something else.

Please let me know if you would require sample data to be put in here to substantiate the claim . ( I have not put samples, as I have a strong notion that you must have observed this earlier somewhere)
regards
Devopam



Tom Kyte
October 18, 2005 - 8:56 am UTC

I recommend only using the RAW inputs to this routine these days - too many issues mixing "strings" with "encrypted data (which by definition is binary)"

so, ignore the string routines, only use the raw routines and use utl_raw to convert between raw and string data

that way you'll see "consistent" output given the same inputs.

performance orf query or program

Pardeep Sharma, February 26, 2007 - 10:50 am UTC

Hi TOM,
I m pardeep.I need ur help.i want to know ,how to check the performance of any query or program.and how to use this tkprof tool.Can you explain me with some examples.

Tom Kyte
February 26, 2007 - 3:25 pm UTC

keep reading - there are literally thousands of examples on this site........

and the documentation on otn.oracle.com isn't horrible, check out

http://docs.oracle.com/docs/cd/B19306_01/server.102/b14211/toc.htm

Alexander the ok, February 20, 2008 - 10:31 am UTC

Tom,

Are there any cases when it's ok to store encrypted data in a varchar, or do you recommend always using RAW?
Tom Kyte
February 20, 2008 - 12:32 pm UTC

you would have to convert the encrypted binary data (encrypted data is binary) into HEX or maybe base64 encode it to make it safe to store in a string, then of course you have to convert back into raw in order to decrypt

Asheesh Dhupper, July 16, 2008 - 7:45 am UTC

Hi Tom,

Indeed a splendid and helpful explaination about the DBMS_OBFUSCATION_PACKAGE. But still I am not able to understand why the parameter 'KEY' in both DESEncrypt and DESDecrypt procedures is used.
Please Guide.
Awaiting for ur precious answer.
Tom Kyte
July 16, 2008 - 10:14 am UTC

"UR" is not available.


key is - well, *the key*, the key used to encrypt the data. without the key, you cannot decrypt it.

Asheesh Dhupper, July 16, 2008 - 7:49 am UTC

In continuation to the above, I have framed a Block:

Declare
v_data varchar2(255);--to make the string multiple of 8
v_result varchar2(50):='asheeshmaneesh';
v_random varchar2(50);
begin
v_data:=rpad(v_result,(trunc(length(v_result)/8)+1)*8,chr(0));

v_random:=dbms_random.value(0,35);

dbms_obfuscation_toolkit.DESEncrypt(input_string=>v_data,key_string=>v_random,encrypted_string=>v_result);

dbms_output.put_line('Encryption :'||v_result);

dbms_obfuscation_toolkit.DESdecrypt(input_string=>v_result,key_string=>v_random,decrypted_string=>v_data);

dbms_output.put_line('Decryption :'||v_data);
end;

Will it provide me a better security of Passwords stored in our user table if I implement this on User table.
Tom Kyte
July 16, 2008 - 10:15 am UTC

you never want to encrypt passwords, you hash them

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:95412348059

Asheesh Dhupper, July 17, 2008 - 1:43 am UTC

Hi Tom,
Thank you for the answer. Well, can you please tell me why there is a need to HASH passwords instead of Encrypting them. Does it provide a better security or is there any other reason. Also, suppose, if we use encryption, can't we use a random key generator instead of a static key.
Please Guide.
Tom Kyte
July 17, 2008 - 11:43 am UTC

better security.

if you encrypt, you need to manage the keys, how will you manage the keys? (random key generator - hmmmm, think about it - now you have to save this random key somewhere and protect it)


Think about this - do you

a) need to know their password to get into your system or
b) need to verify their supplied password is correct

you need (b)


when I sign up for a 'web service', and that web thingy has a "remind me of my password function", I do not trust that service at all - and am inclined to NOT use that service.

There is no reason at all - none - for you to save my password in a format that allows you to read it, you do not NEED to do that, it only opens you up to hacking. I have to trust that you are smart enough to protect the data - and not many people deserve that trust (if any)


If you hash it, you can accomplish (b) easily.

If you encrypt it, you have to describe in great detail how you will manage the keys, how you will protect my password in the event someone steals your database, among other things.


encrypting a password is wrong.

hashing it is right.


when user says "i forgot my password", you do not need to email it them (in fact, I would hate that - i do hate that when they email me in clear text my password, my password I probably use for something else). Instead, you would email them a one time use password that expires really soon and must be changed immediately upon receipt.


Asheesh Dhupper, July 22, 2008 - 1:28 am UTC

Thank u very much :)

DBMS_OBFUSCATION_TOOLKIT

SM, May 19, 2009 - 1:42 pm UTC

I am exporting data as text into file. There is a user requirement that the data needs to be encrypted. But they will not be using Oracle to decrypt data. Can the data encrypted by DBMS_OBFUSCATION_TOOLKIT be decrypted by software other than Oracle. If it can be done can you please point me to the documentation? If not, would you suggest that I encrypt the file as a whole (using some encryption software) instead of the data?
Thank you for your time.
SM
Tom Kyte
May 23, 2009 - 12:25 pm UTC

you cannot export encrypted data into a text file, encrypted data is ALWAYS binary.

In theory you could decrypt using some other language/API, but in practice, the encryption vector we use to initialize with is not documented.

You'll want to read the data out, encrypt it using some standard API with inputs you can provide to your user, place the output into a BINARY FORMATTED FILE (this file will contain 0A, 0D, ctl-Z, and many other control characters that cannot appear in a text file, it is a binary file - period)


Thanks for clearing things on DBMS_OBFUSCATION_TOOLKIT

Jaspreet Nagra, July 27, 2009 - 3:25 pm UTC

I have following 2 questions:
1. Do we have any method to find it out whether the values are in encrypted form or not?
Scenario: We have one button in our Admin site which have encrypt the values upon click. We need to make the button Active only when the values are not encrypted.
2. Why we should not use varchar2?
Tom Kyte
July 27, 2009 - 8:35 pm UTC

1) look for a raw column that is a multiple of 16 bytes - 16, 32, 48, etc.... That would be a hint.

If the developers put it into a varchar2 - they made a big mistake, encrypted data is RAW binary data.


In your scenario, you would obviously need to have two fields. One of the proper datatype to store the data in cleartext and one to store the encrypted data.

It sounds like you do not have that yet, but you will NEED IT, it is mandatory. You'll be moving the data from one column to the other.

2) because it is BINARY DATA, it is not stored in your characterset. If someone retrieves the data and puts it back - the odds are they will CHANGE IT if you store it in a varchar2 - due to character set translation.

Simple example:

database is US7ASCII (for example)
client is we8iso (8 bit)

client reads out binary data and it is converted from 7bit to 8bit (nothing happens)

client writes binary data back in and it is converted from 8bit to 7bit - ouch, that hurts, that high bit disappears! The data is corrupted and cannot ever be decrypted again.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library