jdk工具keytool和jarsigner協助Part1(jdk keytool&jarsigner tool manual)
0.背景
keytool是JDK中包含的密鑰和認證的管理工具。用於管理私密金鑰及其相關的X.509憑證鏈結的keystore。X.509憑證鏈結用於認證對應的公開金鑰,keystore類似於一個資料庫。同時keytool還用於管理信任實體發布的認證。
jarsigner是JDK中包含的用於JAR檔案簽名和驗證的工具。為Java檔案檔案(JAR)產生簽名,以及對已簽名的jar檔案的進行校正。
1.工具Location
這兩個工具都位於$JAVA_HOME/bin目錄下,其中$JAVA_HOME是JDK的安裝目錄。
這兩個工具都是在命令列中使用,在命令列視窗輸入:
keytool和jarsigner即可擷取命令的工具的使用方法。
2.keytool工具簡介
keytool是密鑰和認證管理工具。使用者使用該工具來管理公開金鑰/私密金鑰對以及關聯的認證,通過使用數位簽章,可以應用於自簽名或者資料完整性/認證服務,使用者還可以使用該工具來緩衝夥伴的公開金鑰(以認證的形式)。
認證是由實體進行數位簽章的聲明,這裡實體可以是個人或者企業。一旦資料被數位簽章,那麼可以通過檢查資料完整性和可靠性來校正簽名。完整性的意思是資料沒有被修改/篡改過,可靠性是指資料確實是來自於宣布擁有資料的人。
keytool將密鑰和憑證存放區在所謂的keystore中,預設的keystore實現是將keystore作為一個檔案。它使用密碼來保護私密金鑰。
jarsigner工具使用keystore中的資訊來產生或者校正JAR檔案的數位簽章。jarsigner使用附帶在JAR檔案中的認證來校正數位簽章(認證包含在JAR檔案的簽名塊檔案中),然後檢查認證的公開金鑰是否是可信賴的,也就是說是否包含在指定的keystore中。
3.keystore實體
在keystore中包含了兩種不同類型的實體:
i.密鑰實體 - 包含了非常敏感的加密金鑰資訊,以受保護的形式進行儲存,以防止未授權訪問。典型的這種類型的實體儲存一個secret key,或者通過憑證鏈結串連的public key對應的private key。keytool和jarsigner工具只處理後一種類型的實體,即private key和關聯的憑證鏈結。
ii.信任的認證實體 - 包含了其他組織的public key certificate。之所以成為信任的認證,是因為keystore的所有者信任認證中的public key確實屬於由認證的subject標識的個體。認證的簽發者通過簽發認證為此擔保。
4.keystore別名(aliases)
通過使用唯一的別名可以訪問keystore中的實體。別名是不區分大小寫。
當使用-genkey命令產生key pair(public & private key),或者使用-import命令來添加認證或者憑證鏈結到信任認證列表時來指定的。keytool命令必須使用這個別名來引用這個實體。
例如,使用duke作為別名來產生新的public/private key pair,並將public key封裝到一個自簽名的認證中。命令如下:
keytool -genkey -alias duke -keypass dukekeypasswd
這裡使用了初始密碼,可以通過下面的命令進行密碼的修改:
keytool -keypasswd -alias duke -keypass dukekeypasswd -new newpass
上面的命令將密碼由dukekeypasswd修改為newpass。
5.keystore儲存位置
每個keytool命令都包含了一個-keystore選項,用於指定持久化keystore檔案的名字和位置。預設的keystore儲存在使用者主目錄(user.home系統屬性)中,名為.keystore。假設使用者名稱為uName,那麼user.home屬性的值預設為:
多使用者Windows NT/2000系統:C:/Winnt/Profiles/uName
多使用者Windows 95/98/XP系統:C:/WINDOWS/Profiles/uName
單使用者Windows 95/98/XP系統:C:/WINDOWS
註:-keystore選項指定的input stream是作為參數傳遞到KeyStore.load方法中,如果NONE被指定,那麼null stream被傳送到KeyStore.load方法。只有當KeyStore不是基於檔案的時候,比方說,位於硬體中,才會指定為NONE。
6.keystore產生
當使用-genkey,-import,-identitydb命令時,都會建立一個keystore(當keystore不存在時)。
再具體的說,當在-keystore選項中指定的keystore檔案不存在時,keystore會被建立。
如果不指定-keystore選項,會使用預設的keystore檔案名稱,即user.home/.keystore,如果該檔案不存在,那麼建立該檔案。
7.keystore實現
java.security.KeyStore類提供了定義良好的介面用於訪問和修改keystore中的資訊。可能還會存在多種不同的具體實現,對應不同類型的keystore。
目前,keytool和jarsigner以及基於GUI的Policy Tool都使用keystore實現。既然KeyStore是公用的類,JDK使用者可以使用它來編寫更多的安全應用。
Sun公司提供了一個內建的預設的實現,將keystore作為一個檔案來實現,使用的keystore類型為"JKS"。通過密碼來保護private key,同時通過密碼(通常和保護private key的密碼不同)來保護整個keystore的完整性。
keystore的實現是基於provider的。再進一步的說,KeyStore提供的應用程式介面是以SPI(Service Provider Interface)的方式來實現的。也就是說,在java.security package中,還包含了一個對應的keystoreSpi抽象類別,定義了provider必須實現的SPI。因此,要提供keystore的實現,就必須實現provider並提供KeystoreSpi子類的實現。
應用程式可以選擇不同類型的keystore實現,通過使用KeyStore類的getInstanceFactory 方法。keystore類型定義了keystore資訊的儲存和資料格式,以及用於保護private key的演算法。不同類型的Keystore實現是不相容的。
keytool工具可以工作與任意基於檔案的keystore實現。而jarsigner和policytool則可以從任意位置(可以通過URL指定的)來讀取keystore。
對於keystore和jarsigner,可以通過-storetype命令列選項來指定keystore類型,對於Policy Tool,可以通過Change Keystore命令來制定keystore類型。
如果不顯示的指定keystore的類型,那麼工具會根據security屬性檔案中的keystore.type的值來選擇keystore的實現。security屬性檔案叫做java.security,位於JDK security屬性目錄中,JAVA_HOME/lib/security,JAVA_HOME表示java運行時環境即JRE的目錄。
擷取keystore.type值後,檢查當前安裝的所有provider,直到發現該類型的keystore實現。然後使用provider提供的keystore實現。
KeyStore類定義了一個靜態方法,叫做getDefaultType,應用程式以及applets可以使用該方法來擷取keystore.type屬性的值。下面的方法建立了一個預設keystore類型的KeyStore執行個體。
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
預設的keystore類型是"jks",這是Sun公司提供的預設實現。通過security屬性檔案指定:
keystore.type=jks
可以通過修改security屬性檔案的該值來修改預設的keystore實現。例如:
keystore.type=pkcs12
註:類型不區分大小寫,PKCS12等價於pkcs12。
8.支援的演算法及密鑰大小
keytool允許使用者指定任意已經註冊的Data Encryption Serviceprovider提供的key pair產生器以及簽名演算法。也就是說,keyalg和slgalg選項必須被provider實現所支援。預設的key pair產生器演算法是DSA,簽名演算法是從底層的private key的演算法繼承來的:如果底層private key的類型是DSA,那麼預設的簽名演算法就是SHA1withDSA,如果底層private key的類型是RSA,那麼預設的簽名演算法就是MD5withRSA。
當成生DSA key pair時,key的大小必須在512 - 1024之間,並且必須是64的整數倍。所有演算法的預設的key大小為1024。
9.認證
認證,通常也叫密鑰憑證,是由實體進行數位簽章的聲明。認證的一些術語說明如下:
公開金鑰:與特定實體相關聯的數字,並且公開給與其有互動的外部實體。公開金鑰用於驗證簽名。
數位簽章:如果資料被數位簽章,那麼它將作為實體的身份被儲存,簽名可以證明實體識別資料。通過使用實體的私密金鑰來進行簽名,可以確保資料不可偽造。
身份標識:用於確定實體。在某些系統中,身份就是公開金鑰,在一些其他系統中,可以是Unix的UID,Email地址,X.509 DN。
簽名:簽名是使用實體的私密金鑰來對一些資料進行計算。當signer(簽名者)是一個認證時,也被叫做issuer(發行者)。
私密金鑰:只提供給特定實體的數字,也就是說,它應該是保密的。在所有的公開金鑰加密系統中,私密金鑰和公開金鑰是成對存在的。在典型的PKCS(public key crypto systems)系統中,例如DSA,一個私密金鑰對應唯一的一個公開金鑰,私密金鑰用於計算簽名。
實體:實體可以是個人,組織,程式,電腦,企業,銀行以及在某種程度上使用者信任的任何事物。
基本上說,公開金鑰加密需要訪問使用者的公開金鑰。在大規模的網路環境下,很難保證通訊實體間已經建立了重要關係或者一個可信賴的存放庫儲存了所有用過的公開金鑰。這種情況下,認證作為一個解決方案來解決公開金鑰發布的問題。現在,認證中心(Certification Authority,i.e CA)可以扮演可信賴的第三方。
使用keytool可以顯示,匯入,到處認證。同樣,也可以產生自簽名的認證。
keytool目前可以處理X.509認證。
10.X.509認證
X.509標準定義了認證中可以包含哪些資訊,並描述了資料的格式,所有的X.509認證都包含除簽名外的以下的資料:
版本:標識認證的X.509標準的版本,用於確定哪些資訊是可以被指定的。截至到目前,已經定義了三種版本。keytool可以匯入和到處v1,v2和v3認證,可以產生v1認證。
序號:建立認證的實體需要給認證分配一個序號來標識它發行的認證。這個資訊在很多地方使用,例如如果一個認證被廢棄了,那麼它的序號將被添加到認證廢棄列表中(CRL)。
簽名演算法標識:標識CA簽署憑證時使用的演算法。
發行者名稱:簽名該認證的實體的X.500 DN。這通常是CA。
有效期間:每個認證都有一個有效期間。由起始時間和結束時間來確定。
主題名:認證標識的公開金鑰所屬的實體的名字。名稱使用X.500標準。例如:
CN=Java Duke, OU=Java Software Division, O=Sun Microsystems Inc, C=US
主題公開金鑰資訊:實體的公開金鑰,以及演算法標識。
其中v1是最普遍的。v2還沒有廣泛使用。v3提供了對擴充的支援。
11.X.500 DN
X.500 Distinguished Names(DN)用於標識實體,例如X.509認證的subject和issuer欄位的資訊。keytoo支援以下的子部分:
commonName:人的名字
organizationUnit:規模較小的組織名,比如部門。
organizationName:規模較大的組織名。
localityName:地區名。
stateName:州或者省的名字。
country:兩個字元的國家代碼。
當提供distinguished name時,使用-dname選項,字串的格式不許如下所示:
CN=cName, OU=orgUnit, O=org, L=city, S=state, C=countryCode
例如:
keytool -genkey -dname "CN=Mark Smith, OU=JavaSoft, O=Sun, L=Cupertino, S=California, C=US" -alias mark
必須按照指定的順序指定各個部分的值,但是並不是所有的部分都是必須的。如果某一部分的值包含逗號,那麼需要使用/進行轉義。例如:
cn=peter schuster, o=Sun Microsystems/, Inc., o=sun, c=us
12.Internet RFC1421認證編碼通訊協定
認證常常以可以列印的編碼格式進行儲存。這個編碼格式是由Internet RFC 1421標準來定義的,用來取代二進位格式。這個認證格式,即Base64編碼,方便了匯出認證給其他應用程式使用。
通過-import或者-printcert命令來讀取時,可以使用這種格式或者二進位格式。
-export命令預設以二進位格式輸出認證,但是會以可列印的編碼格式,如果指定-rfc選項的話。
-list命令預設列印認證的MD5指印。如果-v選項被指定的話,認證可以以可讀的格式列印,如果-rfc選項被指定的話,認證以printable編碼格式輸出。
可列印編碼格式的認證以
-----BEGIN CERTIFICATE-----
開頭,以
-----END CERTIFICATE-----
結尾。
13.憑證鏈結
keytool可以建立和管理keystore的key實體,每個key實體可以包含一個私密金鑰和一個關聯的憑證鏈結。憑證鏈結中的第一個認證包含對應私密金鑰的公開金鑰。
當keys被第一次產生時,憑證鏈結開始包含單一的元素,即自我簽署憑證。自我簽署憑證是指issuer和subject是同一個實體的認證。每當-genkey被調用時,都會產生一個新的public/private key pair,並將public key封裝進自我簽署憑證。
之後,當使用-certreq命令產生認證簽章要求並將其發送給CA,CA的反應被匯入(-import),自簽名的認證被憑證鏈結取代,在憑證鏈結的底部的是CA認證並簽發的認證,接下來的是認證CA公開金鑰的認證。
在很多情況下,這是一個自我簽署憑證(即CA對自己的公開金鑰進行自簽名得到的認證),並作為憑證鏈結中最後的認證。在其他情況,CA會發揮一個憑證鏈結。在這種情況下,憑證鏈結的底部還是相同的,但是第二個認證是一個被不同CA認證的認證,認證CA的公開金鑰。以此類推,最後到一個自簽名的根憑證。
很多CA值返回傳行的認證,而不支援鏈,特別是沒有中間CA的時候。這種情況下,憑證鏈結必須從keystore中已經包含的受信任的認證開始建立。
另外一種反應格式(由PKCS#7標準定義)是包含憑證鏈結。keytool可以處理這兩種反應格式。
14.匯入認證
可以使用-import選項來從檔案中匯入認證。
keytool -import -alias joe -file jcertfile.cer
上面的命令匯入jcertfile.cer中的認證,並將其儲存在keystore中,由別名joe來進行標識。
匯入認證主要有兩個原因:
a.將其添加到信任的認證列表中
b.將CA返回來的認證匯入
到底想匯入哪種取決於-alias選項的值:
如果alias指向一個key實體,那麼keytool假定在匯入CA返回的認證。keytool檢查認證中的public key是否與keystore中儲存的實體(由alias指定的)的public key一致,如果不一致,那麼退出。
如果alias沒有指向任何key實體,那麼keytool假定在向keystore中添加信賴的認證實體。在這種情況下,alias不應該存在於keystore中。如果alias已經存在,那麼keytool輸出一個錯誤。
在匯入信賴的認證前,要檢查認證。首先查看一下認證,使用-printcert認證或者不帶-noprompt選項的-import命令。
15.匯出認證
使用-export命令來匯出認證。
keytool -export -alias jane -file janecertfile.cer
16.顯示認證
使用-list命令來列印出keystore實體的內容:
keytool -list -alias joe
如果不指定-alias的話,那麼將會列印整個keystore。
可以使用-printcert命令來顯示檔案中儲存的認證的內容:
keytool -printcert -file certfile.cer
17.產生自我簽署憑證
自我簽署憑證是指issuer和subject相同的認證。每次使用-genkey命令的時候,都會產生新的public/private key pair,同時將public key封裝進自我簽署憑證。
有時可能需要產生新的自我簽署憑證,例如可能希望使用相同的key pair在不同的身份下。例如可以修改部門。 此時可以:
a.拷貝(clone)原始的key entry。請參考-keyclone。
b.為cloned的實體產生新的自簽名的認證,使用新的DN。
c.為cloned的實體產生CSR,並將反應的認證或者憑證鏈結匯入。請參考-certreq和-import命令。
d.刪除原始的實體。請參考-delete
可以使用-selfcert命令產生自簽名的認證:
keytool -selfcert -alias dukeNew -keypass b92kqmp -dname "cn=Duke Smith, ou=Purchasing, o=BlueSoft, c=US"
18.命令及選項注意事項
所有的命令和選項名都以-做首碼。
每個命令的選項不區分順序。
所有沒有斜體的或者沒有在大括弧或者中括弧中的項目是必須原原本本輸出的。
大括弧包含的選項表示如果該選項沒有被指定,那麼採用預設的值。大括弧還用作-v,-rfc和-J選項,只用來表示這些選項是否出現在命令列上。即表示如果它們不出現,也沒有預設值。
中括弧包含的選項表示,如果使用者不指定值,那麼將會在命令列提示使用者輸入。
斜體表示的項目代表必須提供的實際值。
選項的值必須使用雙引號,如果包含空格的話
下面是一些常見的預設值:
-alias "mykey"
-keyalg "DSA"
-keysize 1024
-validity 90
-keystore $user.home/.keystore
-file stdin/stdout
下面是大多數命令都會使用的通用選項:
-v選項適用於除-help之外的所有命令,表示verbose模式,即輸出詳細資料。
-J選項適用於任何命令,如果出現的話,javaoption會直接傳送到Java解譯器(keytool實際上就是解譯器的封裝器)。該選項不能包含任何空格,主要用於設定執行環境以及記憶體使用量,可用的解譯器選項可以通過輸入java -h或者java -X來查看。
-storetype :設定keystore的類型。
-keystore :keystore檔案的儲存位置
-storepass:keystore檔案的密碼,密碼長度至少為6個字元,當訪問keystore檔案的內容時,必須提供該密碼。如果不指定該選項,命令列會提示使用者輸入。
-provider :指定Data Encryption Serviceprovider的master class檔案的名字。
19.命令詳解
-certreq [-v] [-alias <alias>] [-sigalg <sigalg>]
[-file <csr_file>] [-keypass <keypass>]
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
產生認證簽章要求(CSR),使用PKCS#10格式。CSR是用來發送給CA,CA對認證簽章要求認證,並返回認證或者憑證鏈結,用來替換keystore中既存的憑證鏈結(初始狀態是自簽名的認證)。
alias關聯的private key和X.500 DN被用來建立PKCS#10認證請求。
-delete [-v] -alias <alias>
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
-export [-v] [-rfc] [-alias <alias>] [-file <cert_file>]
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
從keystore中匯出由alias指定的認證,並儲存為cert_file。預設情況下認證以二進位編碼格式匯出,可以通過指定rfc選項來以可列印的編碼格式匯出。
-genkey [-v] [-alias <alias>] [-keyalg <keyalg>]
[-keysize <keysize>] [-sigalg <sigalg>]
[-dname <dname>] [-validity <valDays>]
[-keypass <keypass>] [-keystore <keystore>]
[-storepass <storepass>] [-storetype <storetype>]
[-provider <provider_class_name>] ...
產生key pair(public key機器關聯的private key),將public key封裝入X.509 v1自我簽署憑證,該憑證鏈結中只包含單一元素。這個憑證鏈結以及私密金鑰被儲存到一個新的keystore中,以alias標識。例如:
C:/j2sdk1.4.2_15/bin>keytool -genkey -alias valuptec -keyalg RSA -keysize 1024 -
sigalg SHA1withRSA -dname "CN=Example, O=Example, OU=Example, L=Example, S=Example,C=CH" -keypass p@ssword -validity
3650 -storetype jks -keystore "c:/example.keystore" -storepass p@ssword
-help
-identitydb [-v] [-file <idb_file>] [-keystore <keystore>]
[-storepass <storepass>] [-storetype <storetype>]
[-provider <provider_class_name>] ...
-import [-v] [-noprompt] [-trustcacerts] [-alias <alias>]
[-file <cert_file>] [-keypass <keypass>]
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
從cert_file中讀取認證或者憑證鏈結(當以PKCS#7格式提供時),並將其儲存到keystore中,以alias標識。keytool可以匯入X.501 v1,v2,v3認證,以及PKCS#7格式的憑證鏈結。被匯入的資料必須以二進位編碼格式或者可列印編碼格式提供。
當匯入新的受信任的認證時,alias必須不存在於keystore中。在將認證添加到keystore之前,keytool首先嘗試建立由認證到自我簽署憑證的鏈,使用已經存在於keystore中的受信任的認證。如果-trustcacerts選項被指定,附加的認證被認為是信任鏈結。即在一個名為cacerts的檔案上的認證。如果keytool無法建立由匯入認證到自我簽署憑證的信任路徑(從keystore或者cacerts檔案),認證的資訊被列印,提示使用者檢查資訊。
當匯入認證回複時,通過使用keystore中的信任認證對認證回複進行驗證,同時可以選擇使用cacerts檔案中的認證(指定-trustcacerts選項)。決定認證回複是否被信任的方法如下:
a.如果認證回複是X.509認證,那麼keytool嘗試建立從認證回複到自我簽署憑證的信任鏈結。如果無法建立信任鏈結,認證回複不被匯入。此時keytool不列印認證的內容。
b.如果認證回複是PKCS#7格式的憑證鏈結,首先對憑證鏈結排序(使用者認證在開始,自我簽署憑證在結尾),然後keytool嘗試使用cacerts keystore中的受信任的認證來匹配認證回複中的根憑證。如果沒有發現匹配的認證,根憑證的資訊被列印,提示使用者確認。使用者可以選擇取消匯入。如果-noprompt選項被指定,那麼不會與使用者互動。
註:cacerts認證檔案
一個名為cacerts的認證檔案位於security屬性目錄,java.home/lib/security,java.home標識java runtime environment目錄。
cacerts檔案表示包含了CA的系統範圍的keystore。系統管理員可以配置和管理這個檔案。
cacerts檔案的初密碼是changeit。
-keyclone [-v] [-alias <alias>] -dest <dest_alias>
[-keypass <keypass>] [-new <new_keypass>]
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
clone key。
-keypasswd [-v] [-alias <alias>]
[-keypass <old_keypass>] [-new <new_keypass>]
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
修改private key密碼。
-list [-v | -rfc] [-alias <alias>]
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
列舉keystore檔案中包含的認證資訊,例如:
C:/j2sdk1.4.2_15/jre/lib/security>c:/j2sdk1.4.2_15/bin/keytool.exe -list -alias
valuptec -keystore c:/valupshanghai.keystore -rfc
キーストアのパスワードを入力してください: pa55w@rd
別名: valuptec
作成日: 2009/03/17
エントリのタイプ: keyEntry
証明連鎖の長さ: 1
証明書[1]:
-----BEGIN CERTIFICATE-----
BASE64 ENCODING CERTIFICATE DATA
-----END CERTIFICATE-----
-printcert [-v] [-file <cert_file>]
列印認證資訊。
-selfcert [-v] [-alias <alias>] [-sigalg <sigalg>]
[-dname <dname>] [-validity <valDays>]
[-keypass <keypass>] [-keystore <keystore>]
[-storepass <storepass>] [-storetype <storetype>]
[-provider <provider_class_name>] ...
產生X.509 v1自我簽署憑證,使用包含private key和public key的keystore的資訊。如果dname在命令列提供,那麼用來作為認證的issuer和subject。
-storepasswd [-v] [-new <new_storepass>]
[-keystore <keystore>] [-storepass <storepass>]
[-storetype <storetype>] [-provider <provider_class_name>] ...
修改儲存密碼。
20總結
本文是介紹Java安全工具keytool&jarsigner文章的第一部分,主要介紹了安全相關的概念,例如實體,公開金鑰,私密金鑰,認證,簽名等,並簡要的介紹了keytool的使用方法。
關於jarsigner的介紹,請參考本文的第二部分。