2009-09-03 33 views
22

Tôi muốn ký một lọ bằng cách sử dụng jarsigner, sau đó xác minh nó bằng cách sử dụng ứng dụng Java không có ký hiệu jar như một phần của classpath của nó (tức là chỉ sử dụng vị trí hệ thống tập tin của lọ)Làm thế nào để xác minh một bình đã ký với jarsigner theo chương trình

Bây giờ vấn đề của tôi là lấy tệp chữ ký ra khỏi bình, có cách nào đơn giản để làm điều này không?

Tôi đã chơi với Inflater và Jar InputStreams không có may mắn.

Hoặc điều này có thể được thực hiện theo cách tốt hơn?

Cảm ơn

Trả lời

10

Các security Provider implementation guide phác thảo quá trình thẩm tra lọ. Mặc dù các hướng dẫn này dành cho nhà cung cấp dịch vụ mã hóa JCA để xác minh chính nó, chúng phải được áp dụng cho vấn đề của bạn.

Cụ thể, hãy kiểm tra phương thức verify(X509Certificate targetCert) trong mã mẫu, "MyJCE.java".

+1

Thay vì gợi ý mã, họ có thể cũng cung cấp một phương pháp verifyAllContent() ;-) – lapo

-2

Bạn có thể sử dụng ứng dụng jarsigner để thực hiện việc này. Trong ProcessBuilder (hoặc Runtime.exec), bạn có thể chạy lệnh với những lập luận

ProcessBulider pb = new ProcessBuilder("/usr/bin/jarsigner", "-verify", "-certs", f.getAbsolutePath()); 

và nếu contians đầu ra xác thì jar được ký

Process p = pb.start(); 
p.waitFor(); 
InputStream is = p.getInputStream(); 
InputStreamReader isr = new InputStreamReader(is); 
BufferedReader br = new BufferedReader(isr); 
String line; 
while ((line = br.readLine()) != null) 
{ 
if(line.contains("verified"); 
... 

có những thứ phức tạp hơn bạn có thể làm khi bạn có đầu ra của mã jarsigner.

+0

Ví dụ là nền tảng cụ thể và bổ sung công cụ jarsigner thường chỉ đi kèm với JDK. – Robert

+0

jarsigner sẽ không xác minh chứng chỉ người ký (vì vậy bất kỳ chữ ký không đáng tin cậy nào sẽ làm), nó không kiểm tra dấu thời gian tin cậy (không thể xử lý chữ ký hợp lệ từ người ký có chứng chỉ đã hết hạn) và đầu ra của nó là vô ích ('đã xác minh' được trả về ngay cả khi có lỗi , có thể thu được nhiều thông tin hơn bằng cách phân tích cú pháp các thông báo lỗi và cảnh báo - nhưng vẫn chưa đủ để quyết định xem chứng chỉ có hợp lệ hay không). –

14

Bạn chỉ cần mở tệp JAR bằng java.util.jar.JarFile và yêu cầu nó xác minh tệp JAR. Nếu JAR được ký, thì JarFile có tùy chọn để xác minh nó (được bật theo mặc định). Tuy nhiên, JarFile cũng sẽ mở các JAR chưa được ký một cách hạnh phúc, do đó bạn cũng phải kiểm tra xem tệp đó có được ký hay không. Bạn có thể làm như vậy bằng cách kiểm tra tệp kê khai của JAR cho * -Digest attributes: Các phần tử có thuộc tính attribute như vậy được ký.

Ví dụ:

JarFile jar = new JarFile(new File("path/to/your/jar-file")); 

// This call will throw a java.lang.SecurityException if someone has tampered 
// with the signature of _any_ element of the JAR file. 
// Alas, it will proceed without a problem if the JAR file is not signed at all 
InputStream is = jar.getInputStream(jar.getEntry("META-INF/MANIFEST.MF")); 
Manifest man = new Manifest(is); 
is.close(); 

Set<String> signed = new HashSet(); 
for(Map.Entry<String, Attributes> entry: man.getEntries().entrySet()) { 
    for(Object attrkey: entry.getValue().keySet()) { 
     if (attrkey instanceof Attributes.Name && 
      ((Attributes.Name)attrkey).toString().indexOf("-Digest") != -1) 
      signed.add(entry.getKey()); 
    } 
} 

Set<String> entries = new HashSet<String>(); 
for(Enumeration<JarEntry> entry = jar.entries(); entry.hasMoreElements();) { 
    JarEntry je = entry.nextElement(); 
    if (!je.isDirectory()) 
     entries.add(je.getName()); 
} 

// contains all entries in the Manifest that are not signed. 
// Ususally, this contains: 
// * MANIFEST.MF itself 
// * *.SF files containing the signature of MANIFEST.MF 
// * *.DSA files containing public keys of the signer 

Set<String> unsigned = new HashSet<String>(entries); 
unsigned.removeAll(signed); 

// contains all the entries with a signature that are not present in the JAR 
Set<String> missing = new HashSet<String>(signed); 
missing.removeAll(entries); 
+7

Mở một jar thông qua JarFile (tên tệp) không xác minh các lớp trong JAR nó chỉ cho phép xác minh xảy ra khi truy cập. Do đó để xác minh tất cả các mục nhập của một Jar bạn phải gọi jar.getInputStream (..) cho mỗi mục nhập - điều này kích hoạt xác minh. – Robert

+0

xem http://stackoverflow.com/a/5589898/3934807 đối với một số mã thực hiện đề xuất của Robert – ingenue

2

Bạn có thể sử dụng entry.getCodeSigners() để có được những người ký tên cho một mục đặc biệt trong JAR.

Đảm bảo mở JarFile bằng verify = true và đọc toàn bộ mục nhập JAR trước khi gọi hàm entry.getCodeSigners().

Something như thế này có thể được sử dụng để xác minh mỗi mục đó không phải là một tập tin chữ ký:

boolean verify = true; 
JarFile jar = new JarFile(signedFile, verify); 

// Need each entry so that future calls to entry.getCodeSigners will return anything 
Enumeration<JarEntry> entries = jar.entries(); 
while (entries.hasMoreElements()) { 
    JarEntry entry = entries.nextElement(); 
    IOUtils.copy(jar.getInputStream(entry), new NullOutputStream()); 
} 

// Now check each entry that is not a signature file 
entries = jar.entries(); 
while (entries.hasMoreElements()) { 
    JarEntry entry = entries.nextElement(); 
    String fileName = entry.getName().toUpperCase(Locale.ENGLISH); 
    if (!fileName.endsWith(".SF") 
     && !fileName.endsWith(".DSA") 
     && !fileName.endsWith(".EC") 
     && !fileName.endsWith(".RSA")) { 

     // Now get code signers, inspect certificates etc here... 
     // entry.getCodeSigners(); 
    } 
} 
Các vấn đề liên quan