2011-10-13 31 views
19

有沒有一種方法來取消簽名java jar文件?我在我的開發環境中嘗試使用一些簽名的jar,但是我得到了安全性異常,所以我想要對這些jar進行取消簽名,並且稍後可以在準備部署時簽署它們。如何取出一個罐子?

+0

您檢查了例如這:https://www.chemaxon.com/forum/ftopic65.html? – home

+0

有問題的瓶子從哪裏來?爲什麼你不能登錄你的開發環境? –

+1

顯然有一種方法。 ;-)但是,爲什麼不在開發過程中避免簽名JAR呢?如果你是控制JAR的人,這應該是你的權力;如果你不是JAR控制者,那麼你可能並不打算篡改它(或者原始開發者不會簽署它)。 –

回答

25

我不知道答案,但這裏是我會做什麼:

  1. 解壓有問題的jar文件或文件(罐子只是拉鍊)
  2. 看在META-INF目錄對於那些不是MANIFEST-MF的東西。
  3. 刪除那些東西。
  4. 打開MANIFEST-MF並刪除看起來像簽名相關的東西。
  5. rejar。
+0

這幾乎是你所做的。 – Paul

+1

完美答覆.. – Sid

+0

這就是我不得不做的,我從來沒有找到一種方法來刪除沒有解壓縮的簽名。但是,如果這個答案更具體地涉及步驟2,3,4,那麼我想,因爲有時候除了MANIFEST-MF以外還有其他的東西是必需的而不是簽名相關的。像APPLICATION.JNLP一樣! – Jason

0

如果罐子是由您開發的,那麼它們可以被信任,您可能不需要簽名。但是,如果您從外部獲得它們,則應該在使用它之前調查安全異常的原因。

+0

我正在做同樣的事情。我正在作爲承包商修改大型應用的小部分,他們的構建服務器會自動進行簽名。我需要開發並重寫提供的jar中的類進行測試。他們持有證書親愛的(這是一家銀行),所以我必須根據他們的條款來處理他們構建的輸出。 – peterk

+0

這些罐子是我正在開發的罐子,我不需要簽署它們,直到我部署爲止......但偶爾我想在我的開發環境中使用生產罐子或使用我已經簽名的罐子部署。在這種情況下,解壓所有罐子,刪除簽名並重新壓縮是一件痛苦的事情。我已經重新構建了我的構建系統,所以它不再經常出現。我的構建系統現在將未簽名的jar和簽名jar保存在build目錄中,這樣我就可以在閒暇時切換它們。 – Jason

1

我成功地驗證了DwB的答案,並做了小的修改:由於Is there a quick way to delete a file from a Jar/war without having to extract the jar and recreate it?指出,僅僅從jar工具中刪除是不可能的。我只需要對專有構建腳本進行一些小修改,但我不想整個jar。

我意識到unsign是可能的,當我只做重要的.RSA文件零大小。這隻能jar u命令來完成:

cd %JAR_DIR% 
jar xvf myapp.jar META-INF/MYAPP.RSA 
type nul > META-INF/MYAPP.RSA 
jar uvf myapp.jar META-INF/MYAPP.RSA 
rmdir /S/Q META-INF 
+0

我沒有時間測試此解決方案,但看起來很不錯。 – Jason

+0

從jarsigner工具文檔中,它執行以下操作: 1).SF文件(簽名文件) 2)基於所用算法(例如.RSA,.DSA等)的簽名塊文件3)修改(或創建如果它還不存在)MANIFEST.MF文件 摘要:只刪除前2個文件並刪除MANIFEST.MF文件,或打開它並刪除列出的每個文件的所有哈希) 。 否則,您將刪除其他需要的文件(即屬性文件等)。 參考文獻: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html – atom88

8

要從JAR文件中刪除簽名,從中取出META-INF目錄。一個JAR文件是一個zip文件,以便在Linux上,你可以這樣做:

zip -d file.jar 'META-INF/*.SF' 'META-INF/*.RSA' 

如果你有很多的jar文件unsign,在當前目錄及以下每個jar文件下面的命令執行此:

find . -name '*.jar' -exec zip -d '{}' 'META-INF/*.SF' 'META-INF/*.RSA' ';' 
+0

我想你還必須編輯'META-INF/MANIFEST.MF'你不是嗎? ?或者你可以將簽名留在該文件中並讓該jar仍然可以作爲無符號工作? – Jason

+0

它似乎沒有問題,只是通過刪除文件。 – martinhans

+0

感謝您的支持,我投了票。我沒有爲自己驗證過這一點,我仍然懷疑它在所有情況下都能正常工作。我希望你不介意我的懷疑態度:-)解決方案很好,對我的問題,如果它適用於我的情況,這將是一個更令人滿意的答案...每當我再次遇到這個問題時,我會測試它並更新此答案。 – Jason

4

我看到一個答案已經被接受,但我認爲這可能是有用的反正:

我已經熟了的東西(部分來自其他職位)自動執行任務。
附帶沒有任何擔保,但它適用於我:)
複製Jar文件,同時刪除簽名信息。
注意,MANIFEST只剩下MAIN部分!

使用javac JarUnsigner.java創建.class文件
使用java -cp <class dir> JarUnsigner <inJar> <outJar>

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.Enumeration; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipFile; 
import java.util.zip.ZipOutputStream; 

public class JarUnsigner { 

    private static final String MANIFEST = "META-INF/MANIFEST.MF"; 

