完整加解密套件程式碼
CREATE OR REPLACE PACKAGE pg_encrypt_decrypt IS
iKey VARCHAR2(8) := 'Oracle9i'; -- 固定 8 位元組 Key
FUNCTION gen_raw_key (iKey IN VARCHAR2) RETURN RAW;
FUNCTION decrypt_3key_mode (iValue IN RAW, iMode IN PLS_INTEGER) RETURN VARCHAR2;
FUNCTION encrypt_3key_mode (iValue IN VARCHAR2, iMode IN PLS_INTEGER) RETURN RAW;
FUNCTION format_str (iValue IN VARCHAR2) RETURN VARCHAR2;
FUNCTION format_str2 (iValue IN VARCHAR2) RETURN VARCHAR2;
END pg_encrypt_decrypt;
/
CREATE OR REPLACE PACKAGE BODY pg_encrypt_decrypt IS
FUNCTION gen_raw_key (iKey IN VARCHAR2) RETURN RAW AS
rawkey RAW(240) := '';
BEGIN
FOR i IN 1..LENGTH(iKey) LOOP
rawkey := rawkey || HEXTORAW(TO_CHAR(ASCII(SUBSTR(iKey,i,1))));
END LOOP;
RETURN rawkey;
END gen_raw_key;
FUNCTION decrypt_3key_mode (iValue IN RAW, iMode IN PLS_INTEGER) RETURN VARCHAR2 AS
vDecrypted VARCHAR2(4000);
rawkey RAW(240);
BEGIN
rawkey := gen_raw_key(iKey);
vDecrypted := DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(
input_string => UTL_RAW.CAST_TO_VARCHAR2(iValue),
key_string => rawkey,
which => iMode
);
RETURN format_str2(vDecrypted);
END decrypt_3key_mode;
FUNCTION encrypt_3key_mode (iValue IN VARCHAR2, iMode IN PLS_INTEGER) RETURN RAW AS
vEncrypted VARCHAR2(4000);
vEncryptedRaw RAW(2048);
rawkey RAW(240);
BEGIN
rawkey := gen_raw_key(iKey);
vEncrypted := DBMS_OBFUSCATION_TOOLKIT.DES3ENCRYPT(
input_string => format_str(iValue),
key_string => rawkey,
which => iMode
);
vEncryptedRaw := UTL_RAW.CAST_TO_RAW(vEncrypted);
RETURN vEncryptedRaw;
END encrypt_3key_mode;
-- 補齊至 8 位元組倍數 (3DES 區塊大小)
FUNCTION format_str (iValue IN VARCHAR2) RETURN VARCHAR2 AS
m_value VARCHAR2(4000) := iValue;
i PLS_INTEGER;
BEGIN
i := MOD(LENGTH(m_value), 8);
IF i != 0 THEN
m_value := m_value || RPAD('#', 8-i, '#');
END IF;
RETURN m_value;
END format_str;
-- 移除補齊字元
FUNCTION format_str2 (iValue IN VARCHAR2) RETURN VARCHAR2 AS
m_value VARCHAR2(4000) := iValue;
i PLS_INTEGER;
BEGIN
i := INSTR(m_value, '#', 1, 1);
IF i > 0 THEN
m_value := SUBSTR(m_value, 1, i-1);
END IF;
RETURN m_value;
END format_str2;
END pg_encrypt_decrypt;
/
測試表與驗證腳本
CREATE TABLE users1 (
userid VARCHAR2(50) PRIMARY KEY,
password VARCHAR2(4000), -- 明文
encrypted VARCHAR2(4000) -- 密文
);
INSERT INTO users1 VALUES ('user1','user1234yyyy',NULL);
INSERT INTO users1 VALUES ('user2','abcd1234yy',NULL);
INSERT INTO users1 VALUES ('user3','Oracle12yyy',NULL);
-- 加密
UPDATE users1 SET encrypted = pg_encrypt_decrypt.encrypt_3key_mode(password, 1);
-- 查看密文
SELECT * FROM users1;
-- 解密驗證
SELECT userid, password,
pg_encrypt_decrypt.decrypt_3key_mode(encrypted, 1) AS decrypted
FROM users1;
關鍵技術點
| 項目 | 說明 |
| 演算法 | 3DES (DES-EDE3),透過 DBMS_OBFUSCATION_TOOLKIT 內建實作 |
| Key 長度 | 24 位元組 (3 × 8 bytes),範例以 8 字元字串轉 ASCII 碼組成 |
| Mode 參數 | 1 = ECB 模式 (無 IV);2 = CBC 模式 (需 IV,範例未示) |
| Padding | 自訂 # 補齊至 8 bytes 倍數,解密時移除尾端 # |
| 資料類型 | 加密輸入 VARCHAR2 → 輸出 RAW;解密輸入 RAW → 輸出 VARCHAR2 |
安全性建議 (生產環境必讀)
- 棄用 3DES:NIST 已禁用 3DES (2023 後),請改用
DBMS_CRYPTO 的 AES256 (12c+)。
- Key 管理:勿硬編碼 Key,應存於 Oracle Wallet / Key Vault,運行時動態讀取。
- 模式選擇:生產務必使用 CBC/GCM 模式 + 隨機 IV,ECB 模式不安全 (相同明文產生相同密文)。
- 完整性驗證:加密資料應附加 HMAC 或使用 AEAD 模式 (GCM) 防篡改。