Oracle、Java、Go採用DES/CBC/ZeroPadding加解密一致

加解密,解密前使用16進制編碼轉換字節,加密後使用16進制編碼轉換。以下Java、Go都是針對Oracle進行匹配加解密的。DES加解密都是使用DES/CBC/ZeroPadding模式。

Oracle DES/CBC/ZeroPadding

加密方式CBC,填充方式使用0,偏移量0

--DES 加密
create or replace function des_encrypt(p_text varchar2, p_key varchar2)
  return varchar2 is
  v_text    varchar2(2048);
  v_enc     varchar2(2048);
  v_filllen pls_integer;
begin
  --文本分組不足8位補充0
  v_filllen := ceil(lengthb(p_text) / 8) * 8 - lengthb(p_text);
  v_text    := p_text;
  while (v_filllen > 0) loop
    v_text    := v_text || chr(0);
    v_filllen := v_filllen - 1;
  end loop;
  --DES內置加密
  dbms_obfuscation_toolkit.desencrypt(input_string     => v_text,
                                      key_string       => p_key,
                                      encrypted_string => v_enc);
  return rawtohex(utl_raw.cast_to_raw(v_enc));
exception
  when others then
    return null;
end;

--DES 解密
create or replace function des_decrypt(p_text  j varchar2, p_key varchar2)
  return varchar2 is
  v_text varchar2(2048);
  v_enc  varchar2(2048);
begin
  --密文16進制轉換爲普通字符串
  v_enc := utl_raw.cast_to_varchar2(hextoraw(p_text));
  --內置des解密
  dbms_obfuscation_toolkit.desdecrypt(input_string     => v_enc,
                                      key_string       => p_key,
                                      decrypted_string => v_text);
  return rtrim(v_text, chr(0));
exception
  when others then
    return null;
end;

Java DES/CBC/ZeroPadding

加密方式CBC,填充方式使用0,偏移量0

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;

/**
 * @author zhuyuan 2019/6/1 10:47
 */
public class DESUtils {
    private static final String SECRET_KEY_FACTORY_ALGORITHM = "DES";
    /**
     * 加密算法:DES
     * 加密模式:CBC,每一組的加密模式與之前一組的加密進行強關聯。
     * 位數不足填充模式:不要自動填充,填充由程序實現,使用0填充。
     */
    private static final String CIPHER_ALGORITHM = "DES/CBC/NoPadding";
    /**
     * 密鑰
     */
    private static final String DEFAULT_SECRET_KEY = "12345678";
    /**
     * 偏移量
     */
    private static final byte[] SECRET_KEY_IV = {0, 0, 0, 0, 0, 0, 0, 0};
    /**
     * 分組長
     */
    private final static int BLOCK_SIZE = 8;

    /**
     * 加密
     *
     * @param sourceData
     * @return
     */
    public static String encrypt(String sourceData) {
        return encrypt(sourceData, DEFAULT_SECRET_KEY);
    }

    /**
     * 加密
     *
     * @param sourceData
     * @param secretKey
     * @return
     */
    public static String encrypt(String sourceData, String secretKey) {
        return bytesToHexStr(encrypt(sourceData.getBytes(), secretKey));
    }

    /**
     * 加密
     *
     * @param sourceData byte[]
     * @param secretKey  String
     * @return byte[]
     */
    public static byte[] encrypt(byte[] sourceData, String secretKey) {
        try {
            DESKeySpec desKey = new DESKeySpec(secretKey.getBytes());
            // 創建一個密匙工廠,然後用它把DESKeySpec轉換成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_ALGORITHM);
            Key key = keyFactory.generateSecret(desKey);
            // Cipher對象實際完成加密操作
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            // CBC迭代偏移
            IvParameterSpec ips = new IvParameterSpec(SECRET_KEY_IV);
            // 用密匙初始化Cipher對象
            cipher.init(Cipher.ENCRYPT_MODE, key, ips);
            // 現在,獲取數據並加密
            // 正式執行加密操作
            return cipher.doFinal(addPadding(sourceData));
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
	}
}

Go DES/CBC/ZeroPadding

加密方式CBC,填充方式使用0,偏移量0

package main

import (
	"strings"
	"bytes"
	"encoding/hex"
	"crypto/des"
    "crypto/cipher"
)

func main() {
	text := DesEncrypt([]byte("NO爺"), []byte("12345678"))
	println("加密結果:", strings.ToUpper(hex.EncodeToString(text)));
	
	text2 := DesDecrypt(text, []byte("12345678"));
	println("解密結果:", string(text2))
}

//加密
func DesEncrypt(origData, key []byte) []byte {
	iv := []byte{0, 0, 0, 0, 0, 0, 0, 0}
    block, err := des.NewCipher(key)
    if err != nil {
        return nil
    }
    origData = ZeroPadding(origData)
    blockMode := cipher.NewCBCEncrypter(block, iv)
    crypted := make([]byte, len(origData))
    blockMode.CryptBlocks(crypted, origData)
    return crypted
}

func ZeroPadding(in []byte) []byte {
	length := len(in);
	if (length % 8 == 0) {
		return in;
	} else {
		blockCount := length / 8;
		out := make([]byte, (blockCount + 1) * 8)
		var i int;
		for i = 0; i < length; i++ {
			out[i] = in[i];
		}
		return out;
	}
}

//解密
func DesDecrypt(crypted, key []byte) []byte {
	iv := []byte{0, 0, 0, 0, 0, 0, 0, 0}
    block, err := des.NewCipher(key)
    if err != nil {
        return nil
    }
    origData := make([]byte, len(crypted))
    blockMode := cipher.NewCBCDecrypter(block, iv)
    blockMode.CryptBlocks(origData, crypted)
    return NullUnPadding(origData)
}

func NullUnPadding(in []byte) []byte {
    return bytes.TrimRight(in, string([]byte{0}));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章