    public static void main(String[] args){ 

    if (args.length!=2){ 
     System.out.println("Arguments: <infile.jar> <outfile.jar>"); 
     System.exit(1); 
    } 
    String infile = args[0]; 
    String outfile = args[1]; 
    if ((new File(outfile)).exists()){ 
     System.out.println("Output file already exists:" + outfile); 
     System.exit(1); 
    } 
    try{ 
     ZipFile zipFile = new ZipFile(infile); 
     final ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outfile)); 
     for (Enumeration e = zipFile.entries(); e.hasMoreElements();) { 
     ZipEntry entryIn = (ZipEntry) e.nextElement(); 

     if (! exclude_file(entryIn.getName())) { 

      /* copy the entry as-is */ 
      zos.putNextEntry(new ZipEntry(entryIn.getName())); 
      InputStream is = zipFile.getInputStream(entryIn); 
      byte[] buf = new byte[1024]; 
      int len; 
      while ((len = (is.read(buf))) > 0) { 
      zos.write(buf, 0, len); 
      } 
      zos.closeEntry(); 

     } else { 

      if (MANIFEST.equals(entryIn.getName())){ 
      /* if MANIFEST, adjust the entry */ 
      zos.putNextEntry(new ZipEntry(MANIFEST)); 

      // manifest entries until first empty line. i.e. the 'MainAttributes' section 
      // (this method is used so to keep the formatting exactly the same) 
      InputStream mIS = zipFile.getInputStream(entryIn); 
      BufferedReader in = new BufferedReader(new InputStreamReader(mIS)); 
      String line = in.readLine(); 
      byte[] mNL = "\n".getBytes("UTF-8"); 
      while(line != null && !line.trim().isEmpty()) { 
       zos.write(line.getBytes("UTF-8")); 
       zos.write(mNL); 
       line = in.readLine(); 
      } 
      zos.write(mNL); 
      zos.closeEntry(); 

      }else{ 
      /* else: Leave out the Signature files */ 
      } 

     } 

     } 
     zos.close(); 
     System.out.println("Successfully unsigned " + outfile); 

    }catch(IOException ex){ 
     System.err.println("Error for file: " + infile); 
     ex.printStackTrace(); 
     System.exit(1); 
    } 
    } 

    /** 
    * Exclude .SF signature file 
    * Exclude .RSA and DSA (signed version of .SF file) 
    * Exclude SIG- files (unknown sign types for signed .SF file) 
    * Exclude Manifest file 
    * @param filename 
    * @return 
    */ 
    public static boolean exclude_file(String filename){ 
    return filename.equals("META-INF/MANIFEST.MF") || 
      filename.startsWith("META-INF/SIG-") || 
      filename.startsWith("META-INF/") && (filename.endsWith(".SF") || filename.endsWith(".RSA") || filename.endsWith(".DSA")); 
    } 

} 

在ANT使用unsign一堆罐子如下:

<apply executable="java" dest="${output-dir}"> 
    <arg value="-cp" /> 
    <arg value="${dev-dir}" /> 
    <arg value="JarUnsigner" /> 
    <srcfile/> 
    <targetfile/> 
    <fileset dir="${input-dir}" includes="*.jar"/> 
    <mapper type="glob" from="*.jar" to="*.jar"/> <!-- uses "dest"--> 
</apply> 
+0

好主意!我沒有對它進行測試,但我很樂意提請注意,看看是否有其他人有時間來測試此解決方案。這正是我想要的。 – Jason

+0

謝謝。我們已經使用了很長一段時間了。很好地工作 – Houtman

0

如果你看一下jarsigner工具和它做了什麼,它會產生3件事: 1).SF文件(簽名文件) 2)基於使用的算法(例如.RSA,.DSA等)的簽名塊文件)修改或創建MANIFEST。MF文件

摘要: 要「取消簽名jar」只需刪除前2個文件(.sf和.dsa/rsa FILE)。 要麼刪除MANIFEST.MF文件,要麼將其打開並刪除列出的每個.hes和列出的其他文件的所有哈希)。因此,如果您刪除META-INF目錄中的所有內容,則可能會刪除可能需要的其他jar資源(即屬性文件等)。這種刪除「看上去簽名相關」的所有內容的「霰彈槍方法」是有害的,並且不遵循以下原則:第一,不傷害(對你的.jar)。

在這裏看到: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html

https://docs.oracle.com/javase/tutorial/deployment/jar/intro.html

理解簽名和驗證

」 ......當您註冊一個JAR文件你的公鑰被放置在歸檔中連同相關的證書,以便它很容易供任何想要驗證您的簽名的人使用。... 摘要和簽名文件

當您簽署JAR文件時,歸檔文件中的每個文件都會在歸檔文件清單中獲得一個摘要條目。以下是對這樣的記錄是這樣一個例子:

名稱:測試/班/ ClassOne.class SHA1-摘要:TD1GZt8G11dXY2p4olSZPc5Rj64 =

當一個JAR文件進行簽名,將自動生成一個簽名文件和放置在JAR文件的META-INF目錄中,該目錄包含存檔清單的相同目錄。簽名文件具有擴展名爲.SF的文件名。

簽名塊文件

除了簽名文件,當一個JAR文件進行簽名的簽名塊文件被自動放置在META-INF目錄下。與清單文件或簽名文件不同,簽名塊文件不可讀。

簽名塊文件中包含覈查必不可少兩個元素:

爲與生成JAR文件的數字簽名,簽名者的私鑰 由任何人想要使用含有簽名者的公鑰證書驗證已簽名的JAR文件 簽名塊文件名通常會有一個.DSA擴展名,指明它們是由默認數字簽名算法創建的。如果使用與某些其他標準算法相關的密鑰進行簽名,則可以使用其他文件擴展名。

相關問題