📄 jarfile.java
字号:
try { jarfile.readSignatures(); } catch (IOException ioe) { if (JarFile.DEBUG) { JarFile.debug(ioe); ioe.printStackTrace(); } jarfile.signaturesRead = true; // fudge it. } // Include the certificates only if we have asserted that the // signatures are valid. This means the certificates will not be // available if the entry hasn't been read yet. if (jarfile.entryCerts != null && jarfile.verified.get(zip.getName()) == Boolean.TRUE) { Set certs = (Set) jarfile.entryCerts.get(jar.getName()); if (certs != null) jar.certs = (Certificate[]) certs.toArray(new Certificate[certs.size()]); } } return jar; } } /** * XXX * It actually returns a JarEntry not a zipEntry * @param name XXX */ public synchronized ZipEntry getEntry(String name) { ZipEntry entry = super.getEntry(name); if (entry != null) { JarEntry jarEntry = new JarEntry(entry); Manifest manifest; try { manifest = getManifest(); } catch (IOException ioe) { manifest = null; } if (manifest != null) { jarEntry.attr = manifest.getAttributes(name); } if (verify && !signaturesRead) try { readSignatures(); } catch (IOException ioe) { if (DEBUG) { debug(ioe); ioe.printStackTrace(); } signaturesRead = true; } // See the comments in the JarEnumeration for why we do this // check. if (DEBUG) debug("entryCerts=" + entryCerts + " verified " + name + " ? " + verified.get(name)); if (entryCerts != null && verified.get(name) == Boolean.TRUE) { Set certs = (Set) entryCerts.get(name); if (certs != null) jarEntry.certs = (Certificate[]) certs.toArray(new Certificate[certs.size()]); } return jarEntry; } return null; } /** * Returns an input stream for the given entry. If configured to * verify entries, the input stream returned will verify them while * the stream is read, but only on the first time. * * @param entry The entry to get the input stream for. * @exception ZipException XXX * @exception IOException XXX */ public synchronized InputStream getInputStream(ZipEntry entry) throws ZipException, IOException { // If we haven't verified the hash, do it now. if (!verified.containsKey(entry.getName()) && verify) { if (DEBUG) debug("reading and verifying " + entry); return new EntryInputStream(entry, super.getInputStream(entry), this); } else { if (DEBUG) debug("reading already verified entry " + entry); if (verify && verified.get(entry.getName()) == Boolean.FALSE) throw new ZipException("digest for " + entry + " is invalid"); return super.getInputStream(entry); } } /** * Returns the JarEntry that belongs to the name if such an entry * exists in the JarFile. Returns null otherwise * Convenience method that just casts the result from <code>getEntry</code> * to a JarEntry. * * @param name the jar entry name to look up * @return the JarEntry if it exists, null otherwise */ public JarEntry getJarEntry(String name) { return (JarEntry) getEntry(name); } /** * Returns the manifest for this JarFile or null when the JarFile does not * contain a manifest file. */ public synchronized Manifest getManifest() throws IOException { if (!manifestRead) manifest = readManifest(); return manifest; } // Only called with lock on this JarFile. // Package private for use in inner classes. void readSignatures() throws IOException { Map pkcs7Dsa = new HashMap(); Map pkcs7Rsa = new HashMap(); Map sigFiles = new HashMap(); // Phase 1: Read all signature files. These contain the user // certificates as well as the signatures themselves. for (Enumeration e = super.entries(); e.hasMoreElements(); ) { ZipEntry ze = (ZipEntry) e.nextElement(); String name = ze.getName(); if (name.startsWith(META_INF)) { String alias = name.substring(META_INF.length()); if (alias.lastIndexOf('.') >= 0) alias = alias.substring(0, alias.lastIndexOf('.')); if (name.endsWith(PKCS7_DSA_SUFFIX) || name.endsWith(PKCS7_RSA_SUFFIX)) { if (DEBUG) debug("reading PKCS7 info from " + name + ", alias=" + alias); PKCS7SignedData sig = null; try { sig = new PKCS7SignedData(super.getInputStream(ze)); } catch (CertificateException ce) { IOException ioe = new IOException("certificate parsing error"); ioe.initCause(ce); throw ioe; } catch (CRLException crle) { IOException ioe = new IOException("CRL parsing error"); ioe.initCause(crle); throw ioe; } if (name.endsWith(PKCS7_DSA_SUFFIX)) pkcs7Dsa.put(alias, sig); else if (name.endsWith(PKCS7_RSA_SUFFIX)) pkcs7Rsa.put(alias, sig); } else if (name.endsWith(SF_SUFFIX)) { if (DEBUG) debug("reading signature file for " + alias + ": " + name); Manifest sf = new Manifest(super.getInputStream(ze)); sigFiles.put(alias, sf); if (DEBUG) debug("result: " + sf); } } } // Phase 2: verify the signatures on any signature files. Set validCerts = new HashSet(); Map entryCerts = new HashMap(); for (Iterator it = sigFiles.entrySet().iterator(); it.hasNext(); ) { int valid = 0; Map.Entry e = (Map.Entry) it.next(); String alias = (String) e.getKey(); PKCS7SignedData sig = (PKCS7SignedData) pkcs7Dsa.get(alias); if (sig != null) { Certificate[] certs = sig.getCertificates(); Set signerInfos = sig.getSignerInfos(); for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); ) verify(certs, (SignerInfo) it2.next(), alias, validCerts); } sig = (PKCS7SignedData) pkcs7Rsa.get(alias); if (sig != null) { Certificate[] certs = sig.getCertificates(); Set signerInfos = sig.getSignerInfos(); for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); ) verify(certs, (SignerInfo) it2.next(), alias, validCerts); } // It isn't a signature for anything. Punt it. if (validCerts.isEmpty()) { it.remove(); continue; } entryCerts.put(e.getValue(), new HashSet(validCerts)); validCerts.clear(); } // Phase 3: verify the signature file signatures against the manifest, // mapping the entry name to the target certificates. this.entryCerts = new HashMap(); for (Iterator it = entryCerts.entrySet().iterator(); it.hasNext(); ) { Map.Entry e = (Map.Entry) it.next(); Manifest sigfile = (Manifest) e.getKey(); Map entries = sigfile.getEntries(); Set certificates = (Set) e.getValue(); for (Iterator it2 = entries.entrySet().iterator(); it2.hasNext(); ) { Map.Entry e2 = (Map.Entry) it2.next(); String entryname = String.valueOf(e2.getKey()); Attributes attr = (Attributes) e2.getValue(); if (verifyHashes(entryname, attr)) { if (DEBUG) debug("entry " + entryname + " has certificates " + certificates); Set s = (Set) this.entryCerts.get(entryname); if (s != null) s.addAll(certificates); else this.entryCerts.put(entryname, new HashSet(certificates)); } } } signaturesRead = true; } /** * Tell if the given signer info is over the given alias's signature file, * given one of the certificates specified. */ private void verify(Certificate[] certs, SignerInfo signerInfo, String alias, Set validCerts) { Signature sig = null; try { OID alg = signerInfo.getDigestEncryptionAlgorithmId(); if (alg.equals(DSA_ENCRYPTION_OID)) { if (!signerInfo.getDigestAlgorithmId().equals(SHA1_OID)) return; sig = Signature.getInstance("SHA1withDSA"); } else if (alg.equals(RSA_ENCRYPTION_OID)) { OID hash = signerInfo.getDigestAlgorithmId(); if (hash.equals(MD2_OID)) sig = Signature.getInstance("md2WithRsaEncryption"); else if (hash.equals(MD4_OID)) sig = Signature.getInstance("md4WithRsaEncryption"); else if (hash.equals(MD5_OID)) sig = Signature.getInstance("md5WithRsaEncryption"); else if (hash.equals(SHA1_OID)) sig = Signature.getInstance("sha1WithRsaEncryption"); else return; } else { if (DEBUG) debug("unsupported signature algorithm: " + alg); return; } } catch (NoSuchAlgorithmException nsae) { if (DEBUG) { debug(nsae); nsae.printStackTrace(); } return; } ZipEntry sigFileEntry = super.getEntry(META_INF + alias + SF_SUFFIX); if (sigFileEntry == null) return; for (int i = 0; i < certs.length; i++) { if (!(certs[i] instanceof X509Certificate)) continue; X509Certificate cert = (X509Certificate) certs[i]; if (!cert.getIssuerX500Principal().equals(signerInfo.getIssuer()) || !cert.getSerialNumber().equals(signerInfo.getSerialNumber())) continue; try { sig.initVerify(cert.getPublicKey()); InputStream in = super.getInputStream(sigFileEntry); if (in == null) continue; byte[] buf = new byte[1024]; int len = 0; while ((len = in.read(buf)) != -1) sig.update(buf, 0, len); if (sig.verify(signerInfo.getEncryptedDigest())) { if (DEBUG) debug("signature for " + cert.getSubjectDN() + " is good"); validCerts.add(cert); } } catch (IOException ioe) { continue; } catch (InvalidKeyException ike) { continue; } catch (SignatureException se) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -