加密解密使用同一把金鑰。優點:演算法簡單高效、金鑰短、速度快、破解極難。缺點:安全性仰賴金鑰保管,公開網路傳遞金鑰風險高,多用戶環境下金鑰管理複雜。代表:DES。
任意長度資料產生唯一「數位指紋」(如 SHA-1 產生 20 位元組)。兩大屬性:
代表:SHA-1(NIST)、MD5(Rivest)。
允許雙方在公開管道交換資訊,協商出共享祕密金鑰。代表:指數金鑰交換協定。
1976 年 Diffie-Hellman 奠基。加密金鑰(公開金鑰)公開,解密金鑰(私鑰)獨佔。代表:RSA(Rivest、Shamir、Adleman 1977 年提出)。
發送者用私鑰對訊息摘要(雜湊值)執行 RSA 運算,確保不可抵賴性與完整性。接收者用發送者公鑰驗證。核心雜湊函數需滿足:輸入無長度限制、輸出固定長度、易正向計算、難反向推導、抗碰撞。代表:DSA。
需安裝 JCE(Java Cryptography Extension),將 jce1.2.1/lib 內容複製至 $JAVA_HOME/jre/lib/ext,並將 jce1_2_1.jar、sunjce_provider.jar 加入 CLASSPATH。
import java.security.*;
public class MyDigest {
public static void main(String[] args) {
new MyDigest().testDigest();
}
public void testDigest() {
try {
String msg = "我的測試訊息";
// 建立 SHA-1 摘要器
MessageDigest alga = MessageDigest.getInstance("SHA-1");
alga.update(msg.getBytes());
byte[] digestA = alga.digest();
System.out.println("本訊息摘要: " + bytesToHex(digestA));
// 模擬接收端驗證
MessageDigest algb = MessageDigest.getInstance("SHA-1");
algb.update(msg.getBytes());
if (MessageDigest.isEqual(digestA, algb.digest())) {
System.out.println("訊息檢查正常");
} else {
System.out.println("摘要不相同,資料可能被竄改");
}
} catch (NoSuchAlgorithmException ex) {
System.out.println("非法摘要演算法");
}
}
// 位元組陣列轉十六進位字串
public String bytesToHex(byte[] b) {
StringBuilder hs = new StringBuilder();
for (int n = 0; n < b.length; n++) {
String stmp = Integer.toHexString(b[n] & 0xFF);
if (stmp.length() == 1) hs.append('0');
hs.append(stmp);
if (n < b.length - 1) hs.append(':');
}
return hs.toString().toUpperCase();
}
}
MessageDigest.getInstance("SHA-1" | "MD5"):取得演算法實例。update(byte[]):輸入資料(可分多次呼叫)。digest():完成計算並回傳摘要(MD5 16 位元組、SHA-1 20 位元組)。reset():重置可重用。isEqual(byte[], byte[]):恆定時間比較兩摘要(防時序攻擊)。// 1. 產生金鑰對
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
SecureRandom random = new SecureRandom();
keyGen.initialize(1024, random); // 1024 bits
KeyPair pair = keyGen.generateKeyPair();
PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();
// 2. 簽名
Signature dsa = Signature.getInstance("SHA1withDSA");
dsa.initSign(privateKey);
dsa.update(dataBytes);
byte[] signature = dsa.sign();
// 3. 驗證
Signature dsaVerify = Signature.getInstance("SHA1withDSA");
dsaVerify.initVerify(publicKey);
dsaVerify.update(dataBytes);
boolean valid = dsaVerify.verify(signature);
金鑰對生成後需妥善儲存(私鑰加密儲存、公鑰分發),後續章節將深入金鑰管理、憑證與 SSL/TLS 整合。