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

Java 程式碼簽名實作:DSA 金鑰產生、簽章與驗證完整範例

     編輯:Java 相關知識

前言

代碼簽名是確保 JAR 檔、Applet、RMI 物件完整性與來源可信的基石。本文提供三個獨立工具類別,示範如何使用 java.security 套件實作 DSA 金鑰對產生、SHA1withDSA 簽章與驗證,適合 Jini、RMI、Applet 部署場景。

1. 金鑰對產生器

import java.security.*;
import java.io.*;

public class KeyPairGen {
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: java KeyPairGen ");
            System.exit(1);
        }
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
            kpg.initialize(512); // 建議生產環境用 2048 bits
            KeyPair kp = kpg.generateKeyPair();

            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(args[0]))) {
                oos.writeObject(kp);
            }
            System.out.println("Key pair saved to " + args[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

執行:java KeyPairGen mykeys.dat

2. 簽章產生器

import java.security.*;
import java.io.*;

public class SignGen {
    public static void main(String[] args) {
        if (args.length != 3) {
            System.out.println("Usage: java SignGen   ");
            System.exit(1);
        }
        try {
            KeyPair kp;
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(args[0]))) {
                kp = (KeyPair) ois.readObject();
            }

            Signature sig = Signature.getInstance("SHA1withDSA");
            sig.initSign(kp.getPrivate());
            sig.update(args[1].getBytes("UTF-8"));
            byte[] signature = sig.sign();

            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(args[2]))) {
                oos.writeObject(signature);
            }
            System.out.println("Signature saved to " + args[2]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

執行:java SignGen mykeys.dat "Hello World" mysig.dat

注意:實務上應對檔案內容計算 SHA-256 摘要再簽章,而非直接簽字串。

3. 簽章驗證器

import java.security.*;
import java.io.*;

public class SignVerify {
    public static void main(String[] args) {
        if (args.length != 3) {
            System.out.println("Usage: java SignVerify   ");
            System.exit(1);
        }
        try {
            KeyPair kp;
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(args[0]))) {
                kp = (KeyPair) ois.readObject();
            }

            byte[] signature;
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(args[2]))) {
                signature = (byte[]) ois.readObject();
            }

            Signature sig = Signature.getInstance("SHA1withDSA");
            sig.initVerify(kp.getPublic());
            sig.update(args[1].getBytes("UTF-8"));

            if (sig.verify(signature)) {
                System.out.println("Verify OK!");
            } else {
                System.out.println("Verify Error!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

執行:java SignVerify mykeys.dat "Hello World" mysig.dat

實務部署建議

場景做法
JAR 檔簽名使用 jarsigner 工具搭配 Keystore (JKS/PKCS12),而非手動序列化 KeyPair
Applet/RMI簽署所有 JAR,並在 JNLP/HTML 中宣告 all-permissions
金鑰長度DSA 512 bits 已不安全,生產環境請用 RSA 2048+ 或 ECDSA P-256
憑證鏈向 CA 購買代碼簽署憑證,避免使用者看到「未受信任」警告
時間戳jarsigner -tsa https://timestamp.digicert.com 確保憑證過期後簽名仍有效

常見錯誤排查

  • InvalidKeyException:金鑰格式不符 (DSA 金鑰用 RSA 算法或反之)
  • SignatureException: Signature length not correct:簽章資料損毀或非對應算法產生
  • ClassNotFoundException:反序列化 KeyPair 時 classpath 缺少提供者類別
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved