使用keytool生成公鑰、私鑰、證書並且讀取出來,使用私鑰簽名jar並驗證(轉)
參考鏈接:http://happyqing.iteye.com/blog/2139504
:https://blog.csdn.net/arjelarxfc/article/details/52461828
:https://blog.csdn.net/yangxt/article/details/1796965
在看書的時候涉及到了Java的安全加密技術,然後發現生成私鑰公鑰證書用的是keytool這個jdk自帶插件
keytool的主要用法:
keytool的幾個常用的命令。
1.創建證書
2.查看證書庫
3.導出證書文件
4.導入證書的信息
5.查看證書信息
6.刪除密鑰庫中的條目
7.修改證書條目的口令
SUN公司提供了制作證書的工具keytool。
在JDK 1.4以後的版本中都包含了這一工具,它的位置為<JAVA_HOME>\bin\keytool.exe。
1.創建證書
Cmd代碼- keytool -genkeypair -alias "test1" -keyalg "RSA" -keystore "test.keystore"
說明:
密鑰庫密碼為testtest
證書條目密碼為testtest1,若別名為test2則密碼為testtest2
這樣為個不亂
功能:
創建一個別名為test1的證書條目,該條目存放在名為test.keystore的密鑰庫中,若test.keystore密鑰庫不存在則創建。
參數說明:
-genkeypair:生成一對非對稱密鑰;
-alias:指定密鑰對的別名,該別名是公開的;
-keyalg:指定加密算法,本例中的采用通用的RAS加密算法;
-keystore:密鑰庫的路徑及名稱,不指定的話,默認在操作系統的用戶目錄下生成一個".keystore"的文件
註意:
1.“名字與姓氏”應該是域名,若輸成了姓名,和真正運行的時候域名不符,會出問題;
2.再次輸入密碼,第一次輸入的是密鑰庫(keystore)的密碼,第二次輸入的是證書條目的密碼
3.這裏所說的證書庫和密鑰庫是等同的(個人觀點)
為了測試需要,這裏再創建兩個別名為test2和test3的證書條目在test.keystore密鑰庫中,代碼如下:
- keytool -genkeypair -alias "test2" -keyalg "RSA" -keystore "test.keystore"
- keytool -genkeypair -alias "test3" -keyalg "RSA" -keystore "test.keystore"
2.查看證書庫
Cmd代碼- keytool -list -keystore test.keystore
功能:
查看名為test.keystore的證書庫中的證書條目
3.導出到證書文件
Cmd代碼- keytool -export -alias test1 -file test.crt -keystore test.keystore
功能:
將名為test.keystore的證書庫中別名為test1的證書條目導出到證書文件test.crt中
4.導入證書的信息
Cmd代碼- keytool -import -keystore test_cacerts -file test.crt
功能:
將證書文件test.crt導入到名為test_cacerts的證書庫中,
5.查看證書信息
Cmd代碼- keytool -printcert -file "test.crt"
功能:
查看證書文件test.crt的信息
6.刪除密鑰庫中的條目
刪除前查看密鑰庫test.keysote中的證書條目
Cmd代碼- keytool -list -keystore test.keystore
刪除密鑰庫test.keystore中別名為test2的證書條目
Cmd代碼- keytool -delete -keystore test.keystore -alias test2
刪除後查看密鑰庫test.keystore中的證書條目
Cmd代碼- keytool -list -keystore test.keystore
7.修改證書條目的口令
交互的方式
Cmd代碼- keytool -keypasswd -alias test1 -keystore test.keystore
功能:
將密鑰庫test.keystore中別名為test1的證書條目的密碼修改為testtesttest1
非交互方式
Cmd代碼- keytool -keypasswd -alias test1 -keypass testtesttest1 -new testtest1 -storepass testtest -keystore test.keystore
功能:
將密鑰庫test.keystore中別名為test1的證書條目的密碼修改為testtest1
我使用的命令:
keytool -genkey -alias friend -keypass friend4life -validity 10000 -keystore ijvmkeys
賦給ijvmkeys的密碼是:ijvm2ed
keytool -genkey -alias stranger -keypass stranger4life -validity 10000 -keystore ijvmkeys
這裏是將生成了兩對私鑰公鑰和證書放在一個keystore裏面,用別名區分。並且指定了keystore的展示密碼為:ijvm2ed,條目的密碼分別為:friend4life和stranger4life。
然後接下來使用jarsigner利用生成的秘鑰證書進行簽名:
jarsigner -keystore ijvmkeys -storepass ijvm2ed -keypass friend4life friend.jar friend
jar signer -keystore ijvmkeys -storepass ijvm2ed -keypass stranger4life stranger.jar stranger
然後使用jarsigner可以做簽名校驗:
將jar裏的文件做修改,然後再次驗證:
keystore文件不是證書,它可以使用命令得到證書。加密的私鑰和公鑰怎麽得到呢?以及單獨的證書怎麽用Java方式得到呢?
之前一直在糾結這個問題,並且圖為friend4life是我們的私鑰,後面發現那只是倉庫鑰匙而已。私鑰公鑰等可以用Java代碼得到:
package kunpu.security; import sun.misc.BASE64Encoder; import java.io.FileInputStream; import java.io.FileWriter; import java.security.*; import java.security.cert.Certificate; /** * @author zhen * @Date 2018/4/16 10:58 */ public class ExportCert { //導出證書 base64格式 public static void exportCert(KeyStore keyStore, String alias, String exportFile) throws Exception { Certificate certificate = keyStore.getCertificate(alias); BASE64Encoder encoder = new BASE64Encoder(); String encoded = encoder.encode(certificate.getEncoded()); FileWriter fw = new FileWriter(exportFile); fw.write("------Begin Certificate----- \r\n ");//非必須 fw.write(encoded); fw.write("\r\n-----End Certificate-----");//非必須 fw.close(); } //得到KeyPair public static KeyPair getKeyPair(KeyStore keyStore, String alias, char[] password){ try{ Key key = keyStore.getKey(alias, password); if (key instanceof PrivateKey){ Certificate certificate = keyStore.getCertificate(alias); PublicKey publicKey = certificate.getPublicKey(); return new KeyPair(publicKey, (PrivateKey) key); } }catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e){ e.printStackTrace(); } return null; } //導出私鑰 public static void exportPrivateKey(PrivateKey privateKey, String exportFile) throws Exception { BASE64Encoder encoder = new BASE64Encoder(); String encoded = encoder.encode(privateKey.getEncoded()); FileWriter fileWriter = new FileWriter(exportFile); fileWriter.write("-----Begin Private Key-----\r\n");//非必須 fileWriter.write(encoded); fileWriter.write("\r\n-----End Private Key-----");//非必須 fileWriter.close(); } //導出公鑰 public static void exportPublicKey(PublicKey publicKey, String exportFile) throws Exception { BASE64Encoder encoder = new BASE64Encoder(); String encoded = encoder.encode(publicKey.getEncoded()); FileWriter fileWriter = new FileWriter(exportFile); fileWriter.write("-----Begin Public Key-----\r\n");//非必須 fileWriter.write(encoded); fileWriter.write("\r\n-----End Public Key-----");//非必須 fileWriter.close(); } public static void main(String[] args) throws Exception{ String keyStoreType = "jks"; String keystoreFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\ijvmkeys"; String password = "ijvm2ed"; //keystore的解析密碼 String friendPassword = "friend4life";//條目的解析密碼 KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(new FileInputStream(keystoreFile), password.toCharArray()); String alias = "friend";//條目別名 String exportCertFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\cert.txt"; String exportPrivateFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\privateKey.txt"; String exportPublicFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\publicKey.txt"; ExportCert.exportCert(keyStore, alias, exportCertFile); KeyPair keyPair = ExportCert.getKeyPair(keyStore, alias, friendPassword.toCharArray()); //註意這裏的密碼是你的別名對應的密碼,不指定的話就是你的keystore的解析密碼 ExportCert.exportPrivateKey(keyPair.getPrivate(), exportPrivateFile); ExportCert.exportPublicKey(keyPair.getPublic(), exportPublicFile); System.out.println("OK"); } }
代碼當中遇到過問題,就是條目的密碼指定錯誤了。沒有指定默認使用的 是keystore的密碼
jarsigner:jar的簽名和校驗工具
jarsigner - JAR 簽名和校驗工具
為 Java 歸檔 (JAR) 文件產生簽名,並校驗已簽名的 JAR 文件的簽名。
結構
jarsigner [ options ] jar-file alias jarsigner -verify [ options ] jar-file
說明
jarsigner
為 Java 歸檔 (JAR) 文件簽名 校驗已簽名的 JAR 文件的簽名和完整性JAR 功能使得類文件、圖像、聲音和其它數字化數據可打包到一個文件中,以便更方便快捷地發布。名為 jar 的工具使開發者可以生成 JAR 文件(從技術上來說,任何 zip 文件都可看作為 JAR 文件,盡管由 jar 創建或由 jarsigner 處理時,JAR 文件也包含一個 META-INF/MANIFEST.MF 文件)。
數字簽名是一個根據某些數據(被“簽名”的數據)和實體(人、公司等)的私鑰計算出來的位字符串。與手寫的簽名一樣,數字簽名有很多有用的特性:
其真實性可被校驗,方法是使用與生成簽名的私鑰對應的公鑰進行計算。 它不可能被偽造(假設私鑰沒有泄露)。 它是已簽名數據的函數,因此不能被聲明為其它數據的簽名。 已簽名的數據不能被修改;如果被修改了,簽名將不再被校驗為可信的。為了給文件生成一個實體的簽名,該實體首先必須有一對與它相關的公/私鑰對,以及一個或多個鑒別其公鑰的證書。證書是由某個實體的數字化方式簽發的聲明,證明其它實體的公鑰是某個特定的值。
jarsigner 使用來自密鑰倉庫的密鑰和證書信息為 JAR 文件生成數字簽名。密鑰倉庫是一個由私鑰及其相關的 X.509 證書鏈(它鑒別相應公鑰)組成的數據庫。使用 keytool 實用程序來創建和管理密鑰倉庫。
jarsigner 使用實體的私鑰創建簽名。已簽名的 JAR 文件包含(除了其它東西)一份來自密鑰倉庫的公鑰(它對應於用於為該文件簽名的私鑰)的證書副本。jarsigner 可以使用已簽名的 JAR 文件中的證書(在其簽名塊文件中)來校驗其數字簽名。
現在 jarsigner 只能為 JDK 的 jar 工具創建的 JAR 文件或 zip 文件簽名(除了它們還有一個 META-INF/MANIFEST.MF 文件以外,JAR 文件與 zip 文件一樣)。當 jarsigner 為 zip 文件簽名時將自動創建這樣的文件。
jarsigner 的缺省行為是簽名 JAR(或 zip)文件。使用
-verify
選項將其替換為校驗已簽名的 JAR 文件。JDK 1.1 的兼容性
keytool 和 jarsigner 工具完全替代了 JDK 1.1 中提供的 javakey 工具。這些新工具所提供的功能比 javakey 提供的多,包括能夠用口令來保護密鑰倉庫和私鑰,以及除了能夠生成簽名外還可以校驗它們。
新的密鑰倉庫體系結構取代了 javakey 所創建和管理的身份數據庫。密鑰倉庫格式和 1.1 版中 javakey 使用的數據庫格式之間沒有向後兼容。但是,
可以通過 keytool-identitydb
命令將身份數據庫中的信息導入密鑰倉庫。 jarsigner 可以簽名先前已用 javakey 簽過名的 JAR 文件。 jarsigner 可以校驗用 javakey 簽名的 JAR 文件。因此,它識別並能處理來自 JDK 1.1 身份數據庫而不是 JDK 1.2 密鑰倉庫的簽名人別名。下表解釋了在 JDK 1.1.x 中簽名的 JAR 文件在 JDK 1.2 中是如何處理的。
JAR 文件類型 在 1.1 數據庫中的身份 從 1.1 數據庫 (4) 導入到 1.2 密鑰倉庫的可信的身份 策略文件為 Identity/Alias
授特權 被授予的權利 已簽名的 JAR 否 否 否 授予所有代碼的缺省權利。 未簽名的 JAR 否 否 否 授予所有代碼的缺省權利。 已簽名的 JAR 否 是 否 授予所有代碼的缺省權利。 已簽名的 JAR 是/不受信任 否 否 授予所有代碼的缺省權利。(3) 已簽名的 JAR 是/不受信任 否 是 授予所有代碼的缺省權利。(1,3) 已簽名的 JAR 否 是 是 授予所有代碼的缺省權利加上策略文件中授予的權利。 已簽名的 JAR 是/受信任 是 是 授予所有代碼的缺省權利加上策略文件中授予的權利。(2) 已簽名的 JAR 是/受信任 否 否 所有權利 已簽名的 JAR 是/受信任 是 否 所有權利 (1) 已簽名的 JAR 是/受信任 否 是 所有權利 (1)註意:
如果策略文件中提到了 identity/alias,則它必須導入到密鑰倉庫中,以使策略文件影響授予的權利。 策略文件/密鑰倉庫組合在身份數據庫中優先於可信任的身份。 JDK 1.2 中忽略不可信任的身份。 只有可信任的身份才能導入到 JDK 1.2 密鑰倉庫。密鑰倉庫別名
所有密鑰倉庫實體都須通過唯一的別名來訪問。
當使用 jarsigner 簽名 JAR 文件時,必須為包含用於生成簽名的私鑰的密鑰倉庫實體指定別名。例如,下面命令將使用與別名“duke”(它在“working”目錄下的名為“mystore”的密鑰倉庫中)相關聯的私鑰為名為“MyJARFile.jar”的 JAR 文件簽名。因為沒有指定輸出文件,它將用已簽名的 JAR 文件覆蓋 MyJARFile.jar。
jarsigner -keystore /working/mystore -storepass myspass -keypass dukekeypasswd MyJARFile.jar duke密鑰倉庫被口令保護,因此必須指定倉庫口令(此處為“myspass”)。如果在命令行中沒有指定它,將提示需要它。同樣,私鑰也被口令保護在密鑰倉庫中,因此必須指定該私鑰的口令(此處為“dukekeypasswd”),如果沒有在命令行中指定它或與倉庫口令不一樣,將提示需要它。
密鑰倉庫位置
jarsigner
有一個-keystore
選項用於指定要使用的密鑰倉庫的 URL。按默認,密鑰倉庫儲存在用戶宿主目錄(由系統屬性的 "user.home" 決定)中名為 .keystore 的文件中。在 Solaris 系統中 "user.home" 默認為用戶的宿主目錄。密鑰倉庫實現
java.security
目前有兩個命令行工具(keytool 和 jarsigner),以及一個基於 GUI 的工具(名為 Policy Tool)利用密鑰倉庫實現。由於
密鑰倉庫
是公用的, JDK 用戶可編寫其它的使用該密鑰倉庫的安全性應用程序。
有個固有的默認實現,是由 Sun Microsystems 公司提供的。它利用名為“JKS” 的專用密鑰倉庫類型(格式),將密鑰倉庫實現為一個文件。它用單個口令保護每個私鑰,也用口令(可能為另一個口令)保護整個密鑰倉庫的完整性。
密鑰倉庫的實現基於提供者。具體地說,由
keystore
所提供的應用程序接口是借助於“服務提供者接口”(SPI) 來實現的。也就是說,有對應的抽象KeystoreSpi
類,也是在java.security
包中,它定義了“提供者”必須實現的服務提供者接口方法(“提供者”指的是一個或一組包,這個或這組包提供了一部份可由 JDK 安全 API 訪問的那些服務的具體實現)。因此,要提供密鑰倉庫實現,客戶必須實現提供者並提供 KeystoreSpi 子類實現,如如何為 Java 加密體系結構實現 提供者 中所述。
通過使用
KeyStore
類中提供的“getInstance”工廠方法,應用程序可從不同的提供者中挑選不同類型的密鑰倉庫實現。密鑰倉庫類型定義密鑰倉庫信息的存儲和數據格式,以及用於保護密鑰倉庫中的私鑰和密鑰倉庫自身完整性的算法。不同類型的密鑰倉庫實現是不兼容的。
keytool 可以使用任何基於文件的密鑰倉庫實現 (它把在命令行中傳遞給它的密鑰倉庫位置當成文件處理並將之轉換為文件輸入流,從該文件輸入流中加載密鑰倉庫信息)。另一方面,jarsigner 和 policytool 工具可從任何可用 URL 指定的位置讀取某個密鑰倉庫。
對於 jarsigner 和 keytool,可以通過 -storetype 選項在命令行中指定密鑰倉庫類型。對於 策略工具,可通過“編輯”菜單中的“更改密鑰倉庫”命令來指定密鑰倉庫類型。
如果沒有顯式地指定密鑰倉庫類型,這些工具將只是根據安全屬性文件中指定的
keystore.type
屬性值來選擇密鑰倉庫實現。安全屬性文件名叫 java.security,它位於 JDK 安全屬性目錄java.home/lib/security
中,其中 java.home 為 JDK 的安裝目錄。
每個工具都先獲取
keystore.type
的值,然後檢查所有當前已安裝的提供者直到找到實現所要求類型的密鑰倉庫的提供者為止。然後就使用該提供者的密鑰倉庫實現。
KeyStore
類定義了名為getDefaultType
的靜態方法,它可讓應用程序或 applet 檢索keystore.type
屬性的值。以下代碼將創建默認密鑰倉庫類型(此類型由keystore.type
屬性所指定)的實例:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
默認的密鑰倉庫類型是 "jks" (這是由 "SUN" 提供的密鑰倉庫實現的專用類型)。它在安全性屬性文件中由下面這行進行指定:
keystore.type=jks
要使工具利用非缺省的密鑰倉庫實現,請更改此行以指定不同的密鑰倉庫類型。
如果您有這樣的提供者包,它給出名為 "pkcs12" 的密鑰倉庫類型的密鑰倉庫實現,則可將前面提到的那行改為:
keystore.type=pkcs12
註意: 密鑰倉庫類型的命名中大小寫無關緊要。例如,"JKS" 將被認為是與 "jks" 相同的。
包中提供的
KeyStore
類為訪問和修改密鑰倉庫中的信息提供了相當固定的接口。可以有多個不同的具體實現,其中每個實現都是對某個特定類型的密鑰倉庫的具體實現。支持的算法
現在 jarsigner 使用二者都可以簽名 JAR 文件。
帶 SHA-1 報文摘要算法的DSA (數字簽名算法),或 帶 MD5 報文摘要算法的 RSA 算法。也就是說,如果簽名人的公鑰和私鑰是 DSA 密鑰,則 jarsigner 將使用“SHA1withDSA”算法為 JAR 文件簽名。如果簽名人的密鑰是 RSA 密鑰,jarsigner 將試圖使用“MD5withRSA”算法為 JAR 文件簽名。這只有靜態地安裝了提供“MD5withRSA”算法實現的提供者才可能(來自缺省的“SUN”提供者的“SHA1withDSA”算法總是可用的)。
已簽名的 JAR 文件
當 jarsigner 被用於為 JAR 文件簽名時,輸出的已簽名 JAR 文件與輸入 JAR 文件完全一樣,除了它在 META-INF 目錄下有兩個附加文件:
擴展名為 .SF 的簽名文件,以及 擴展名為 .DSA 的簽名塊文件。這兩個文件的基本文件名來自
-sigFile
選項。例如,如果該選項為-sigFile MKSIGN則這兩個文件分別為“MKSIGN.SF”和“MKSIGN.DSA”。
如果命令行中沒有
-sigfile
選項,則 .SF 和 .DSA 文件的基本文件名將是命令行中指定的別名的前 8 個字符,並全部被轉換為大寫。如果別名少於 8 個字符,將使用整個別名。如果別名中包含簽名文件名所不允許的字符,則形成文件名時這樣的字符將被轉換為下劃線 ("_")。合法的字符包括字母、數字、下劃線和連字符。簽名 (.SF) 文件
簽名文件(.SF 文件)與清單文件相似,後者總是在用 jarsigner 對文件進行簽名時包含在 JAR 文件中。也就是說,對於 JAR 文件中包含的每個源文件,.SF 文件與清單文件一樣有如下三行:
文件名, 使用的報文摘要算法 (SHA),以及 SHA 摘要值。在清單文件中,SHA 每個源文件的摘要值是源文件中二進制數據的摘要 (散列)。而在 .SF 文件中,給定源文件的摘要值是該源文件的清單文件中的三行的散列。
缺省情況下簽名文件還包含一個含有整個清單文件的散列的頭。這個頭使得可以進行校驗優化,如 JAR 文件校驗所述。
簽名塊 (.DSA) 文件
.SF 文件被簽名且簽名被放入 .DSA 文件。.DSA 文件還包含來自密鑰倉庫的證書或證書鏈(被編碼到其中),它們鑒別與用於簽名的私鑰對應的公鑰。
JAR 文件校驗
如果簽名合法,並且簽名生成時在 JAR 文件中的文件從此沒有更改過,JAR 文件校驗將成功。JAR 文件校驗包括下列步驟:
校驗 .SF 文件本身的簽名。也就是說,校驗確保保存在每個簽名塊 (.DSA) 文件中的簽名的確是使用與公鑰(其證書或證書鏈也出現在該 .DSA 文件中)對應的私鑰生成的。它還確保該簽名是相應簽名 (.SF) 文件的合法簽名,因此 .SF 文件沒有被更改過。
將列在 .SF 文件的每個項中的摘要與清單中相應的部分進行校驗。.SF 文件缺省地包含一個含有整個清單文件的散列的頭。該頭存在時,校驗將檢查頭中的散列是否匹配清單文件的散列。如果匹配,校驗將進行下一步。
如果不匹配,則需一個次優的校驗以確保 .SF 文件中的每個源文件信息部分的散列等於清單文件中的相應部分的散列(參見簽名 (.SF) 文件)。
保存在 .SF 文件頭中的清單文件的散列不等於當前清單文件的散列的一種原因可能是因為生成簽名(因此生成 .SF 文件)後一個或多個文件被添加到 JAR 文件中(使用
讀取 JAR 中每個在 .SF 文件中有相應項的文件。讀取時,計算文件的摘要,然後將結果與清單中該文件的摘要部分進行比較。摘要應相同,否則校驗將失敗。jar
工具)。當jar
工具用於添加文件時,清單文件被更改(為新文件添加了節),但 .SF 文件沒有更改。如果簽名生成時在 JAR 文件中的文件從此沒有更改過,校驗仍被認為是成功的,這種情況下 .SF 文件的非頭部分中的散列與清單文件中相應部分的散列相等。如果在校驗期間發生了嚴重的校驗錯誤,則該進程終止並拋出安全異常。它將被 jarsigner捕獲並顯示。
一個 JAR 文件多個簽名
工具用於兩個目的:JAR 文件可以被多個人使用 jarsigner 工具進行多次簽名,每次為不同的人指定別名,如下:
jarsigner myBundle.jar susan jarsigner myBundle.jar kevinJAR 文件被多次簽名時,產生的 JAR 文件中將有多個 .SF 和 .DSA 文件,每個簽名有一對。因此,在上例中,輸出的 JAR 文件將包含下列文件:
SUSAN.SF SUSAN.DSA KEVIN.SF KEVIN.DSA註意: JAR 文件可以有混合簽名,有些是 JDK 1.1 javakey 工具生成的,其它是 jarsigner 生成的。也就是說,jarsigner 可用於為先前已使用 javakey 簽過名的 JAR 文件簽名。
選項
下面列出並說明了各種 jarsigner 選項。註意:
- 所有選項名前都有一個減號 (-)。
- 選項可以以任何次序提供。
- 斜體項(選項值)代表必須提供的實際值。
-keystore
、-storepass
、-keypass
、-sigfile
和-signedjar
選項僅在為 JAR 文件簽名時相關,而不是在校驗已簽名的 JAR 文件時。同樣,別名僅在為 JAR 文件簽名時在命令行中指定。
-keystore
url- 指定密鑰倉庫的 URL。缺省值是用戶的宿主目錄中的 .keystore 文件,它由系統屬性“user.home”決定。
簽名時需要密鑰倉庫,因此如果沒有缺省的(或要使用非缺省的)密鑰倉庫,就必須明確指定一個。
校驗時不需要密鑰倉庫,但如果指定了一個,或存在缺省的,且
-verbose
選項也被指定了,則將輸出該密鑰倉庫中是否包含了用於校驗 JAR 文件的證書的附加信息。註意:
-keystore
參數實際上可以是指定的文件名(及路徑)而不是 URL,這種情況下它將當作“file:” URL. 也就是說,-keystore filePathAndName被當作等價於
-keystore file:filePathAndName-storetype
storetype- 指定要被實例化的密鑰倉庫類型。默認的密鑰倉庫類型是安全屬性文件中 "keystore.type" 屬性值所指定的那個類型,由
java.security.KeyStore
中的靜態方法getDefaultType
返回。-storepass
password- 指定訪問密鑰倉庫所需的口令。這僅在簽名(不是校驗)JAR 文件時需要。在這種情況下,如果命令行中沒有提供
-storepass
選項,用戶將被提示輸入口令。註意: 口令不應在命令行或腳本中指定,除非是為了測試,或在安全系統中。並且,在口令提示下鍵入口令時將顯示出鍵入的字符,因此不要在其它人面前鍵入。
-keypass
password- 指定用於保護密鑰倉庫項(由命令行中指定的別名標出)的私鑰的口令。使用 jarsigner 為 JAR 文件簽名時需要該口令。如果命令行中沒有提供口令,且所需的口令與密鑰倉庫的口令不同,則將提示用戶輸入它。
註意: 口令不應在命令行或腳本中指定,除非是為了測試,或在安全系統中。並且,在口令提示下鍵入口令時將顯示出鍵入的字符,因此不要在其它人面前鍵入。
-sigfile
file- 指定用於生成 .SF 和 .DSA 文件的基本文件名。例如,如果 file 為“DUKESIGN”,則生成的 .SF 和 .DSA 文件將被命名為“DUKESIGN.SF”和“DUKESIGN.DSA”,並將放到已簽名的 JAR 文件的“META-INF”目錄中。
file 中的字符應來自“a-zA-Z0-9_-”。也就是說,只允許字母、數字、下劃線和連字符。註意: .SF 和 .DSA 文件名中小寫字母將被轉換為大寫字母。
如果命令行中沒有
-sigfile
選項,則 .SF 和 .DSA 文件的基本文件名將是命令行中指定的別名的前 8 個字符,並全部被轉換為大寫。如果別名少於 8 個字符,將使用整個別名。如果別名中包含簽名文件名所不允許的字符,則形成文件名時這樣的字符將被轉換為下劃線 ("_")。-signedjar
file- 指定用於已簽名的 JAR 文件的名稱。
如果命令行中沒有指定名稱,將使用輸入的 JAR 文件名(要簽名的 JAR 文件名);換句話說,該文件將被簽名 JAR 文件覆蓋。
-verify
- 如果它出現在命令行中,則指定的 JAR 文件將被校驗,而不是簽名。如果校驗成功,將顯示“jar verified”。如果試圖校驗未簽名的 JAR 文件,或校驗被不支持的算法(例如未安裝 RSA 提供者時使用的 RSA)簽名的 JAR 文件,則將有如下顯示: "jar is unsigned. (signatures missing or not parsable)"
可以校驗使用 jarsigner 或 JDK 1.1 javakey 工具或共用二者簽名的 JAR 文件。
有關校驗的詳細信息,參見 JAR 文件校驗。
-certs
- 如果它與
-verify
和-verbose
選項一起出現在命令行中,則輸出將包括 JAR 文件的每個簽名人的證書信息。該信息包括
- 驗證簽名人公鑰的證書的類型名(保存在 .DSA 文件中)
- 如果該證書是 X.509 證書(更準確地說是
java.security.cert.X509Certificate
的實例): 簽名人的特征名密鑰倉庫也被檢查。如果命令行中沒有指定密鑰倉庫值,缺省密鑰倉庫文件(如果有)將被檢查。如果簽名人的公鑰證書與密鑰倉庫中的項匹配,則還將顯示下列信息:
- 該簽名人的密鑰倉庫項的別名,在圓括號中。如果該簽名人實際上來自於 JDK 1.1 身份數據庫而不是密鑰倉庫,則別名將顯示在方括號而不是圓括號中。
-verbose
- 如果它出現在命令行中,則代表“verbose”模式,它使 jarsigner 在 JAR 簽名或校驗過程中輸出額外信息。
-internalsf
- 過去,JAR 文件被簽名時產生的 .DSA(簽名塊)文件包含一個同時產生的 .SF 文件(簽名文件)的完整編碼副本。這種做法已被更改。為了減小輸出 JAR 文件的整個大小,缺省情況下 .DSA 文件不再包含 .SF 文件的副本。但是如果
-internalsf
出現在命令行中,將采用舊的做法。該選項主要在測試時有用;實際上不應使用它,因為這樣將消除有用的優化。-sectionsonly
- 如果它出現在命令行中,則 JAR 文件被簽名時生成的 .SF 文件(簽名文件)將不包括含有整個清單文件的散列的頭。它僅包含 與 JAR 中每個單獨的源文件相關的信息和散列,如簽名 (.SF) 文件所述。
缺省情況下,該頭將作為一種優化手段添加。只要該頭存在,則無論何時 JAR 被校驗,都將首先檢查該頭中的散列是否真正與整個清單文件的散列匹配。如果匹配,校驗將進行下一步。如果不匹配,則有必要執行一個次優的校驗,檢查 .SF 文件中每個源文件信息部分中的散列是否等於清單文件中相應部分的散列。
有關的詳細信息,參見 JAR 文件校驗。
該選項主要在測試時有用;實際上不應使用它,因為這樣將消除有用的優化。
-J
javaoption- 將指定的 javaoption 串直接傳遞到 Java 解釋器。((jarsigner 實際上是解釋器的一個 “wrapper”)。該選項不應含有任何空格。它有助於調整執行環境或內存使用。要獲得可用的解釋器選項的清單,可在命令行鍵入
java -h
或java -X
。
程序例子
簽名 JAR 文件
假設您有一個 JAR 文件名為“bundle.jar”並且希望使用“working”目錄中名為“mystore”的密鑰倉庫裏別名為“Jane”的用戶的私鑰進行簽名。假設密鑰倉庫口令是“myspass”且 jane 的私鑰口令是“j638klm”。您可以使用下列命令為該 JAR 文件簽名並將簽了名的 JAR 文件命名為“sbundle.jar”:
jarsigner -keystore /working/mystore -storepass myspass -keypass j638klm -signedjar sbundle.jar bundle.jar jane註意上面的命令中沒有指定
-sigfile
,因此所產生的要放入已簽名 JAR 文件的 .SF 和 .DSA 文件將采用基於別名的缺省名。也就是說,它們將被命名為JANE.SF
和JANE.DSA
。如果要根據提示輸入倉庫口令和私鑰口令,可以將上面的命令縮短為
jarsigner -keystore /working/mystore -signedjar sbundle.jar bundle.jar jane如果要使用的是缺省密鑰倉庫(它在宿主目錄中,名為“.keystore”),則不必指定密鑰倉庫,如下:
jarsigner -signedjar sbundle.jar bundle.jar jane最後,如果要使已簽名的 JAR 文件簡單地覆蓋輸入的 JAR 文件 (
bundle.jar
),則不必指定-signedjar
選項:jarsigner bundle.jar jane校驗已簽名的 JAR 文件
要校驗已簽名的 JAR 文件,(也就是說驗證簽名合法且 JAR 文件未被更改過)請使用如下命令:
jarsigner -verify sbundle.jar如果校驗成功,將顯示
jar verified.。否則將出現錯誤信息。
如果使用
-verbose
選項則將獲得更多的信息。下面是用-verbose
選項使用 jarsigner 的例子及其輸出:jarsigner -verify -verbose sbundle.jar 198 Fri Sep 26 16:14:06 PDT 1997 META-INF/MANIFEST.MF 199 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.SF 1013 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.DSA smk 2752 Fri Sep 26 16:12:30 PDT 1997 AclEx.class smk 849 Fri Sep 26 16:12:46 PDT 1997 test.class s = signature was verified m = entry is listed in manifest k = at least one certificate was found in keystore jar verified.校驗證書信息
如果校驗時與
-verify
和-verbose
選項一起指定了-certs
選項,則輸出將包括該 JAR 文件的每個簽名人的證書信息,其中包括證書類型、簽名人的特征名信息(如果是 X.509 證書),以及括在圓括號中的簽名人的密鑰倉庫別名(如果 JAR 文件中的公鑰證書與密鑰倉庫項中的證書匹配。例如:jarsigner -keystore /working/mystore -verify -verbose -certs myTest.jar 198 Fri Sep 26 16:14:06 PDT 1997 META-INF/MANIFEST.MF 199 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.SF 1013 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.DSA 208 Fri Sep 26 16:23:30 PDT 1997 META-INF/JAVATEST.SF 1087 Fri Sep 26 16:23:30 PDT 1997 META-INF/JAVATEST.DSA smk 2752 Fri Sep 26 16:12:30 PDT 1997 Tst.class X.509, CN=Test Group, OU=Java Software, O=Sun Microsystems, L=CUP, S=CA, C=US (javatest) X.509, CN=Jane Smith, OU=Java Software, O=Sun, L=cup, S=ca, C=us (jane) s = signature was verified m = entry is listed in manifest k = at least one certificate was found in keystore jar verified.如果簽名人的證書不是 X.509 證書,將沒有特征名信息。這種情況下,僅顯示證書類型和別名。例如,如果該證書為 PGP 證書,且別名為“bob”,則將顯示
PGP, (bob)校驗包含身份數據庫簽名人的 JAR 文件
如果 JAR 文件已用 JDK 1.1 javakey 工具簽名,因此簽名人是身份數據庫中的別名,則校驗輸出將包括一個“i”符號。如果 JAR 文件同時被身份數據庫中的別名和密鑰倉庫中的別名二者簽名,則將出現“k”和“i”。
當使用了
-certs
選項時,任何身份數據庫別名都將顯示在方括號中,而不是顯示在用於密鑰倉庫別名的圓括號中。例如:jarsigner -keystore /working/mystore -verify -verbose -certs writeFile.jar 198 Fri Sep 26 16:14:06 PDT 1997 META-INF/MANIFEST.MF 199 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.SF 1013 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.DSA 199 Fri Sep 27 12:22:30 PDT 1997 META-INF/DUKE.SF 1013 Fri Sep 27 12:22:30 PDT 1997 META-INF/DUKE.DSA smki 2752 Fri Sep 26 16:12:30 PDT 1997 writeFile.html X.509, CN=Jane Smith, OU=Java Software, O=Sun, L=cup, S=ca, C=us (jane) X.509, CN=Duke, OU=Java Software, O=Sun, L=cup, S=ca, C=us [duke] s = signature was verified m = entry is listed in manifest k = at least one certificate was found in keystore i = at least one certificate was found in identity scope jar verified.註意別名“duke”在方括號中,這說明它是身份數據庫別名,不是密鑰倉庫別名。
使用keytool生成公鑰、私鑰、證書並且讀取出來,使用私鑰簽名jar並驗證(轉)