zoukankan      html  css  js  c++  java
  • AES加解密程序的实现

    AES加解密程序的实现
    正常情况,用户不能访问sys.dbms_crypto,需要DBA授权:grant execute on dbms_crypto to crm;
    建立加解密的PKG_AES包:
    CREATE OR REPLACE PACKAGE PKG_AES IS
    FUNCTION F_ENCRYPT(I_INPUT_STRING VARCHAR2) RETURN VARCHAR2;
    FUNCTION F_DECRYPT(I_INPUT_STRING VARCHAR2,I_KEY_STRING VARCHAR2) RETURN VARCHAR2;
    END;
    /

    CREATE OR REPLACE PACKAGE BODY PKG_AES IS
    --加密
    FUNCTION F_ENCRYPT(I_INPUT_STRING VARCHAR2) RETURN VARCHAR2 IS
    V_KEY_STRING RAW(128) := UTL_RAW.CAST_TO_RAW('abcdefgh123456781234567812345678'); --加密串,同时也是解密串
    V_ENCRYPTED_RAW RAW(200);
    BEGIN
    V_ENCRYPTED_RAW := DBMS_CRYPTO.ENCRYPT(SRC => UTL_RAW.CAST_TO_RAW(I_INPUT_STRING) --被加密的字符串
    ,TYP => DBMS_CRYPTO.AES_CBC_PKCS5 --加密算法,算法有很多
    ,KEY => V_KEY_STRING); --加密串

    RETURN(RAWTOHEX(V_ENCRYPTED_RAW));
    END F_ENCRYPT;
    --解密
    FUNCTION F_DECRYPT(I_INPUT_STRING VARCHAR2,I_KEY_STRING VARCHAR2) RETURN VARCHAR2 IS
    V_KEY_STRING RAW(128) := UTL_RAW.CAST_TO_RAW(I_KEY_STRING); --加密串,同时也是解密串
    V_DECRYPTED_RAW RAW(200);
    BEGIN
    V_DECRYPTED_RAW := DBMS_CRYPTO.DECRYPT(SRC => HEXTORAW(I_INPUT_STRING)
    ,TYP => DBMS_CRYPTO.AES_CBC_PKCS5
    ,KEY => V_KEY_STRING);

    RETURN(UTL_RAW.CAST_TO_VARCHAR2(V_DECRYPTED_RAW));
    END F_DECRYPT;
    END PKG_AES;
    /


    测试:
    SQL> select PKG_AES.F_ENCRYPT('123456789') from dual;
    PKG_AES.F_ENCRYPT('123456789')
    --------------------------------------------------------------------------------
    AAF86856CE79BFCE484B9B4DD686C92E

    SQL> select PKG_AES.F_DECRYPT('AAF86856CE79BFCE484B9B4DD686C92E','abcdefgh123456781234567812345678') from dual;
    PKG_AES.F_DECRYPT('AAF86856CE7
    --------------------------------------------------------------------------------
    123456789

    之前的AES和DES加解密程序虽然实现了字符串的加解密,但如果接触到plsql代码就可以看到加解密串,使用这个加解密串就可以进行解密。
    为了避免这种情况的发生,可以用oracle提供的wrap工具对pl/sql代码进行加密。
    wrap是Oracle所提供的操作系统级的命令,语法如下语法如下:
    wrap iname=input_file [oname=output_file]
    iname 关键字用于指定输入文件的路径名称 oname关键字用于指定输出加密后文件的路径名称,如果省略oname,则会自动生成一个同名的加密文件名,且后缀为plb。
    下面是wrap的用法:
    在D盘根目录下创建一个名称为pkg_aes.sql的文件,文件内容就是上面包的代码,具体为:
    CREATE OR REPLACE PACKAGE PKG_AES IS
    FUNCTION F_ENCRYPT(I_INPUT_STRING VARCHAR2) RETURN VARCHAR2;
    FUNCTION F_DECRYPT(I_INPUT_STRING VARCHAR2,I_KEY_STRING VARCHAR2) RETURN VARCHAR2;
    END;
    /

    CREATE OR REPLACE PACKAGE BODY PKG_AES IS
    --加密
    FUNCTION F_ENCRYPT(I_INPUT_STRING VARCHAR2) RETURN VARCHAR2 IS
    V_KEY_STRING RAW(128) := UTL_RAW.CAST_TO_RAW('abcdefgh123456781234567812345678'); --加密串,同时也是解密串
    V_ENCRYPTED_RAW RAW(200);
    BEGIN
    V_ENCRYPTED_RAW := DBMS_CRYPTO.ENCRYPT(SRC => UTL_RAW.CAST_TO_RAW(I_INPUT_STRING) --被加密的字符串
    ,TYP => DBMS_CRYPTO.AES_CBC_PKCS5 --加密算法
    ,KEY => V_KEY_STRING); --加密串

    RETURN(RAWTOHEX(V_ENCRYPTED_RAW));
    END F_ENCRYPT;
    --解密
    FUNCTION F_DECRYPT(I_INPUT_STRING VARCHAR2,I_KEY_STRING VARCHAR2) RETURN VARCHAR2 IS
    V_KEY_STRING RAW(128) := UTL_RAW.CAST_TO_RAW(I_KEY_STRING); --加密串,同时也是解密串
    V_DECRYPTED_RAW RAW(200);
    BEGIN
    V_DECRYPTED_RAW := DBMS_CRYPTO.DECRYPT(SRC => HEXTORAW(I_INPUT_STRING)
    ,TYP => DBMS_CRYPTO.AES_CBC_PKCS5
    ,KEY => V_KEY_STRING);

    RETURN(UTL_RAW.CAST_TO_VARCHAR2(V_DECRYPTED_RAW));
    END F_DECRYPT;
    END PKG_AES;
    /


    使用wrap命令将以上代码加密:
    在cmd命令窗口中执行
    D:>wrap iname=d:pkg_aes.sql
    用记事本打开加密后的pkg_aes.PLB文件,可看到文件内容为:
    CREATE OR REPLACE PACKAGE PKG_AES IS
    FUNCTION F_ENCRYPT(I_INPUT_STRING VARCHAR2) RETURN VARCHAR2;
    FUNCTION F_DECRYPT(I_INPUT_STRING VARCHAR2,I_KEY_STRING VARCHAR2) RETURN VARCHAR2;
    END;
    /
    CREATE OR REPLACE PACKAGE BODY PKG_AES wrapped
    a000000
    367
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    b
    438 1c6
    O/zFOzXyHW28E7xVeonfs7nb1Jgwgw3DTCDWyo5Vx6qVENUULutFMvbJRTb3owY5NksTrpGa
    +LWdcHAtDdRiTCVVW5Q0dnIAwaLpEaGeOVhH9mkB7ueC3dcRNrzs2UXTd8A+cM11DkUrb1LG
    AuXYgivHzN2nEUWoe68OWDugtCA2yuMNMmwKBba8IUKiTpH07p9Eje2/PwBj21QXATBghsGc
    scT+0HJkQsBCDVO8kzO7C27mWwDAC0JXVQ5JA4jcE0pflHHktB69XTHWUtdBbmGEqy44MniF
    zTA/zw5Soy5+O+H1/gqHn4CC/MOh1wZyqYeDprQ9U1wXKA1OOUL5K0i0tvz6qYwrWV1bsOvu
    dl2KsXZZMLEeqqFbLHX1B7a+kInWhhmHy4OoC8s0kSvLdapIu3Lgcw5OEKS6LGmu44YU2+oi
    vTiktS8plXgBmjr+
    /

    把加密后的内容放到库的命令窗口运行,即可编译通过。
    存储过程加密前后的使用方式没有任何区别。
    由于加密后的内容无法解密,也就不用担心源代码的暴露问题了。
    这个工具使用起来简单方便,尤其是可以批量生成存储过程的加密文件。


    性能测试:
    drop table t purge;
    create table t as select * from dba_objects;
    alter table T add phone VARCHAR2(50);
    update t set phone=to_char(rownum+13012345678);
    73257 rows updated
    commit;
    加密性能测试:
    set timing on
    update t set phone=PKG_AES.F_ENCRYPT(phone,'');
    73257 rows updated
    Executed in 6.266 seconds
    commit;
    select phone from T where rownum<=10;
    PHONE
    --------------------------------------------------
    2A168C06FF70340C656238ADA69E78E3
    39785A5583587C6979EA46615928C139
    7272FB647D7D4065238CD253F6062AED
    0323CECA5BA5E1229D5133570B19CAFE
    510C4B9FD3228F0B3DC1DD8C1E4D6783
    9E3FA4BCD4AB3B257C6981091A564CFC
    955CE3C5E30D6CEF08575F53EAAEF6A9
    42503F4F21D9CDCF4D468E094A6E4FD5
    B6BC3B8C74E9B5D5D9B233EE223EB09B
    FE42348C7FEE46750401F0DAF5EE47B6

    解密性能测试:
    set timing on
    update t set phone=PKG_AES.F_DECRYPT(phone,'abcdefgh123456781234567812345678');
    73257 rows updated
    Executed in 5.219 seconds
    commit;
    select phone from T where rownum<=10;
    PHONE
    --------------------------------------------------
    13012345679
    13012345680
    13012345681
    13012345683
    13012345684
    13012345685
    13012345687
    13012345688
    13012345689
    13012345690
    结论:
    对7万行的小表,加密用时6秒多,解密用时5秒多。效果理想。

    把解密的解密串拿出包后,对大表加解密测试:
    构建大表:
    insert into t select * from t;
    insert into t select * from t;
    ... ...
    commit;
    select count(*) from t;
    COUNT(*)
    ----------
    2344224
    加密性能测试:
    update t set phone=PKG_AES.F_ENCRYPT(phone);
    2344224 rows updated
    Executed in 212.578 seconds
    commit;

    解密性能测试:
    update t set phone=PKG_AES.F_DECRYPT(phone,'abcdefgh123456781234567812345678');
    2344224 rows updated
    Executed in 196.297 seconds
    结论:
    对230万行的大表,加密用时212秒多,解密用时196秒多。效果理想。

  • 相关阅读:
    PC端Vue后台管理系统request.js结合业务封装axios
    从零开始学 Web 之 Vue.js(五)Vue的动画
    css实现左右两个div等高
    css样式优先级计算规则
    jquery中attr和prop区别
    table文字溢出显示省略号问题
    2020-12-15
    2020-12-14
    2020-12-11
    2020-12-10
  • 原文地址:https://www.cnblogs.com/buffercache/p/10209452.html
Copyright © 2011-2022 走看看