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

Java 加密算法實戰筆記:從對稱加密到數字簽名與密鑰協商

     編輯:Java 相關知識

Java Cryptography Architecture (JCA) 與 Extension (JCE) 提供完整的加密工具箱。本文系統整理消息摘要、對稱加密、非對稱加密、數字簽名、Diffie-Hellman 密鑰協商五大核心場景的標準 API 用法、參數選型與工程化落地要點。

一、核心概念速查表

類別代表算法核心類典型用途
消息摘要MD5 (128bit), SHA-1 (160bit), SHA-256MessageDigest文件完整性校驗、密碼存儲 (需加鹽)、區塊鏈
對稱加密DES, 3DES (DESede), AES, BlowfishCipher, KeyGenerator大數據加密、數據庫字段加密、會話加密
非對稱加密RSA (加密/簽名), DSA (僅簽名), ECKeyPairGenerator, Cipher密鑰交換、數字簽名、身份認證
密鑰協商Diffie-Hellman (DH), ECDHKeyAgreement, KeyPairGenerator雙方協商會話密鑰 (TLS/SSL 核心)
數字簽名SHA1withDSA, SHA256withRSA, ECDSASignature防篡改、防抵賴、代碼簽名、電子合同

二、消息摘要:完整性校驗標準模式

public static String digest(String input, String algorithm) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance(algorithm); // "SHA-256"
    byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
    return Hex.encodeHexString(hash); // Apache Commons Codec
}

// 驗證
boolean verified = MessageDigest.isEqual(expectedHash, actualHash); // 定時比較防側信道

工程提示:密碼存儲**禁止**直接使用 MD5/SHA,必須使用 PBKDF2、BCrypt、Argon2 等慢速雜湊 (Spring Security BCryptPasswordEncoder)。

三、對稱加密:AES-GCM 推薦配置 (Java 8+)

public static byte[] encrypt(byte[] plaintext, SecretKey key, byte[] iv) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    GCMParameterSpec spec = new GCMParameterSpec(128, iv); // 128bit 認證標籤
    cipher.init(Cipher.ENCRYPT_MODE, key, spec);
    return cipher.doFinal(plaintext); // 輸出: 密文 || 認證標籤
}

public static byte[] decrypt(byte[] ciphertext, SecretKey key, byte[] iv) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    GCMParameterSpec spec = new GCMParameterSpec(128, iv);
    cipher.init(Cipher.DECRYPT_MODE, key, spec);
    return cipher.doFinal(ciphertext);
}

// 密鑰生成
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256); // AES-256
SecretKey key = kg.generateKey();

// IV 生成 (每次加密唯一)
SecureRandom sr = new SecureRandom();
byte[] iv = new byte[12]; // GCM 推薦 96bit IV
sr.nextBytes(iv);

避坑:

  • **ECB 模式不可用** (模式可見性洩露)
  • CBC 模式需 PKCS5Padding + 隨機 IV,但無完整性保護,易受 Padding Oracle 攻擊
  • **首選 AES-GCM / ChaCha20-Poly1305** (AEAD 同時提供機密性+完整性)
  • 密鑰管理:生產環境使用 HSM/KMS,代碼中僅持有加密後的 DEK (Data Encryption Key)

四、非對稱加密與數字簽名:RSA 最佳實踐

// 密鑰對生成 (2048bit 以上)
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
PrivateKey priv = kp.getPrivate();
PublicKey pub = kp.getPublic();

// 加密 (僅適用短數據,長數據用混合加密)
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pub);
byte[] encrypted = cipher.doFinal(plaintext);

// 簽名 (SHA256withRSA)
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(priv);
sig.update(data);
byte[] signature = sig.sign();

// 驗證
Signature verify = Signature.getInstance("SHA256withRSA");
verify.initVerify(pub);
verify.update(data);
boolean valid = verify.verify(signature);

五、Diffie-Hellman 密鑰協商:雙方生成共享會話鍵


// Alice 端
KeyPairGenerator aliceKpg = KeyPairGenerator.getInstance("DH");
aliceKpg.initialize(2048);
KeyPair aliceKp = aliceKpg.generateKeyPair();
// 發送 aliceKp.getPublic().getEncoded() 給 Bob

// Bob 端
KeyFactory kf = KeyFactory.getInstance("DH");
X509EncodedKeySpec spec = new X509EncodedKeySpec(alicePubEncoded);
PublicKey alicePub = kf.generatePublic(spec);

// 從 Alice 公鑰提取參數,生成自己的 DH 密鑰對
DHParameterSpec dhSpec = ((DHPublicKey) alicePub).getParams();
KeyPairGenerator bobKpg = KeyPairGenerator.getInstance("DH");
bobKpg.initialize(dhSpec);
KeyPair bobKp = bobKpg.generateKeyPair();
// 發送 bobKp.getPublic().getEncoded() 給 Alice

// 雙方各自生成共享密鑰
KeyAgreement aliceKa = KeyAgreement.getInstance("DH");
aliceKa.init(aliceKp.getPrivate());
aliceKa.doPhase(bobPub, true);
SecretKey aliceShared = aliceKa.generateSecret("AES"); // 直接導出 AES 密鑰

KeyAgreement bobKa = KeyAgreement.getInstance("DH");
bobKa.init(bobKp.getPrivate());
bobKa.doPhase(alicePub, true);
SecretKey bobShared = bobKa.generateSecret("AES");

// aliceShared.equals(bobShared) == true

六、密鑰編碼與持久化標準

密鑰類型編碼格式規格類還原代碼
PublicKeyX.509X509EncodedKeySpecKeyFactory.getInstance("RSA").generatePublic(spec)
PrivateKeyPKCS#8PKCS8EncodedKeySpecKeyFactory.getInstance("RSA").generatePrivate(spec)
SecretKeyRaw bytesSecretKeySpecnew SecretKeySpec(bytes, "AES")

七、工程化落地清單

  1. 算法選型:對稱 → AES-256-GCM;非對稱 → RSA-2048-OAEP / ECDSA-P256;摘要 → SHA-256;密碼 → BCrypt/Argon2
  2. 提供者優先級:Security.insertProviderAt(new BouncyCastleProvider(), 1) 確保優先使用 BC 實現 (支援更多算法、常數時間實現)
  3. 隨機數源:SecureRandom (默認強隨機),避免 new Random()
  4. 異常處理:捕獲 GeneralSecurityException 父類,區分 InvalidKeyException、BadPaddingException、IllegalBlockSizeException
  5. 日誌脫敏:嚴禁記錄明文、密鑰、IV、簽名值;僅記錄操作類型、數據長度、成功/失敗
  6. 合規性:FIPS 140-2 環境需啟用 SunPKCS11 接入硬件模塊

八、常見誤區辨析

加密算法雖為標準庫調用,但參數選型、密鑰生命周期管理、側信道防護、合規適配才是工程落地的核心難點。建議團隊建立《加密算法使用規範》,統一算法白名單、參數模板與審計流程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
誤區正確認知
「RSA 可以加密任意長度數據」RSA 明文長度 < KeySize/8 - Padding開銷 (2048bit ≈ 245 bytes)。長數據必須用混合加密:AES 加密數據 + RSA 加密 AES Key
「Base64 是加密」Base64 僅編碼,無任何機密性
「雙重加密更安全」雙重 DES (2DES) 遭遇中間相遇攻擊,安全性等同單 DES。3DES (EDE) 才有效提升
「保存 PrivateKey 到文件即可」必須加密存儲 (PKCS#12 / JCEKS / 加密文件),生產環境上 HSM/KMS