Sie sind auf Seite 1von 10

Orcl as sysdba

Oracle Database 10g provides means to encrypt and decrypt your sensitive data using the
built-in API called DBMS_CRYPTO. Using DBMS_CRYPTO API one can encrypt sensitive
information like SSN, Credit Card Numbers, Debit Card Numbers, etc stored in the database
as these are not supposed to be stored in plain text for security reasons. The
DBMS_CRYPTO toolkit is easy to use and is intended to replace
DBMS_OBFUSCATION_TOOLKIT which was introduced in 8.1.6.
The concept behind any encryption toolkit is to have two things: 1) An algorithm, the actual
logic, and 2) The encryption key
Using these combination's we can safely encrypt our data.
In this blog entry, let us see how DBMS_CRYPTO can be used to encrypt data and also
consider its performance implications.
To start with, lets create a test table and insert couple of records in plain text:
view plaincopy to clipboardprint?

1.
2.

SQL> select * from v$version;

3.

BANNER

4.

----------------------------------------------------------------

5.

Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod

6.

PL/SQL Release 10.2.0.4.0 - Production

7.

CORE

8.

TNS for 32-bit Windows: Version 10.2.0.4.0 - Production

9.

NLSRTL Version 10.2.0.4.0 - Production

10.2.0.4.0

Production

10.
11. SQL>
12. SQL> create table emp(empid number, ename varchar2(100), ssn varchar2(80));
13.
14. Table created.
15.
16. SQL> insert into emp values (1, 'SMITH',

123456701);

17.
18. 1 row created.
19.
20. SQL> insert into emp values (2, 'ALLEN',
21.

123456702);

22. 1 row created.


23.
24. SQL> insert into emp values (3, 'WARD',

123456703);

25.
26. 1 row created.
27.
28. SQL> commit;
29. SQL> set line 10000
30. SQL> column ename format a30
31. SQL> column ssn format a40
32. SQL> select * from emp;
33.
34.

EMPID ENAME

SSN

35. ---------- ------------------------------ ------------36.

1 SMITH

123456701

37.

2 ALLEN

123456702

38.

3 WARD

123456703

39.
40. SQL>

The SSN has been inserted into the table in plain text and can be read by anybody having
SELECT privilege on EMP table. Now, lets create a package using DBMS_CRYPTO API to
handle encryption and decryption.
view plaincopy to clipboardprint?

1.
2.

SQL> Create or replace package cryptit is


2 Function encrypt_data( p_data IN VARCHAR2 ) Return RAW DETERMINISTIC;

3.

Function decrypt_data( p_data IN RAW ) Return VARCHAR2 DETERMINISTIC;

4.

4 End cryptit;

5.

5 /

6.
7.

Package created.

8.
9.

SQL>

10. SQL> Create or replace package body cryptit is

11.

V_Key

12.

13.

Function encrypt_data( p_data IN VARCHAR2 ) Return RAW DETERMINISTIC

14.

IS

15.

l_data RAW(2048) := utl_raw.cast_to_raw(p_data);

16.

l_encrypted RAW(2048);

17.

BEGIN

18.

NULL;

19. 10

RAW(128) := UTL_RAW.cast_to_raw('testkey1');

l_encrypted := dbms_crypto.encrypt

20. 11

-- Key

-- Algorithm

( src => l_data,

21. 12

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

22. 13

key => V_KEY );

23. 14
24. 15
25. 16

Return l_encrypted;
END encrypt_data;

26. 17
27. 18

Function decrypt_data( p_data IN RAW ) Return VARCHAR2 DETERMINISTIC

28. 19

IS

29. 20
30. 21

l_decrypted RAW(2048);
BEGIN

31. 22

l_decrypted := dbms_crypto.decrypt

32. 23

( src => p_data,

33. 24

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

34. 25

key => V_KEY );

35. 26
36. 27
37. 28

Return utl_raw.cast_to_varchar2(l_decrypted);
END decrypt_data;

38. 29 End cryptit;


39. 30 /
40.
41. Package body created.
42.

-- Algorithm

43. SQL>
44. <p></p>

The package body consists of functions to encrypt and decrypt data along with a key. As
these functions will always output the same value for a specific input, we can make them
Deterministic functions. (A Deterministic Function always returns the same result any time
they are called with a specific set of input values.)
Let's now make use of these functions to encrypt our sensitive data.
view plaincopy to clipboardprint?

1.
2.

SQL> update emp set ssn = cryptit.encrypt_data(ssn);

3.

3 rows updated.

4.
5.

SQL> select * from emp;

6.
7.
8.

EMPID ENAME

SSN

---------- ------------------------------ ----------------------------------

9.

1 SMITH

5F3168C22E54060DE7D97B31F7E38BB6

10.

2 ALLEN

5F3168C22E54060D0C2527FBBD3DCD6C

11.

3 WARD

5F3168C22E54060D8166D3757932A112

12.
13. SQL>
14. SQL>

When inserting new records we simply make use of "cryptit.encrypt_data" function in the
INSERT statement.
view plaincopy to clipboardprint?

1.
2.

SQL> insert into emp values( 4, 'MOMEN', cryptit.encrypt_data(123456704));

3.

1 row created.

4.
5.

SQL> commit;

6.
7.

Commit complete.

8.
9.

SQL> select * from emp;

10.
11.

EMPID ENAME

SSN

12. ---------- ------------------------------ ---------------------------------------13.

1 SMITH

5F3168C22E54060DE7D97B31F7E38BB6

14.

2 ALLEN

5F3168C22E54060D0C2527FBBD3DCD6C

15.

3 WARD

5F3168C22E54060D8166D3757932A112

16.

4 MOMEN

5F3168C22E54060D2CFF7E7A35B14187

17.
18. SQL>
19.
20. SQL> column decrypted_ssn format a15
21. SQL> select empid, ename, cryptit.decrypt_data(ssn) decrypted_ssn, ssn from emp;
22.
23.

EMPID ENAME

DECRYPTED_SSN SSN

24. ---------- ------------------------------ --------------- ---------------------------------------25.

1 SMITH

123456701

5F3168C22E54060DE7D97B31F7E38BB6

26.

2 ALLEN

123456702

5F3168C22E54060D0C2527FBBD3DCD6C

27.

3 WARD

123456703

5F3168C22E54060D8166D3757932A112

28.

4 MOMEN

123456704

5F3168C22E54060D2CFF7E7A35B14187

29.
30. SQL>

All is fine as far as encryption is concerned, but lets see what happens when SSN is used in
the WHERE clause of queries. We will create an index on SSN and run a query against it.
view plaincopy to clipboardprint?

1.
2.

SQL> create index t_ssn on emp(ssn);

3.

Index created.

4.
5.

SQL> set autotrace on exp

6.

SQL> select * from emp where ssn = cryptit.encrypt_data('123456701');

7.
8.
9.

EMPID ENAME

SSN

---------- ------------------------------ ----------------------------------------

10.

1 SMITH

5F3168C22E54060DE7D97B31F7E38BB6

11.
12.
13. Execution Plan
14. ---------------------------------------------------------15. Plan hash value: 2894032564
16.
17. ------------------------------------------------------------------------------------18. | Id | Operation

| Name | Rows | Bytes | Cost (%CPU)| Time

19. ------------------------------------------------------------------------------------20. | 0 | SELECT STATEMENT

1 | 107 |

21. | 1 | TABLE ACCESS BY INDEX ROWID| EMP |


22. |* 2 | INDEX RANGE SCAN

| T_SSN |

1|

2 (0)| 00:00:01 |

1 | 107 |
|

2 (0)| 00:00:01 |

1 (0)| 00:00:01 |

23. ------------------------------------------------------------------------------------24.
25. Predicate Information (identified by operation id):
26. --------------------------------------------------27.
28.

2 - access("SSN"=RAWTOHEX("CRYPTIT"."ENCRYPT_DATA"('123456701')))

29.
30. Note
31. ----32.

- dynamic sampling used for this statement

33.
34. SQL>

Well, the index "T_SSN" has been selected by the optimizer to be cost efficient. When a
range of values is to be scanned, optimizer falls flat on its face as it has no idea and picks
up FTS.
view plaincopy to clipboardprint?

1.

SQL> select * from emp where cryptit.decrypt_data(ssn) between '123456702' and '123456
704';

2.
3.

EMPID ENAME

SSN

4.

---------- ------------------------------ ----------------------------------------

5.

2 ALLEN

5F3168C22E54060D0C2527FBBD3DCD6C

6.

3 WARD

5F3168C22E54060D8166D3757932A112

7.

4 MOMEN

5F3168C22E54060D2CFF7E7A35B14187

8.
9.
10. Execution Plan
11. ---------------------------------------------------------12. Plan hash value: 3956160932
13.
14. -------------------------------------------------------------------------15. | Id | Operation

| Name | Rows | Bytes | Cost (%CPU)| Time

16. -------------------------------------------------------------------------17. | 0 | SELECT STATEMENT |

1 | 107 |

18. |* 1 | TABLE ACCESS FULL| EMP |

3 (0)| 00:00:01 |

1 | 107 |

3 (0)| 00:00:01 |

19. -------------------------------------------------------------------------20.
21. Predicate Information (identified by operation id):
22. --------------------------------------------------23.
24.

1 - filter("CRYPTIT"."DECRYPT_DATA"(HEXTORAW("SSN"))>='123456702'

25.

AND "CRYPTIT"."DECRYPT_DATA"(HEXTORAW("SSN"))<='123456704')

26.
27. Note
28. ----29.

- dynamic sampling used for this statement

We can also create Function Based Indexes on encrypted columns such that data is
accessed faster with a better execution plan. This is the reason I have marked both
ENCRYPT_DATA and DECRYPT_DATA as DETERMINISTIC functions.
view plaincopy to clipboardprint?

