} /* * Examines a signature timestamp token to generate a timestamp object. * * Examines the signer's unsigned attributes for a * <tt>signatureTimestampToken</tt> attribute. If present, * then it is parsed to extract the date and time at which the * timestamp was generated. * * @param info A signer information element of a PKCS 7 block. * * @return A timestamp token or null if none is present. * @throws IOException if an error is encountered while parsing the * PKCS7 data. * @throws NoSuchAlgorithmException if an error is encountered while * verifying the PKCS7 object. * @throws SignatureException if an error is encountered while * verifying the PKCS7 object. * @throws CertificateException if an error is encountered while generating * the TSA's certpath. */ private Timestamp getTimestamp(SignerInfo info) throws IOException, NoSuchAlgorithmException, SignatureException, CertificateException { Timestamp timestamp = null; // Extract the signer's unsigned attributes PKCS9Attributes unsignedAttrs = info.getUnauthenticatedAttributes(); if (unsignedAttrs != null) { PKCS9Attribute timestampTokenAttr = unsignedAttrs.getAttribute("signatureTimestampToken"); if (timestampTokenAttr != null) { PKCS7 timestampToken = new PKCS7((byte[])timestampTokenAttr.getValue()); // Extract the content (an encoded timestamp token info) byte[] encodedTimestampTokenInfo = timestampToken.getContentInfo().getData(); // Extract the signer (the Timestamping Authority) // while verifying the content SignerInfo[] tsa = timestampToken.verify(encodedTimestampTokenInfo); // Expect only one signer ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(timestampToken); CertPath tsaChain = certificateFactory.generateCertPath(chain); // Create a timestamp token info object TimestampToken timestampTokenInfo = new TimestampToken(encodedTimestampTokenInfo); // Create a timestamp object timestamp = new Timestamp(timestampTokenInfo.getDate(), tsaChain); } } return timestamp; } // for the toHex function private static final char[] hexc = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; /** * convert a byte array to a hex string for debugging purposes * @param data the binary data to be converted to a hex string * @return an ASCII hex string */ static String toHex(byte[] data) { StringBuffer sb = new StringBuffer(data.length*2); for (int i=0; i<data.length; i++) { sb.append(hexc[(data[i] >>4) & 0x0f]); sb.append(hexc[data[i] & 0x0f]); } return sb.toString(); } // returns true if set contains signer static boolean contains(CodeSigner[] set, CodeSigner signer) { for (int i = 0; i < set.length; i++) { if (set[i].equals(signer)) return true; } return false; } // returns true if subset is a subset of set static boolean isSubSet(CodeSigner[] subset, CodeSigner[] set) { // check for the same object if (set == subset) return true; boolean match; for (int i = 0; i < subset.length; i++) { if (!contains(set, subset[i])) return false; } return true; } /** * returns true if signer contains exactly the same code signers as * oldSigner and newSigner, false otherwise. oldSigner * is allowed to be null. */ static boolean matches(CodeSigner[] signers, CodeSigner[] oldSigners, CodeSigner[] newSigners) { // special case if ((oldSigners == null) && (signers == newSigners)) return true; boolean match; // make sure all oldSigners are in signers if ((oldSigners != null) && !isSubSet(oldSigners, signers)) return false; // make sure all newSigners are in signers if (!isSubSet(newSigners, signers)) { return false; } // now make sure all the code signers in signers are // also in oldSigners or newSigners for (int i = 0; i < signers.length; i++) { boolean found = ((oldSigners != null) && contains(oldSigners, signers[i])) || contains(newSigners, signers[i]); if (!found) return false; } return true; } void updateSigners(CodeSigner[] newSigners, Hashtable<String, CodeSigner[]> signers, String name) { CodeSigner[] oldSigners = signers.get(name); // search through the cache for a match, go in reverse order // as we are more likely to find a match with the last one // added to the cache CodeSigner[] cachedSigners; for (int i = signerCache.size() - 1; i != -1; i--) { cachedSigners = signerCache.get(i); if (matches(cachedSigners, oldSigners, newSigners)) { signers.put(name, cachedSigners); return; } } if (oldSigners == null) { cachedSigners = newSigners; } else { cachedSigners = new CodeSigner[oldSigners.length + newSigners.length]; System.arraycopy(oldSigners, 0, cachedSigners, 0, oldSigners.length); System.arraycopy(newSigners, 0, cachedSigners, oldSigners.length, newSigners.length); } signerCache.add(cachedSigners); signers.put(name, cachedSigners); }}Lines 501–671 of 671. Previous lines
} /* * Examines a signature timestamp token to generate a timestamp object. * * Examines the signer's unsigned attributes for a * <tt>signatureTimestampToken</tt> attribute. If present, * then it is parsed to extract the date and time at which the * timestamp was generated. * * @param info A signer information element of a PKCS 7 block. * * @return A timestamp token or null if none is present. * @throws IOException if an error is encountered while parsing the * PKCS7 data. * @throws NoSuchAlgorithmException if an error is encountered while * verifying the PKCS7 object. * @throws SignatureException if an error is encountered while * verifying the PKCS7 object. * @throws CertificateException if an error is encountered while generating * the TSA's certpath. */ private Timestamp getTimestamp(SignerInfo info) throws IOException, NoSuchAlgorithmException, SignatureException, CertificateException { Timestamp timestamp = null; // Extract the signer's unsigned attributes PKCS9Attributes unsignedAttrs = info.getUnauthenticatedAttributes(); if (unsignedAttrs != null) { PKCS9Attribute timestampTokenAttr = unsignedAttrs.getAttribute("signatureTimestampToken"); if (timestampTokenAttr != null) { PKCS7 timestampToken = new PKCS7((byte[])timestampTokenAttr.getValue()); // Extract the content (an encoded timestamp token info) byte[] encodedTimestampTokenInfo = timestampToken.getContentInfo().getData(); // Extract the signer (the Timestamping Authority) // while verifying the content SignerInfo[] tsa = timestampToken.verify(encodedTimestampTokenInfo); // Expect only one signer ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(timestampToken); CertPath tsaChain = certificateFactory.generateCertPath(chain); // Create a timestamp token info object TimestampToken timestampTokenInfo = new TimestampToken(encodedTimestampTokenInfo); // Create a timestamp object timestamp = new Timestamp(timestampTokenInfo.getDate(), tsaChain); } } return timestamp; } // for the toHex function private static final char[] hexc = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; /** * convert a byte array to a hex string for debugging purposes * @param data the binary data to be converted to a hex string * @return an ASCII hex string */ static String toHex(byte[] data) { StringBuffer sb = new StringBuffer(data.length*2); for (int i=0; i<data.length; i++) { sb.append(hexc[(data[i] >>4) & 0x0f]); sb.append(hexc[data[i] & 0x0f]); } return sb.toString(); } // returns true if set contains signer static boolean contains(CodeSigner[] set, CodeSigner signer) { for (int i = 0; i < set.length; i++) { if (set[i].equals(signer)) return true; } return false; } // returns true if subset is a subset of set static boolean isSubSet(CodeSigner[] subset, CodeSigner[] set) { // check for the same object if (set == subset) return true; boolean match; for (int i = 0; i < subset.length; i++) { if (!contains(set, subset[i])) return false; } return true; } /** * returns true if signer contains exactly the same code signers as * oldSigner and newSigner, false otherwise. oldSigner * is allowed to be null. */ static boolean matches(CodeSigner[] signers, CodeSigner[] oldSigners, CodeSigner[] newSigners) { // special case if ((oldSigners == null) && (signers == newSigners)) return true; boolean match; // make sure all oldSigners are in signers if ((oldSigners != null) && !isSubSet(oldSigners, signers)) return false; // make sure all newSigners are in signers if (!isSubSet(newSigners, signers)) { return false; } // now make sure all the code signers in signers are // also in oldSigners or newSigners for (int i = 0; i < signers.length; i++) { boolean found = ((oldSigners != null) && contains(oldSigners, signers[i])) || contains(newSigners, signers[i]); if (!found) return false; } return true; } void updateSigners(CodeSigner[] newSigners, Hashtable<String, CodeSigner[]> signers, String name) { CodeSigner[] oldSigners = signers.get(name); // search through the cache for a match, go in reverse order // as we are more likely to find a match with the last one // added to the cache CodeSigner[] cachedSigners; for (int i = signerCache.size() - 1; i != -1; i--) { cachedSigners = signerCache.get(i); if (matches(cachedSigners, oldSigners, newSigners)) { signers.put(name, cachedSigners); return; } } if (oldSigners == null) { cachedSigners = newSigners; } else { cachedSigners = new CodeSigner[oldSigners.length + newSigners.length]; System.arraycopy(oldSigners, 0, cachedSigners, 0, oldSigners.length); System.arraycopy(newSigners, 0, cachedSigners, oldSigners.length, newSigners.length); } signerCache.add(cachedSigners); signers.put(name, cachedSigners); } }