s.append('\n'); first = false; } try { CertPath cp = certificateFactory.generateCertPath(certs); validator.validate(cp, pkixParameters); } catch (Exception e) { chainNotValidated = true; s.append(tab + rb.getString(".CertPath.not.validated.") + e.getLocalizedMessage() + "]\n"); // TODO } String result = s.toString(); cacheForSignerInfo.put(signer, result); return result; } private void writeEntry(ZipFile zf, ZipOutputStream os, ZipEntry ze) throws IOException { ZipEntry ze2 = new ZipEntry(ze.getName()); ze2.setMethod(ze.getMethod()); ze2.setTime(ze.getTime()); ze2.setComment(ze.getComment()); ze2.setExtra(ze.getExtra()); if (ze.getMethod() == ZipEntry.STORED) { ze2.setSize(ze.getSize()); ze2.setCrc(ze.getCrc()); } os.putNextEntry(ze2); writeBytes(zf, ze, os); } /** * Writes all the bytes for a given entry to the specified output stream. */ private synchronized void writeBytes (ZipFile zf, ZipEntry ze, ZipOutputStream os) throws IOException { int n; InputStream is = null; try { is = zf.getInputStream(ze); long left = ze.getSize(); while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) { os.write(buffer, 0, n); left -= n; } } finally { if (is != null) { is.close(); } } } void loadKeyStore(String keyStoreName, boolean prompt) { if (!nullStream && keyStoreName == null) { keyStoreName = System.getProperty("user.home") + File.separator + ".keystore"; } try { if (providerName == null) { store = KeyStore.getInstance(storetype); } else { store = KeyStore.getInstance(storetype, providerName); } // Get pass phrase // XXX need to disable echo; on UNIX, call getpass(char *prompt)Z // and on NT call ?? if (token && storepass == null && !protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype)) { storepass = getPass (rb.getString("Enter.Passphrase.for.keystore.")); } else if (!token && storepass == null && prompt) { storepass = getPass (rb.getString("Enter.Passphrase.for.keystore.")); } if (nullStream) { store.load(null, storepass); } else { keyStoreName = keyStoreName.replace(File.separatorChar, '/'); URL url = null; try { url = new URL(keyStoreName); } catch (java.net.MalformedURLException e) { // try as file url = new File(keyStoreName).toURI().toURL(); } InputStream is = null; try { is = url.openStream(); store.load(is, storepass); } finally { if (is != null) { is.close(); } } } Set<TrustAnchor> tas = new HashSet<>(); try { KeyStore caks = KeyTool.getCacertsKeyStore(); if (caks != null) { Enumeration<String> aliases = caks.aliases(); while (aliases.hasMoreElements()) { String a = aliases.nextElement(); try { tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null)); } catch (Exception e2) { // ignore, when a SecretkeyEntry does not include a cert } } } } catch (Exception e) { // Ignore, if cacerts cannot be loaded } if (store != null) { Enumeration<String> aliases = store.aliases(); while (aliases.hasMoreElements()) { String a = aliases.nextElement(); try { X509Certificate c = (X509Certificate)store.getCertificate(a); // Only add TrustedCertificateEntry and self-signed // PrivateKeyEntry if (store.isCertificateEntry(a) || c.getSubjectDN().equals(c.getIssuerDN())) { tas.add(new TrustAnchor(c, null)); } } catch (Exception e2) { // ignore, when a SecretkeyEntry does not include a cert } } } certificateFactory = CertificateFactory.getInstance("X.509"); validator = CertPathValidator.getInstance("PKIX"); try { pkixParameters = new PKIXParameters(tas); pkixParameters.setRevocationEnabled(false); } catch (InvalidAlgorithmParameterException ex) { // Only if tas is empty } } catch (IOException ioe) { throw new RuntimeException(rb.getString("keystore.load.") + ioe.getMessage()); } catch (java.security.cert.CertificateException ce) { throw new RuntimeException(rb.getString("certificate.exception.") + ce.getMessage()); } catch (NoSuchProviderException pe) { throw new RuntimeException(rb.getString("keystore.load.") + pe.getMessage()); } catch (NoSuchAlgorithmException nsae) { throw new RuntimeException(rb.getString("keystore.load.") + nsae.getMessage()); } catch (KeyStoreException kse) { throw new RuntimeException (rb.getString("unable.to.instantiate.keystore.class.") + kse.getMessage()); } } X509Certificate getTsaCert(String alias) { java.security.cert.Certificate cs = null; try { cs = store.getCertificate(alias); } catch (KeyStoreException kse) { // this never happens, because keystore has been loaded } if (cs == null || (!(cs instanceof X509Certificate))) { MessageFormat form = new MessageFormat(rb.getString ("Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the")); Object[] source = {alias, alias}; error(form.format(source)); } return (X509Certificate) cs; } /** * Check if userCert is designed to be a code signer * @param userCert the certificate to be examined * @param bad 3 booleans to show if the KeyUsage, ExtendedKeyUsage, * NetscapeCertType has codeSigning flag turned on. * If null, the class field badKeyUsage, badExtendedKeyUsage, * badNetscapeCertType will be set. */ void checkCertUsage(X509Certificate userCert, boolean[] bad) { // Can act as a signer? // 1. if KeyUsage, then [0:digitalSignature] or // [1:nonRepudiation] should be true // 2. if ExtendedKeyUsage, then should contains ANY or CODE_SIGNING // 3. if NetscapeCertType, then should contains OBJECT_SIGNING // 1,2,3 must be true if (bad != null) { bad[0] = bad[1] = bad[2] = false; } boolean[] keyUsage = userCert.getKeyUsage(); if (keyUsage != null) { keyUsage = Arrays.copyOf(keyUsage, 9); if (!keyUsage[0] && !keyUsage[1]) { if (bad != null) { bad[0] = true; badKeyUsage = true; } } } try { List<String> xKeyUsage = userCert.getExtendedKeyUsage(); if (xKeyUsage != null) { if (!xKeyUsage.contains("2.5.29.37.0") // anyExtendedKeyUsage && !xKeyUsage.contains("1.3.6.1.5.5.7.3.3")) { // codeSigning if (bad != null) { bad[1] = true; badExtendedKeyUsage = true; } } } } catch (java.security.cert.CertificateParsingException e) { // shouldn't happen } try { // OID_NETSCAPE_CERT_TYPE byte[] netscapeEx = userCert.getExtensionValue ("2.16.840.1.113730.1.1"); if (netscapeEx != null) { DerInputStream in = new DerInputStream(netscapeEx); byte[] encoded = in.getOctetString(); encoded = new DerValue(encoded).getUnalignedBitString() .toByteArray(); NetscapeCertTypeExtension extn = new NetscapeCertTypeExtension(encoded); Boolean val = (Boolean)extn.get( NetscapeCertTypeExtension.OBJECT_SIGNING); if (!val) { if (bad != null) { bad[2] = true; badNetscapeCertType = true; } } } } catch (IOException e) { // } } void getAliasInfo(String alias) { Key key = null; try { java.security.cert.Certificate[] cs = null; if (altCertChain != null) { try { cs = CertificateFactory.getInstance("X.509"). generateCertificates(new FileInputStream(altCertChain)). toArray(new Certificate[0]); } catch (CertificateException ex) { error(rb.getString("Cannot.restore.certchain.from.file.specified")); } catch (FileNotFoundException ex) { error(rb.getString("File.specified.by.certchain.does.not.exist")); } } else { try { cs = store.getCertificateChain(alias); } catch (KeyStoreException kse) { // this never happens, because keystore has been loaded } } if (cs == null || cs.length == 0) { if (altCertChain != null) { error(rb.getString ("Certificate.chain.not.found.in.the.file.specified.")); } else { MessageFormat form = new MessageFormat(rb.getString ("Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and")); Object[] source = {alias, alias}; error(form.format(source)); } } certChain = new X509Certificate[cs.length]; for (int i=0; i<cs.length; i++) { if (!(cs[i] instanceof X509Certificate)) { error(rb.getString ("found.non.X.509.certificate.in.signer.s.chain")); } certChain[i] = (X509Certificate)cs[i]; } // We don't meant to print anything, the next call // checks validity and keyUsage etc printCert("", certChain[0], true, 0, true); try { CertPath cp = certificateFactory.generateCertPath(Arrays.asList(certChain)); validator.validate(cp, pkixParameters); } catch (Exception e) { chainNotValidated = true; } try { if (!token && keypass == null) key = store.getKey(alias, storepass); else key = store.getKey(alias, keypass); } catch (UnrecoverableKeyException e) { if (token) { throw e; } else if (keypass == null) { // Did not work out, so prompt user for key password MessageFormat form = new MessageFormat(rb.getString ("Enter.key.password.for.alias.")); Object[] source = {alias}; keypass = getPass(form.format(source)); key = store.getKey(alias, keypass); } } } catch (NoSuchAlgorithmException e) { error(e.getMessage()); } catch (UnrecoverableKeyException e) { error(rb.getString("unable.to.recover.key.from.keystore")); } catch (KeyStoreException kse) { // this never happens, because keystore has been loaded } if (!(key instanceof PrivateKey)) { MessageFormat form = new MessageFormat(rb.getString ("key.associated.with.alias.not.a.private.key")); Object[] source = {alias}; error(form.format(source)); } else { privateKey = (PrivateKey)key; } } void error(String message) { System.out.println(rb.getString("jarsigner.")+message); System.exit(1); } void error(String message, Exception e) { System.out.println(rb.getString("jarsigner.")+message); if (debug) { e.printStackTrace(); } System.exit(1); } char[] getPass(String prompt) { System.err.print(prompt); System.err.flush(); try { char[] pass = Password.readPassword(System.in); if (pass == null) { error(rb.getString("you.must.enter.key.password")); } else { return pass; } } catch (IOException ioe) { error(rb.getString("unable.to.read.password.")+ioe.getMessage()); } // this shouldn't happen return null; } /* * Reads all the bytes for a given zip entry. */ private synchronized byte[] getBytes(ZipFile zf, ZipEntry ze) throws IOException { int n; InputStream is = null; try { is = zf.getInputStream(ze); baos.reset(); long left = ze.getSize(); while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) { baos.write(buffer, 0, n); left -= n; } } finally { if (is != null) { is.close(); } } return baos.toByteArray(); } /* * Returns manifest entry from given jar file, or null if given jar file * does not have a manifest entry. */ private ZipEntry getManifestFile(ZipFile zf) { ZipEntry ze = zf.getEntry(JarFile.MANIFEST_NAME); if (ze == null) { // Check all entries for matching name Enumeration<? extends ZipEntry> enum_ = zf.entries(); while (enum_.hasMoreElements() && ze == null) { ze = enum_.nextElement(); if (!JarFile.MANIFEST_NAME.equalsIgnoreCase (ze.getName())) { ze = null; } } } return ze; } /* * Computes the digests of a zip entry, and returns them as an array * of base64-encoded strings. */ private synchronized String[] getDigests(ZipEntry ze, ZipFile zf, MessageDigest[] digests, BASE64Encoder encoder) throws IOException { int n, i; InputStream is = null; try { is = zf.getInputStream(ze); long left = ze.getSize(); while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) { for (i=0; i<digests.length; i++) { digests[i].update(buffer, 0, n); } left -= n; } } finally { if (is != null) { is.close(); } } // complete the digests String[] base64Digests = new String[digests.length]; for (i=0; i<digests.length; i++) { base64Digests[i] = encoder.encode(digests[i].digest()); } return base64Digests; } /* * Computes the digests of a zip entry, and returns them as a list of * attributes */ private Attributes getDigestAttributes(ZipEntry ze, ZipFile zf, MessageDigest[] digests, BASE64Encoder encoder) throws IOException { String[] base64Digests = getDigests(ze, zf, digests, encoder); Attributes attrs = new Attributes(); for (int i=0; i<digests.length; i++) { attrs.putValue(digests[i].getAlgorithm()+"-Digest", base64Digests[i]); } return attrs; } /* * Updates the digest attributes of a manifest entry, by adding or * replacing digest values. * A digest value is added if the manifest entry does not contain a digest * for that particular algorithm. * A digest value is replaced if it is obsolete. * * Returns true if the manifest entry has been changed, and false * otherwise. */ private boolean updateDigests(ZipEntry ze, ZipFile zf, MessageDigest[] digests, BASE64Encoder encoder, Manifest mf) throws IOException { boolean update = false; Attributes attrs = mf.getAttributes(ze.getName()); String[] base64Digests = getDigests(ze, zf, digests, encoder); for (int i=0; i<digests.length; i++) {Lines 1501–2000 of 2445. Previous lines Load more
s.append('\n'); first = false; } try { CertPath cp = certificateFactory.generateCertPath(certs); validator.validate(cp, pkixParameters); } catch (Exception e) { chainNotValidated = true; s.append(tab + rb.getString(".CertPath.not.validated.") + e.getLocalizedMessage() + "]\n"); // TODO } String result = s.toString(); cacheForSignerInfo.put(signer, result); return result; } private void writeEntry(ZipFile zf, ZipOutputStream os, ZipEntry ze) throws IOException { ZipEntry ze2 = new ZipEntry(ze.getName()); ze2.setMethod(ze.getMethod()); ze2.setTime(ze.getTime()); ze2.setComment(ze.getComment()); ze2.setExtra(ze.getExtra()); if (ze.getMethod() == ZipEntry.STORED) { ze2.setSize(ze.getSize()); ze2.setCrc(ze.getCrc()); } os.putNextEntry(ze2); writeBytes(zf, ze, os); } /** * Writes all the bytes for a given entry to the specified output stream. */ private synchronized void writeBytes (ZipFile zf, ZipEntry ze, ZipOutputStream os) throws IOException { int n; InputStream is = null; try { is = zf.getInputStream(ze); long left = ze.getSize(); while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) { os.write(buffer, 0, n); left -= n; } } finally { if (is != null) { is.close(); } } } void loadKeyStore(String keyStoreName, boolean prompt) { if (!nullStream && keyStoreName == null) { keyStoreName = System.getProperty("user.home") + File.separator + ".keystore"; } try { if (providerName == null) { store = KeyStore.getInstance(storetype); } else { store = KeyStore.getInstance(storetype, providerName); } // Get pass phrase // XXX need to disable echo; on UNIX, call getpass(char *prompt)Z // and on NT call ?? if (token && storepass == null && !protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype)) { storepass = getPass (rb.getString("Enter.Passphrase.for.keystore.")); } else if (!token && storepass == null && prompt) { storepass = getPass (rb.getString("Enter.Passphrase.for.keystore.")); } if (nullStream) { store.load(null, storepass); } else { keyStoreName = keyStoreName.replace(File.separatorChar, '/'); URL url = null; try { url = new URL(keyStoreName); } catch (java.net.MalformedURLException e) { // try as file url = new File(keyStoreName).toURI().toURL(); } InputStream is = null; try { is = url.openStream(); store.load(is, storepass); } finally { if (is != null) { is.close(); } } } Set<TrustAnchor> tas = new HashSet<>(); try { KeyStore caks = KeyTool.getCacertsKeyStore(); if (caks != null) { Enumeration<String> aliases = caks.aliases(); while (aliases.hasMoreElements()) { String a = aliases.nextElement(); try { tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null)); } catch (Exception e2) { // ignore, when a SecretkeyEntry does not include a cert } } } } catch (Exception e) { // Ignore, if cacerts cannot be loaded } if (store != null) { Enumeration<String> aliases = store.aliases(); while (aliases.hasMoreElements()) { String a = aliases.nextElement(); try { X509Certificate c = (X509Certificate)store.getCertificate(a); // Only add TrustedCertificateEntry and self-signed // PrivateKeyEntry if (store.isCertificateEntry(a) || c.getSubjectDN().equals(c.getIssuerDN())) { tas.add(new TrustAnchor(c, null)); } } catch (Exception e2) { // ignore, when a SecretkeyEntry does not include a cert } } } certificateFactory = CertificateFactory.getInstance("X.509"); validator = CertPathValidator.getInstance("PKIX"); try { pkixParameters = new PKIXParameters(tas); pkixParameters.setRevocationEnabled(false); } catch (InvalidAlgorithmParameterException ex) { // Only if tas is empty } } catch (IOException ioe) { throw new RuntimeException(rb.getString("keystore.load.") + ioe.getMessage()); } catch (java.security.cert.CertificateException ce) { throw new RuntimeException(rb.getString("certificate.exception.") + ce.getMessage()); } catch (NoSuchProviderException pe) { throw new RuntimeException(rb.getString("keystore.load.") + pe.getMessage()); } catch (NoSuchAlgorithmException nsae) { throw new RuntimeException(rb.getString("keystore.load.") + nsae.getMessage()); } catch (KeyStoreException kse) { throw new RuntimeException (rb.getString("unable.to.instantiate.keystore.class.") + kse.getMessage()); } } X509Certificate getTsaCert(String alias) { java.security.cert.Certificate cs = null; try { cs = store.getCertificate(alias); } catch (KeyStoreException kse) { // this never happens, because keystore has been loaded } if (cs == null || (!(cs instanceof X509Certificate))) { MessageFormat form = new MessageFormat(rb.getString ("Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the")); Object[] source = {alias, alias}; error(form.format(source)); } return (X509Certificate) cs; } /** * Check if userCert is designed to be a code signer * @param userCert the certificate to be examined * @param bad 3 booleans to show if the KeyUsage, ExtendedKeyUsage, * NetscapeCertType has codeSigning flag turned on. * If null, the class field badKeyUsage, badExtendedKeyUsage, * badNetscapeCertType will be set. */ void checkCertUsage(X509Certificate userCert, boolean[] bad) { // Can act as a signer? // 1. if KeyUsage, then [0:digitalSignature] or // [1:nonRepudiation] should be true // 2. if ExtendedKeyUsage, then should contains ANY or CODE_SIGNING // 3. if NetscapeCertType, then should contains OBJECT_SIGNING // 1,2,3 must be true if (bad != null) { bad[0] = bad[1] = bad[2] = false; } boolean[] keyUsage = userCert.getKeyUsage(); if (keyUsage != null) { keyUsage = Arrays.copyOf(keyUsage, 9); if (!keyUsage[0] && !keyUsage[1]) { if (bad != null) { bad[0] = true; badKeyUsage = true; } } } try { List<String> xKeyUsage = userCert.getExtendedKeyUsage(); if (xKeyUsage != null) { if (!xKeyUsage.contains("2.5.29.37.0") // anyExtendedKeyUsage && !xKeyUsage.contains("1.3.6.1.5.5.7.3.3")) { // codeSigning if (bad != null) { bad[1] = true; badExtendedKeyUsage = true; } } } } catch (java.security.cert.CertificateParsingException e) { // shouldn't happen } try { // OID_NETSCAPE_CERT_TYPE byte[] netscapeEx = userCert.getExtensionValue ("2.16.840.1.113730.1.1"); if (netscapeEx != null) { DerInputStream in = new DerInputStream(netscapeEx); byte[] encoded = in.getOctetString(); encoded = new DerValue(encoded).getUnalignedBitString() .toByteArray(); NetscapeCertTypeExtension extn = new NetscapeCertTypeExtension(encoded); Boolean val = (Boolean)extn.get( NetscapeCertTypeExtension.OBJECT_SIGNING); if (!val) { if (bad != null) { bad[2] = true; badNetscapeCertType = true; } } } } catch (IOException e) { // } } void getAliasInfo(String alias) { Key key = null; try { java.security.cert.Certificate[] cs = null; if (altCertChain != null) { try { cs = CertificateFactory.getInstance("X.509"). generateCertificates(new FileInputStream(altCertChain)). toArray(new Certificate[0]); } catch (CertificateException ex) { error(rb.getString("Cannot.restore.certchain.from.file.specified")); } catch (FileNotFoundException ex) { error(rb.getString("File.specified.by.certchain.does.not.exist")); } } else { try { cs = store.getCertificateChain(alias); } catch (KeyStoreException kse) { // this never happens, because keystore has been loaded } } if (cs == null || cs.length == 0) { if (altCertChain != null) { error(rb.getString ("Certificate.chain.not.found.in.the.file.specified.")); } else { MessageFormat form = new MessageFormat(rb.getString ("Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and")); Object[] source = {alias, alias}; error(form.format(source)); } } certChain = new X509Certificate[cs.length]; for (int i=0; i<cs.length; i++) { if (!(cs[i] instanceof X509Certificate)) { error(rb.getString ("found.non.X.509.certificate.in.signer.s.chain")); } certChain[i] = (X509Certificate)cs[i]; } // We don't meant to print anything, the next call // checks validity and keyUsage etc printCert("", certChain[0], true, 0, true); try { CertPath cp = certificateFactory.generateCertPath(Arrays.asList(certChain)); validator.validate(cp, pkixParameters); } catch (Exception e) { chainNotValidated = true; } try { if (!token && keypass == null) key = store.getKey(alias, storepass); else key = store.getKey(alias, keypass); } catch (UnrecoverableKeyException e) { if (token) { throw e; } else if (keypass == null) { // Did not work out, so prompt user for key password MessageFormat form = new MessageFormat(rb.getString ("Enter.key.password.for.alias.")); Object[] source = {alias}; keypass = getPass(form.format(source)); key = store.getKey(alias, keypass); } } } catch (NoSuchAlgorithmException e) { error(e.getMessage()); } catch (UnrecoverableKeyException e) { error(rb.getString("unable.to.recover.key.from.keystore")); } catch (KeyStoreException kse) { // this never happens, because keystore has been loaded } if (!(key instanceof PrivateKey)) { MessageFormat form = new MessageFormat(rb.getString ("key.associated.with.alias.not.a.private.key")); Object[] source = {alias}; error(form.format(source)); } else { privateKey = (PrivateKey)key; } } void error(String message) { System.out.println(rb.getString("jarsigner.")+message); System.exit(1); } void error(String message, Exception e) { System.out.println(rb.getString("jarsigner.")+message); if (debug) { e.printStackTrace(); } System.exit(1); } char[] getPass(String prompt) { System.err.print(prompt); System.err.flush(); try { char[] pass = Password.readPassword(System.in); if (pass == null) { error(rb.getString("you.must.enter.key.password")); } else { return pass; } } catch (IOException ioe) { error(rb.getString("unable.to.read.password.")+ioe.getMessage()); } // this shouldn't happen return null; } /* * Reads all the bytes for a given zip entry. */ private synchronized byte[] getBytes(ZipFile zf, ZipEntry ze) throws IOException { int n; InputStream is = null; try { is = zf.getInputStream(ze); baos.reset(); long left = ze.getSize(); while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) { baos.write(buffer, 0, n); left -= n; } } finally { if (is != null) { is.close(); } } return baos.toByteArray(); } /* * Returns manifest entry from given jar file, or null if given jar file * does not have a manifest entry. */ private ZipEntry getManifestFile(ZipFile zf) { ZipEntry ze = zf.getEntry(JarFile.MANIFEST_NAME); if (ze == null) { // Check all entries for matching name Enumeration<? extends ZipEntry> enum_ = zf.entries(); while (enum_.hasMoreElements() && ze == null) { ze = enum_.nextElement(); if (!JarFile.MANIFEST_NAME.equalsIgnoreCase (ze.getName())) { ze = null; } } } return ze; } /* * Computes the digests of a zip entry, and returns them as an array * of base64-encoded strings. */ private synchronized String[] getDigests(ZipEntry ze, ZipFile zf, MessageDigest[] digests, BASE64Encoder encoder) throws IOException { int n, i; InputStream is = null; try { is = zf.getInputStream(ze); long left = ze.getSize(); while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) { for (i=0; i<digests.length; i++) { digests[i].update(buffer, 0, n); } left -= n; } } finally { if (is != null) { is.close(); } } // complete the digests String[] base64Digests = new String[digests.length]; for (i=0; i<digests.length; i++) { base64Digests[i] = encoder.encode(digests[i].digest()); } return base64Digests; } /* * Computes the digests of a zip entry, and returns them as a list of * attributes */ private Attributes getDigestAttributes(ZipEntry ze, ZipFile zf, MessageDigest[] digests, BASE64Encoder encoder) throws IOException { String[] base64Digests = getDigests(ze, zf, digests, encoder); Attributes attrs = new Attributes(); for (int i=0; i<digests.length; i++) { attrs.putValue(digests[i].getAlgorithm()+"-Digest", base64Digests[i]); } return attrs; } /* * Updates the digest attributes of a manifest entry, by adding or * replacing digest values. * A digest value is added if the manifest entry does not contain a digest * for that particular algorithm. * A digest value is replaced if it is obsolete. * * Returns true if the manifest entry has been changed, and false * otherwise. */ private boolean updateDigests(ZipEntry ze, ZipFile zf, MessageDigest[] digests, BASE64Encoder encoder, Manifest mf) throws IOException { boolean update = false; Attributes attrs = mf.getAttributes(ze.getName()); String[] base64Digests = getDigests(ze, zf, digests, encoder); for (int i=0; i<digests.length; i++) {