风起漂泊 发表于 2018-9-12 13:36:51

Oracle wrap 和 unwrap( 加密与解密) 说明

一. Wrap 说明
  官网的说明如下:
  A PL/SQL Source Text Wrapping
  http://download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/wrap.htm#LNPLS1744
  You can wrap the PL/SQL source text for any of these stored PL/SQL units, thereby preventing anyone from displaying or editing that text:
  (1)Package specification
  (2)Package body
  (3)Type specification
  (4)Type body
  (5)Function
  (6)Procedure
  A file containing wrapped PL/SQL source text is called a wrapped file. Awrapped file can be moved, backed up, or processed by SQL*Plus or the Importand Export utilities.
  To produce a wrapped file, use either the PL/SQL Wrapper utility or a DBMS_DDL subprogram.The PL/SQL Wrapper utility wraps the source text of every wrappable PL/SQL unitcreated by a specified SQL file. The DBMS_DDL subprograms wrap thesource text of single dynamically generated wrappable PL/SQL units.
  Both the PL/SQL Wrapper utility and DBMS_DDL subprograms detecttokenization errors (for example, runaway strings), but not syntax or semanticerrors (for example, nonexistent tables or views).

  Wrapped files are upward-compatible between Oracle Database>  itpub上有篇文章提到了wrap 加密的原理:
  From:http://space.itpub.net/12932950/viewspace-619808
  Oracle加密的原理就是先对源码进行lz压缩lzstr,然后对压缩数据进行SHA-1运算得到40位的加密串shstr,然后将加密串与压缩串拼接得到shstr+lzstr,然后对拼接后的字符串进行Oracle双字符转换(转换表)。最后将转换后的字符串进行base64编码,最终得到wrap的加密串。
  The default file extension for input_file is sql. The default nameof output_file is input_file.plb. Therefore, these commands are equivalent:
  wrapiname=/mydir/myfile
  wrapiname=/mydir/myfile.sql oname=/mydir/myfile.plb
  Thisexample specifies a different file extension for input_file and adifferent name for output_file:
  wrapiname=/mydir/myfile.src oname=/yourdir/yourfile.out
  wrap 的使用步骤如下:
  (1)将我们要加密的sql 语句保存到一个sql文本里。
  (2)用wrap 进行处理,指定输入的sql,即我们第一步的问题,然后指定输出的路径和文件名,默认扩展名是plb。
  (3)执行我们第二部进过wrap 处理的sql,即plb文件,创建我们的对象.
示例1:wrap funcation
  --函数
  CREATE OR REPLACE FUNCTION F_DAVE (
  n int
  ) RETURN string
  IS
  BEGIN
  IF n = 1 THEN
  RETURN 'Dave is DBA!';
  ELSIF n = 2 THEN
  RETURN 'Dave come from AnQing!';
  ELSE
  RETURN 'Dave come from HuaiNing!';
  END IF;
  END;
  /
  SYS@dave2(db2)> select F_DAVE(4) fromdual;
  F_DAVE(4)
  --------------------------------------------------------------------------------
  Dave come from HuaiNing!
  BTW: 今天群里有人问我的blog的例子里为啥有安庆,因为我是安庆怀宁人。
  $ pwd
  /home/oracle
  $ cat dave.sql
  CREATE OR REPLACE FUNCTION F_DAVE (
  n int
  ) RETURNstring
  IS
  BEGIN
  IF n = 1 THEN
  RETURN 'Dave is DBA!';
  ELSIF n = 2 THEN
  RETURN 'Dave come from AnQing!';
  ELSE
  RETURN 'Dave come from HuaiNing!';
  END IF;
  END;
  /
  $ wrap iname=dave.sql

  PL/SQL Wrapper:>  Copyright (c) 1993, 2004, Oracle.All rights reserved.
  Processing dave.sql to dave.plb
  $ ls
  bifile.bbd dave.plbdave.sqlDesktop log.bbd
  $ cat dave.plb
  CREATE OR REPLACE FUNCTION F_DAVE wrapped
  a000000
  1
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  8
  10d e7
  S9NWrpt8q6tkKEMxCcfYJz2aLF4wgxDQLZ4VfC9AkE6OnV4ydypXGhveHcDg8UXy98WIg6xR
  crtc/BRdQJjutbna/9+g0LlaSx87/znV+y926S1AeC0IRi/tjPJTyvJereDdk8mftMo8QMjV
  fw0xXn0zVagAawwNVhSAiy/JPTMKkrBkC5ruMwQSTe6JQNq7Q2QtJV0hgQou0rYuet4/gJ5B
  wAj75ph6EA==
  /
  SYS@dave2(db2)> @dave.plb
  --再次调用函数,正常使用:
  SYS@dave2(db2)> select F_DAVE(4) fromdual;
  F_DAVE(4)
  --------------------------------------------------------------------------------
  Dave come from HuaiNing!
  --查看函数源码,已经加过密了:
  SYS@dave2(db2)> select text fromdba_source where name='F_DAVE';
  TEXT
  --------------------------------------------------------------------------------
  FUNCTION F_DAVE wrapped
  a000000
  1
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  TEXT
  --------------------------------------------------------------------------------
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  abcd
  8
  10d e7
  S9NWrpt8q6tkKEMxCcfYJz2aLF4wgxDQLZ4VfC9AkE6OnV4ydypXGhveHcDg8UXy98WIg6xR
  crtc/BRdQJjutbna/9+g0LlaSx87/znV+y926S1AeC0IRi/tjPJTyvJereDdk8mftMo8QMjV
  TEXT
  --------------------------------------------------------------------------------
  fw0xXn0zVagAawwNVhSAiy/JPTMKkrBkC5ruMwQSTe6JQNq7Q2QtJV0hgQou0rYuet4/gJ5B
  wAj75ph6EA==
示例2:SYS.DBMS_DDL 函数
  the dbms_ddl package provides wrap functionsand create_wrapped procedures, each of whichwraps the pl/sql source text of a single dynamically generated wrappable pl/sqlunit.
  The DBMS_DDL packagealso provides the exception MALFORMED_WRAP_INPUT (ORA-24230),which is raised if the input to WRAP or CREATE_WRAPPED isnot a valid wrappable PL/SQL unit. (For the list of wrappable PL/SQL units, seethe introduction to "PL/SQLSource Text Wrapping".)
  Each WRAP functiontakes as input a single CREATE statement that creates a wrappablePL/SQL unit and returns an equivalent CREATE statement in which thePL/SQL source text is wrapped. For more information about the WRAP functions,see OracleDatabase PL/SQL Packages and Types Reference.
  Each CREATE_WRAPPED proceduredoes what its corresponding WRAP function does and then runs thereturned CREATE statement, creating the specified PL/SQL unit. Formore information about the CREATE_WRAPPED procedures。
  该示例直接参考官方文档:
  DECLARE
  package_textVARCHAR2(32767); --text for creating package spec and body
  FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS
  BEGIN
  RETURN 'CREATE PACKAGE ' || pkgname || ' AUTHID DEFINER AS
  PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);
  PROCEDURE fire_employee (emp_id NUMBER);
  END ' || pkgname || ';';
  ENDgenerate_spec;
  FUNCTION generate_body (pkgname VARCHAR2) RETURN VARCHAR2 AS
  BEGIN
  RETURN'CREATE PACKAGE BODY ' || pkgname || ' AS
  PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS
  BEGIN
  UPDATE employees
  SET salary = salary + amount WHERE employee_id = emp_id;
  END raise_salary;
  PROCEDURE fire_employee (emp_id NUMBER) IS
  BEGIN
  DELETE FROM employees WHERE employee_id = emp_id;
  END fire_employee;
  END ' || pkgname || ';';
  ENDgenerate_body;
  BEGIN
  package_text := generate_spec('emp_actions');-- Generate package spec
  EXECUTE IMMEDIATE package_text;                -- Create package spec
  package_text := generate_body('emp_actions');-- Generate package body
  SYS.DBMS_DDL.CREATE_WRAPPED(package_text);   -- Create wrapped package body
  END;
  /
二. Unwrap 说明
  wrap的目的是为了加密,所以Oracle并没有提供unwrap 的方法。 itpub上的一些牛人研究了一下这个问题,写了一些unwrap的代码。 具体讨论的过程,参考itpub的2个帖子:
  http://www.itpub.net/thread-1154232-1-2.html
  http://www.itpub.net/viewthread.php?tid=1175718&extra=page%3D1&frombbs=1
  我这里贴一下unwrap 的代码:
  /* Formatted on2011/8/18 12:59:54 (QP5 v5.163.1008.3004) */
  CREATE OR REPLACE PACKAGE amosunwrapper
  IS
  FUNCTION deflate (src IN VARCHAR2)
  RETURN RAW;
  FUNCTION deflate (src IN VARCHAR2, quality IN NUMBER)
  RETURN RAW;
  FUNCTION inflate (src IN RAW)
  RETURN VARCHAR2;
  END;
  /
  CREATE OR REPLACE PACKAGE BODY amosunwrapper
  IS
  FUNCTION deflate (src IN VARCHAR2)
  RETURN RAW
  IS
  BEGIN
  RETURN deflate (src, 6);
  END;
  FUNCTION deflate (src IN VARCHAR2, quality IN NUMBER)
  RETURN RAW
  AS
  LANGUAGE JAVA
  NAME 'UNWRAPPER.Deflate( java.lang.String, int ) returnbyte[]';
  FUNCTION inflate (src IN RAW)
  RETURN VARCHAR2
  AS
  LANGUAGE JAVA
  NAME 'UNWRAPPER.Inflate( byte[] ) returnjava.lang.String';
  END;
  /
  /* Formatted on2011/8/18 13:00:16 (QP5 v5.163.1008.3004) */
  CREATE OR REPLACE JAVA SOURCE NAMED UNWRAPPER
  AS import java.io.*;
  import java.util.zip.*;
  public> UNWRAPPER
  {
  public static String Inflate( byte[] src )
  {
  try
  {
  ByteArrayInputStream bis = new ByteArrayInputStream( src );
  InflaterInputStream iis = newInflaterInputStream( bis );
  StringBuffer sb = newStringBuffer();
  for( int c = iis.read(); c != -1; c = iis.read() )
  {
  sb.append( (char) c );
  }
  return sb.toString();
  } catch ( Exception e )
  {
  }
  return null;
  }
  public static byte[] Deflate( String src, intquality )
  {
  try
  {
  byte[] tmp = newbyte[ src.length() + 100 ];
  Deflater defl = new Deflater( quality );
  defl.setInput( src.getBytes( "UTF-8" ) );
  defl.finish();
  int cnt = defl.deflate( tmp );
  byte[] res = newbyte[ cnt ];
  for( int i = 0; i UNWRAPPER
  {
  public static String Inflate( byte[] src )
  {
  try
  {
  ByteArrayInputStream bis = newByteArrayInputStream( src );
  InflaterInputStream iis = newInflaterInputStream( bis );
  StringBuffer sb = newStringBuffer();
  for( int c = iis.read(); c != -1; c = iis.read() )
  {
  sb.append( (char) c );
  }
  String hello = new String(sb.toString().getBytes("iso8859-1"), "GBK");
  return hello;
  } catch ( Exception e )
  {
  }
  return null;
  }
  public static byte[] Deflate( String src, intquality )
  {
  try
  {
  byte[] tmp = newbyte[ src.length() + 100 ];
  Deflater defl = new Deflater( quality );
  defl.setInput( src.getBytes( "UTF-8" ) );
  defl.finish();
  int cnt = defl.deflate( tmp );
  byte[] res = newbyte[ cnt ];
  for( int i = 0; i 0 AND ncnt exec unwrap('SYS','DBMS_ROWID','PACKAGE BODY');
  SQL>select * from dba_source where name='DBMS_ROWID';

页: [1]
查看完整版本: Oracle wrap 和 unwrap( 加密与解密) 说明