1.
2.

SQL> create index f_ssn_idx on emp(cryptit.decrypt_data(ssn));

3.

Index created.

4.
5.

SQL> select * from emp where cryptit.decrypt_data(ssn) between '123456702' and '123456
704';

6.
7.
8.

EMPID ENAME

SSN

---------- ------------------------------ ----------------------------------------

9.

2 ALLEN

5F3168C22E54060D0C2527FBBD3DCD6C

10.

3 WARD

5F3168C22E54060D8166D3757932A112

11.

4 MOMEN

5F3168C22E54060D2CFF7E7A35B14187

12.
13.
14. Execution Plan
15. ---------------------------------------------------------16. Plan hash value: 9274740
17.
18. ----------------------------------------------------------------------------------------19. | Id | Operation

| Name

| Rows | Bytes | Cost (%CPU)| Time

20. ----------------------------------------------------------------------------------------21. | 0 | SELECT STATEMENT

1 | 107 |

22. | 1 | TABLE ACCESS BY INDEX ROWID| EMP

23. |* 2 | INDEX RANGE SCAN

1|

| F_SSN_IDX |

2 (0)| 00:00:01 |

1 | 107 |
|

2 (0)| 00:00:01 |

1 (0)| 00:00:01 |

24. ----------------------------------------------------------------------------------------25.
26. Predicate Information (identified by operation id):
27. --------------------------------------------------28.
29.

2 - access("CRYPTIT"."DECRYPT_DATA"(HEXTORAW("SSN"))>='123456702' AND

30.

"CRYPTIT"."DECRYPT_DATA"(HEXTORAW("SSN"))<='123456704')

31.
32. Note
33. ----34.

- dynamic sampling used for this statement

35.
36. SQL>

The optimizer has rightly picked up the Function based index to access requested data
quickly.
DBMS_CRYPTO is a great way to encrypt sensitive data and we can also create indexes on
the encrypted columns to speedup our queries. Lastly, remember to wrap the CRYPTIT
package body so that the key is not exposed.
DBMS_CRYPTO can also be used to encrypted data recursively. Let us try to encrypt the
already encrypted SSN from the above example.
view plaincopy to clipboardprint?

1.
2.
3.
4.

SQL> select * from emp;


EMPID ENAME

SSN

---------- -------- --------------------------------------------------------------------------------

5.

1 SMITH

5F3168C22E54060DE7D97B31F7E38BB6

6.

2 ALLEN

5F3168C22E54060D0C2527FBBD3DCD6C

7.

3 WARD

5F3168C22E54060D8166D3757932A112

8.

4 MOMEN

5F3168C22E54060D2CFF7E7A35B14187

9.
10. SQL> update emp set ssn = cryptit.encrypt_data(ssn);
11.
12. 4 rows updated.
13.
14. SQL> select * from emp;
15.
16.

EMPID ENAME

SSN

17. ---------- -------- -------------------------------------------------------------------------------18.

1 SMITH 455E357D80B1C81F91D52088DA0FE03A0C133D129CFC3879EE7A8DE993FD
459DB5C9E1EBEF37062C

19.

2 ALLEN 455E357D80B1C81F91D52088DA0FE03A98FC410A71CE64D57935691692D43
3B770C5F8AF07C9113F

20.

3 WARD
455E357D80B1C81F91D52088DA0FE03A9D32D14FE64F41DD66BE7FEF4C31
384F032C16826EAA4830

21.

4 MOMEN 455E357D80B1C81F91D52088DA0FE03A04D5C0AD79E689EABD46F8EC335
308E32D6F7E94167F6EDF

22.

23. SQL> commit;


24.
25. Commit complete.
26.
27. SQL> select empid, ename, cryptit.decrypt_data(cryptit.decrypt_data(ssn)) decrypted_ssn, ss
n from emp;
28.
29.

EMPID ENAME

DECRYPTED_SSN SSN

30. ---------- -------- --------------- -------------------------------------------------------------------------------31.

1 SMITH 123456701
455E357D80B1C81F91D52088DA0FE03A0C133D129CFC3879
EE7A8DE993FD459DB5C9E1EBEF37062C

32.

2 ALLEN 123456702
455E357D80B1C81F91D52088DA0FE03A98FC410A71CE64D5
7935691692D433B770C5F8AF07C9113F

33.

3 WARD
123456703
455E357D80B1C81F91D52088DA0FE03A9D32D14FE64F41DD
66BE7FEF4C31384F032C16826EAA4830

34.

4 MOMEN 123456704
455E357D80B1C81F91D52088DA0FE03A04D5C0AD79E689E
ABD46F8EC335308E32D6F7E94167F6EDF

35.
36. SQL>

For information on DBMS_CRYPTO check Oracle documentation.


Posted by Asif Momen at 5:18 PM

Das könnte Ihnen auch gefallen