/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* <p>The jarsigner utility.
*
* The exit codes for the main method are:
*
* 0: success
* 1: any error that the jar cannot be signed or verified, including:
* keystore loading error
* TSP communication error
* jarsigner command line error...
* otherwise: error codes from -strict
*
* @author Roland Schemers
* @author Jan Luehe
*/
public class JarSigner {
// for i18n
("sun.security.tools.JarSignerResources");
static {
// this is for case insensitive string comparisions
}
// prefix for new signature-related files in META-INF directory
// Attention:
// This is the entry that get launched by the security tool jarsigner.
}
// signer is not in alias list
// or the default keystore, never null
// arguments for provider constructors
// read zip entry raw bytes
private boolean hasExpiredCert = false;
private boolean hasExpiringCert = false;
private boolean notYetValidCert = false;
private boolean chainNotValidated = false;
private boolean notSignedByAlias = false;
private boolean aliasNotInStore = false;
private boolean hasUnsignedEntry = false;
private boolean badKeyUsage = false;
private boolean badExtendedKeyUsage = false;
private boolean badNetscapeCertType = false;
try {
// Try to load and install the specified providers
while (e.hasMoreElements()) {
} else {
}
} else {
Constructor<?> c =
}
("provName.not.a.provider"));
}
}
}
if (verify) {
try {
loadKeyStore(keystore, false);
} catch (Exception e) {
e.getMessage());
}
}
/* if (debug) {
SignatureFileVerifier.setDebug(true);
ManifestEntryVerifier.setDebug(true);
}
*/
} else {
loadKeyStore(keystore, true);
// load the alternative signing mechanism
if (altSignerClass != null) {
}
}
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
} finally {
// zero-out private key password
}
// zero-out keystore password
}
}
if (strict) {
int exitCode = 0;
if (hasExpiringCert) {
exitCode |= 2;
}
exitCode |= 4;
}
exitCode |= 8;
}
if (hasUnsignedEntry) {
exitCode |= 16;
}
if (notSignedByAlias || aliasNotInStore) {
exitCode |= 32;
}
if (exitCode != 0) {
}
}
}
/*
* Parse command line arguments.
*/
/* parse flags */
int n = 0;
if (pos > 0) {
}
}
providerName = args[n];
}
n += 2;
}
}
protectedPath = true;
altCertChain = args[n];
debug = true;
altSignerClass = args[n];
altSignerClasspath = args[n];
signManifest = false;
externalSF = false;
verify = true;
showcerts = true;
strict = true;
fullusage();
} else {
} else {
}
} else {
usage();
}
}
}
// -certs must always be specified with -verbose
usage();
}
usage();
}
usage();
}
}
try {
}
} catch (IOException ioe) {
// File system error?
// Just ignore it.
}
token = true;
}
}
nullStream = true;
}
if (token && !nullStream) {
(".keystore.must.be.NONE.if.storetype.is.{0}"), storetype));
usage();
}
(".keypass.can.not.be.specified.if.storetype.is.{0}"), storetype));
usage();
}
if (protectedPath) {
("If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified"));
usage();
}
}
("If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified"));
usage();
}
}
}
usage();
return null; // Useless, usage() already exit
}
static void usageNoArg() {
usage();
}
static void usage() {
}
static void fullusage() {
("Usage.jarsigner.options.jar.file.alias"));
(".jarsigner.verify.options.jar.file.alias."));
(".keystore.url.keystore.location"));
(".storepass.password.password.for.keystore.integrity"));
(".storetype.type.keystore.type"));
(".keypass.password.password.for.private.key.if.different."));
(".certchain.file.name.of.alternative.certchain.file"));
(".sigfile.file.name.of.SF.DSA.file"));
(".signedjar.file.name.of.signed.JAR.file"));
(".digestalg.algorithm.name.of.digest.algorithm"));
(".sigalg.algorithm.name.of.signature.algorithm"));
(".verify.verify.a.signed.JAR.file"));
(".verbose.suboptions.verbose.output.when.signing.verifying."));
(".suboptions.can.be.all.grouped.or.summary"));
(".certs.display.certificates.when.verbose.and.verifying"));
(".tsa.url.location.of.the.Timestamping.Authority"));
(".tsacert.alias.public.key.certificate.for.Timestamping.Authority"));
(".altsigner.class.class.name.of.an.alternative.signing.mechanism"));
(".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism"));
(".internalsf.include.the.SF.file.inside.the.signature.block"));
(".sectionsonly.don.t.compute.hash.of.entire.manifest"));
(".protected.keystore.has.protected.authentication.path"));
(".providerName.name.provider.name"));
(".providerClass.class.name.of.cryptographic.service.provider.s"));
(".providerArg.arg.master.class.file.and.constructor.argument"));
(".strict.treat.warnings.as.errors"));
}
throws Exception
{
boolean anySigned = false; // if there exists entry inside jar signed
try {
byte[] buffer = new byte[8192];
while (entries.hasMoreElements()) {
try {
int n;
// we just read. this will throw a SecurityException
}
} finally {
}
}
}
// The map to record display info, only used when -verbose provided
// key: signer info string
// value: the list of files with common key
while (e.hasMoreElements()) {
&& !signatureRelated(name);
}
// Only used when -verbose provided
sb = new StringBuffer();
boolean inManifest =
}
// When -certs provided, display info has extra empty
// lines at the beginning and end.
if (isSigned) {
// signerInfo() must be called even if -verbose
// not provided. The method updates various
// warning flags.
if (showcerts) {
}
}
// Print no info for unsigned entries when -verbose:all,
// to be consistent with old behavior.
if (signatureRelated(name)) {
".Signature.related.entries.") + "\n\n");
} else {
".Unsigned.entries.") + "\n\n");
}
}
if (signatureRelated(name)) {
// Entries inside META-INF and other unsigned
// entries are grouped separately.
}
// The label finally contains 2 parts separated by '|':
// The legend displayed before the entry names, and
// the cert info (if -certs specfied).
}
}
}
}
}
}
}
} else {
}
} else {
}
}
}
}
".s.signature.was.verified."));
".m.entry.is.listed.in.manifest"));
".k.at.least.one.certificate.was.found.in.keystore"));
".i.at.least.one.certificate.was.found.in.identity.scope"));
".X.not.signed.by.specified.alias.es."));
}
}
if (!anySigned) {
"jar.is.unsigned.signatures.missing.or.not.parsable."));
} else {
if (badKeyUsage) {
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
}
if (badExtendedKeyUsage) {
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
}
if (badNetscapeCertType) {
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
}
if (hasUnsignedEntry) {
"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
}
if (hasExpiredCert) {
"This.jar.contains.entries.whose.signer.certificate.has.expired."));
}
if (hasExpiringCert) {
"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
}
if (notYetValidCert) {
"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
}
if (chainNotValidated) {
}
if (notSignedByAlias) {
}
if (aliasNotInStore) {
System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
}
"Re.run.with.the.verbose.and.certs.options.for.more.details."));
}
}
}
return;
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
} finally { // close the resource
}
}
}
/*
* Display some details about a certificate:
*
* [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"]
* [<validity-period> | <expiry-warning>]
*
* Note: no newline character at the end
*/
if (c instanceof X509Certificate) {
x509Cert = (X509Certificate) c;
} else {
}
}
try {
boolean printValidity = true;
// test if cert will expire within six months
hasExpiringCert = true;
if (expiringTimeForm == null) {
expiringTimeForm = new MessageFormat(
}
printValidity = false;
}
} else {
}
if (printValidity) {
if (validityTimeForm == null) {
validityTimeForm = new MessageFormat(
}
}
} catch (CertificateExpiredException cee) {
hasExpiredCert = true;
if (expiredTimeForm == null) {
expiredTimeForm = new MessageFormat(
}
} catch (CertificateNotYetValidException cnyve) {
notYetValidCert = true;
if (notYetTimeForm == null) {
notYetTimeForm = new MessageFormat(
}
}
if (checkUsage) {
boolean[] bad = new boolean[3];
String x = "";
if (bad[0]) {
x ="KeyUsage";
}
if (bad[1]) {
x = x + "ExtendedKeyUsage";
}
if (bad[2]) {
x = x + "NetscapeCertType";
}
".{0}.extension.does.not.support.code.signing."), x));
}
}
}
}
if (signTimeForm == null) {
}
}
}
boolean found = false;
int result = 0;
for (Certificate c : certs) {
result |= IN_KEYSTORE;
}
}
} else {
try {
} catch (KeyStoreException kse) {
// never happens, because keystore has been loaded
}
found = true;
result |= IN_KEYSTORE;
}
}
}
}
}
return result;
}
return 0;
int output = 0;
}
}
return output;
}
throws Exception {
boolean aliasUsed = false;
aliasUsed = true;
}
} else {
}
if (!
((c>= 'A' && c<= 'Z') ||
(c>= '0' && c<= '9') ||
(c == '-') ||
(c == '_'))) {
if (aliasUsed) {
// convert illegal characters from the alias to be _'s
c = '_';
} else {
throw new
("signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or."));
}
}
tmpSigFile.append(c);
}
else tmpJarName = signedjar;
// Open the jar (zip) file
try {
} catch (IOException ioe) {
}
try {
} catch (IOException ioe) {
}
/* First guess at what they might be - we don't xclude RSA ones. */
// The Attributes of manifest before updating
boolean mfModified = false;
boolean mfCreated = false;
byte[] mfRawBytes = null;
try {
// Check if manifest exists
// Manifest exists. Read its raw bytes.
} else {
// Create new manifest
"1.0");
+ ")");
mfCreated = true;
}
/*
* For each entry in jar
* (except for signature-related META-INF entries),
* do the following:
*
* - if entry is not contained in manifest, add it to manifest;
* - if entry is contained in manifest, calculate its hash and
* compare it with the one in the manifest; if they are
* different, replace the hash in the manifest with the newly
* generated one. (This may invalidate existing signatures!)
*/
boolean wasSigned = false;
enum_.hasMoreElements();) {
// Store META-INF files in vector, so they can be written
// out first
wasSigned = true;
}
// ignore signature-related and manifest files
continue;
}
}
// jar entry is contained in manifest, check and
// possibly update its digest attributes
manifest) == true) {
mfModified = true;
}
} else if (!ze.isDirectory()) {
// Add entry to manifest
encoder);
mfModified = true;
}
}
// Recalculate the manifest raw bytes if necessary
if (mfModified) {
if (wasSigned) {
if (mfRawBytes != null
/*
* Note:
*
* The Attributes object is based on HashMap and can handle
* continuation columns. Therefore, even if the contents are
* not changed (in a Map view), the bytes that it write()
* may be different from the original bytes that it read()
* from. Since the signature on the main attributes is based
* on raw bytes, we must retain the exact bytes.
*/
} else {
// cat oldHead newTail > newBytes
}
}
} else {
}
}
// Write out the manifest
if (mfModified) {
// manifest file has new length
}
if (mfCreated) {
} else if (mfModified) {
}
}
// Calculate SignatureFile (".SF") and SignatureBlockFile
}
try {
block =
zipFile);
} catch (SocketTimeoutException e) {
// Provide a helpful message when TSA is beyond a firewall
"\n -J-Dhttp.proxyHost=<hostname>" +
"\n -J-Dhttp.proxyPort=<portnumber>\n" +
"\n -J-Dhttps.proxyHost=<hostname> " +
"\n -J-Dhttps.proxyPort=<portnumber> ", e);
}
// signature file
} else {
}
}
}
}
certUrl);
}
}
if (signingMechanism != null) {
}
}
// signature block file
} else {
}
}
// Write out all other META-INF files that we stored in the
// vector
}
}
// Write out all other files
enum_.hasMoreElements();) {
else
}
}
}
} catch(IOException ioe) {
} finally {
// close the resouces
}
}
}
// no IOException thrown in the follow try clause, so disable
// the try clause.
// try {
// attempt an atomic rename. If that fails,
// rename the original jar file, then the signed
// one, then delete the original.
} else {
("attempt.to.rename.signedJarFile.to.jarFile.failed"));
}
} else {
("attempt.to.rename.jarFile.to.origJar.failed"));
}
}
}
|| badNetscapeCertType || chainNotValidated) {
if (badKeyUsage) {
}
if (badExtendedKeyUsage) {
}
if (badNetscapeCertType) {
}
if (hasExpiredCert) {
} else if (hasExpiringCert) {
} else if (notYetValidCert) {
}
if (chainNotValidated) {
}
}
// no IOException thrown in the above try clause, so disable
// the catch clause.
// } catch(IOException ioe) {
// error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
// }
}
/**
* Find the length of header inside bs. The header is a multiple (>=0)
* lines of attributes plus an empty line. The empty line is included
* in the header.
*/
// Initial state true to deal with empty header
boolean newline = true; // just met a newline
for (int i=0; i<len; i++) {
switch (bs[i]) {
case '\r':
// fallthrough
case '\n':
newline = true;
break;
default:
newline = false;
}
}
// If header end is not found, it means the MANIFEST.MF has only
// the main attributes section and it does not end with 2 newlines.
// Returns the whole length so that it can be completely replaced.
return len;
}
/**
* signature-related files include:
* . META-INF/MANIFEST.MF
* . META-INF/*.SF
* . META-INF/*.DSA
* . META-INF/*.RSA
* . META-INF/*.EC
*/
return true;
}
// .SF/.DSA/.RSA/.EC files in META-INF subdirs
// are not considered signature-related
}
return false;
}
/**
* Returns a string of singer info, with a newline at the end
*/
}
StringBuffer s = new StringBuffer();
// display the signature timestamp, if present
s.append('\n');
} else {
}
// display the certificate(s). The first one is end-entity cert and
// its KeyUsage should be checked.
boolean first = true;
for (Certificate c : certs) {
s.append('\n');
first = false;
}
try {
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
(e.getCause() instanceof CertificateExpiredException ||
e.getCause() instanceof CertificateNotYetValidException)) {
// No more warning, we alreay have hasExpiredCert or notYetValidCert
} else {
chainNotValidated = true;
}
}
return result;
}
throws IOException
{
}
}
/**
* Writes all the bytes for a given entry to the specified output stream.
*/
private synchronized void writeBytes
int n;
try {
left -= n;
}
} finally {
}
}
}
+ ".keystore";
}
try {
try {
while (aliases.hasMoreElements()) {
try {
// ignore, when a SecretkeyEntry does not include a cert
}
}
}
} catch (Exception e) {
// Ignore, if cacerts cannot be loaded
}
if (providerName == null) {
} else {
}
// Get pass phrase
// XXX need to disable echo; on UNIX, call getpass(char *prompt)Z
// and on NT call ??
}
try {
if (nullStream) {
} else {
try {
// try as file
}
try {
} finally {
}
}
}
while (aliases.hasMoreElements()) {
try {
// Only add TrustedCertificateEntry and self-signed
// PrivateKeyEntry
if (store.isCertificateEntry(a) ||
}
// ignore, when a SecretkeyEntry does not include a cert
}
}
} finally {
try {
pkixParameters.setRevocationEnabled(false);
} catch (InvalidAlgorithmParameterException ex) {
// Only if tas is empty
}
}
} catch (IOException ioe) {
ioe.getMessage());
ce.getMessage());
} catch (NoSuchProviderException pe) {
pe.getMessage());
} catch (NoSuchAlgorithmException nsae) {
nsae.getMessage());
} catch (KeyStoreException kse) {
throw new RuntimeException
kse.getMessage());
}
}
try {
} catch (KeyStoreException kse) {
// this never happens, because keystore has been loaded
}
("Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the"));
}
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.
*/
// 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
}
bad[0] = true;
badKeyUsage = true;
}
}
}
try {
bad[1] = true;
badExtendedKeyUsage = true;
}
}
}
// shouldn't happen
}
try {
// OID_NETSCAPE_CERT_TYPE
("2.16.840.1.113730.1.1");
if (netscapeEx != null) {
.toByteArray();
if (!val) {
bad[2] = true;
badNetscapeCertType = true;
}
}
}
} catch (IOException e) {
//
}
}
try {
if (altCertChain != null) {
try {
} catch (CertificateException ex) {
} catch (FileNotFoundException ex) {
}
} else {
try {
} catch (KeyStoreException kse) {
// this never happens, because keystore has been loaded
}
}
if (altCertChain != null) {
("Certificate.chain.not.found.in.the.file.specified."));
} else {
("Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and"));
}
}
if (!(cs[i] instanceof X509Certificate)) {
("found.non.X.509.certificate.in.signer.s.chain"));
}
}
// We don't meant to print anything, the next call
// checks validity and keyUsage etc
try {
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
(e.getCause() instanceof CertificateExpiredException ||
e.getCause() instanceof CertificateNotYetValidException)) {
// No more warning, we alreay have hasExpiredCert or notYetValidCert
} else {
chainNotValidated = true;
}
}
try {
else
} catch (UnrecoverableKeyException e) {
if (token) {
throw e;
// Did not work out, so prompt user for key password
("Enter.key.password.for.alias."));
}
}
} catch (NoSuchAlgorithmException e) {
error(e.getMessage());
} catch (UnrecoverableKeyException e) {
} catch (KeyStoreException kse) {
// this never happens, because keystore has been loaded
}
if (!(key instanceof PrivateKey)) {
("key.associated.with.alias.not.a.private.key"));
} else {
}
}
{
}
{
if (debug) {
e.printStackTrace();
}
}
{
try {
} else {
return pass;
}
} catch (IOException ioe) {
}
// this shouldn't happen
return null;
}
/*
* Reads all the bytes for a given zip entry.
*/
int n;
try {
left -= n;
}
} finally {
}
}
return baos.toByteArray();
}
/*
* Returns manifest entry from given jar file, or null if given jar file
* does not have a manifest entry.
*/
// Check all entries for matching name
}
}
}
return ze;
}
/*
* Computes the digests of a zip entry, and returns them as an array
* of base64-encoded strings.
*/
throws IOException {
int n, i;
try {
while((left > 0)
}
left -= n;
}
} finally {
}
}
// complete the digests
}
return base64Digests;
}
/*
* Computes the digests of a zip entry, and returns them as a list of
* attributes
*/
throws IOException {
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.
*/
boolean update = false;
// The entry name to be written into attrs
try {
// Find if the digest already exists
name = n;
break;
}
}
}
}
} catch (NoSuchAlgorithmException nsae) {
// Ignored. Writing new digest entry.
}
update=true;
} else {
// compare digests, and replace the one in the manifest
// if they are different
update=true;
}
}
}
return update;
}
/*
* Try to load the specified signing mechanism.
* The URL class loader is used.
*/
// construct class loader
// do prepends to get correct ordering
// attempt to find signer
// Check that it implements ContentSigner
if (!(signer instanceof ContentSigner)) {
}
return (ContentSigner)signer;
}
}
/**
* This is a BASE64Encoder that does not insert a default newline at the end of
* every output line. This is necessary because java.util.jar does its own
* line management (see Manifest.make72Safe()). Inserting additional new lines
* can cause line-wrapping problems (see CR 6219522).
*/
/**
* Encode the suffix that ends every output line.
*/
}
class SignatureFile {
/** SignatureFile */
/** .SF base name */
boolean signManifest)
{
if (signManifest) {
// sign the whole manifest
}
}
// create digest of the manifest main attributes
}
} else {
throw new IllegalStateException
("ManifestDigester failed to create " +
"Manifest-Main-Attribute entry");
}
/* go through the manifest entries and create the digests */
}
}
}
}
/**
* Writes the SignatureFile to the specified OutputStream.
*
* @param out the output stream
* @exception IOException if an I/O error has occurred
*/
{
}
/**
* get .SF file name
*/
{
}
/**
* get base file name
*/
{
return baseName;
}
/*
* Generate a signed data block.
* If a URL or a certificate (containing a URL) for a Timestamping
* Authority is supplied then a signature timestamp is generated and
* inserted into the signed data block.
*
* @param sigalg signature algorithm to use, or null to use default
* @param tsaUrl The location of the Timestamping Authority. If null
* then no timestamp is requested.
* @param tsaCert The certificate for the Timestamping Authority. If null
* then no timestamp is requested.
* @param signingMechanism The signing mechanism to use.
* @param args The command-line arguments to jarsigner.
* @param zipFile The original source Zip file.
*/
{
}
public static class Block {
private byte[] block;
/*
* Construct a new signature block.
*/
if (!(issuerName instanceof X500Name)) {
// must extract the original encoded form of DN for subsequent
// name comparison checks (converting to a String and back to
// an encoded DN could cause the types of String attribute
// values to be changed)
X509CertInfo tbsCert = new
issuerName = (Principal)
}
/*
* If no signature algorithm was specified, we choose a
* default that is compatible with the private key algorithm.
*/
signatureAlgorithm = "SHA1withDSA";
signatureAlgorithm = "SHA256withRSA";
signatureAlgorithm = "SHA256withECDSA";
else
throw new RuntimeException("private key is not a DSA or "
+ "RSA key");
} else {
}
throw new SignatureException
("private key algorithm is not compatible with signature algorithm");
}
// Timestamp the signature and generate the signature block file
if (signingMechanism == null) {
signingMechanism = new TimestampedSigner();
}
try {
}
} catch (URISyntaxException e) {
throw ioe;
}
// Assemble parameters for the signing mechanism
// Generate the signature block
}
/*
* get block file name.
*/
{
return blockFileName;
}
/**
* Writes the block file to the specified OutputStream.
*
* @param out the output stream
* @exception IOException if an I/O error has occurred
*/
{
}
}
}
/*
* This object encapsulates the parameters used to perform content signing.
*/
private byte[] signature;
private byte[] content;
/**
* Create a new object.
*/
signerCertificateChain == null) {
throw new NullPointerException();
}
this.tsaCertificate = tsaCertificate;
this.signatureAlgorithm = signatureAlgorithm;
}
/**
* Retrieves the command-line arguments.
*
* @return The command-line arguments. May be null.
*/
return args;
}
/**
* Retrieves the identifier for a Timestamping Authority (TSA).
*
* @return The TSA identifier. May be null.
*/
return tsa;
}
/**
* Retrieves the certificate for a Timestamping Authority (TSA).
*
* @return The TSA certificate. May be null.
*/
return tsaCertificate;
}
/**
* Retrieves the signature.
*
* @return The non-null signature bytes.
*/
public byte[] getSignature() {
return signature;
}
/**
* Retrieves the name of the signature algorithm.
*
* @return The non-null string name of the signature algorithm.
*/
return signatureAlgorithm;
}
/**
* Retrieves the signer's X.509 certificate chain.
*
* @return The non-null array of X.509 public-key certificates.
*/
return signerCertificateChain;
}
/**
* Retrieves the content that was signed.
*
* @return The content bytes. May be null.
*/
public byte[] getContent() {
return content;
}
/**
* Retrieves the original source ZIP file before it was signed.
*
* @return The original ZIP file. May be null.
*/
return source;
}
}