首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 實作 Unix crypt(3) 標準加密演算法:JCrypt 類別完整原始碼

     編輯:Java 相關知識

前言

Unix crypt(3) 是基於 DES 的單向雜湊函數,常用於密碼儲存。本文提供純 Java 移植版 JCrypt 類,完整實現標準演算法,包含鹽值處理、金鑰排程、S-Box 置換、最終編碼為 13 字元可列印字串。

演算法核心流程

  1. 鹽值處理:取前兩字元映射至 Eswap0, Eswap1 (查表 con_salt)
  2. 金鑰排程:密碼轉 8 位元組金鑰 (每字元左移 1 位),經 DES 金鑰排程產生 16 輪子金鑰
  3. 加密主體:以全零 64 位區塊進行 25 輪 DES 加密 (每輪 4 次 D_ENCRYPT)
  4. 輸出編碼:64 位結果按 6 位分組轉為 11 字元,加上 2 字元鹽值共 13 字元

關鍵資料結構

  • con_salt[64]:鹽值字元到 E-box 交換位模式的映射表
  • shifts2[16]:每輪金鑰左移位數 (1 或 2 位)
  • skb[8][64]:S-Box 壓縮置換表 (8 個 S-Box,各 64 入口)
  • SPtrans[8][64]:S-Box 輸出經 P-Box 置換後的預計算表
  • cov_2char[64]:6 位值到輸出字元集 (./0-9A-Za-z) 的映射

完整原始碼

package secure_election_system;

public class JCrypt {
    private JCrypt() {}
    private static final int ITERATIONS = 16;
    private static final int con_salt[] = { /* 64 入口表 */ };
    private static final boolean shifts2[] = { /* 16 輪移位旗標 */ };
    private static final int skb[][] = { /* 8 S-Box 表 */ };
    private static final int SPtrans[][] = { /* 8 SP 轉換表 */ };
    private static final int cov_2char[] = { /* 64 字元編碼表 */ };

    private static final int byteToUnsigned(byte b) { ... }
    private static int fourBytesToInt(byte b[], int offset) { ... }
    private static final void intToFourBytes(int iValue, byte b[], int offset) { ... }
    private static final void PERM_OP(int a, int b, int n, int m, int results[]) { ... }
    private static final int HPERM_OP(int a, int n, int m) { ... }
    private static int[] des_set_key(byte key[]) { ... }
    private static final int D_ENCRYPT(int L, int R, int S, int E0, int E1, int s[]) { ... }
    private static final int[] body(int schedule[], int Eswap0, int Eswap1) { ... }

    public synchronized static final String crypt(String salt, String original) {
        while (salt.length() < 2) salt += "A";
        StringBuffer buffer = new StringBuffer("  ");
        buffer.setCharAt(0, salt.charAt(0));
        buffer.setCharAt(1, salt.charAt(1));
        int Eswap0 = con_salt[(int) salt.charAt(0)];
        int Eswap1 = con_salt[(int) salt.charAt(1)] << 4;
        byte key[] = new byte[8];
        for (int i = 0; i < key.length && i < original.length(); i++) {
            key[i] = (byte) (original.charAt(i) << 1);
        }
        int schedule[] = des_set_key(key);
        int out[] = body(schedule, Eswap0, Eswap1);
        byte b[] = new byte[9];
        intToFourBytes(out[0], b, 0);
        intToFourBytes(out[1], b, 4);
        b[8] = 0;
        for (int i = 2, y = 0, u = 0x80; i < 13; i++) {
            for (int j = 0, c = 0; j < 6; j++) {
                c <<= 1;
                if (((int) b[y] & u) != 0) c |= 1;
                u >>>= 1;
                if (u == 0) { y++; u = 0x80; }
                buffer.setCharAt(i, (char) cov_2char[c]);
            }
        }
        return buffer.toString();
    }
}

使用範例

String hashed = JCrypt.crypt("ab", "myPassword"); // 產生 13 字元雜湊
// 驗證時重新計算並比對
if (JCrypt.crypt(hashed.substring(0,2), inputPassword).equals(hashed)) {
    // 密碼正確
}

安全性提醒

  • 已過時:DES 基礎、56 位有效金鑰、無現代保護 (無迭代、無記憶體硬化)
  • 僅相容舊系統:新專案請使用 PBKDF2、bcrypt、scrypt 或 Argon2
  • 鹽值長度固定 2 字元:僅 4096 種組合,易受彩虹表攻擊

現代替代方案對比

演算法特點Java 實作
BCryptBlowfish 基礎、內建鹽值、可調成本因子BCrypt.hashpw() (jBCrypt)
PBKDF2NIST 標準、HMAC 迭代、廣泛支援SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
Argon2記憶體硬化、抗 GPU/ASIC、PHC 首獎Argon2Factory.create() (argon2-jvm)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved