Example usage for org.bouncycastle.asn1.cms ContentInfo ContentInfo

List of usage examples for org.bouncycastle.asn1.cms ContentInfo ContentInfo

Introduction

In this page you can find the example usage for org.bouncycastle.asn1.cms ContentInfo ContentInfo.

Prototype

public ContentInfo(ASN1Sequence seq) 

Source Link

Usage

From source file:com.itextpdf.text.pdf.PdfPKCS7.java

License:Open Source License

/**
 * Verifies a signature using the sub-filter adbe.pkcs7.detached or
 * adbe.pkcs7.sha1./*from  w w  w.  j ava 2s  . com*/
 * @param contentsKey the /Contents key
 * @param provider the provider or <code>null</code> for the default provider
 */
@SuppressWarnings("unchecked")
public PdfPKCS7(byte[] contentsKey, String provider) {
    try {
        this.provider = provider;
        ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey));

        //
        // Basic checks to make sure it's a PKCS#7 SignedData Object
        //
        DERObject pkcs;

        try {
            pkcs = din.readObject();
        } catch (IOException e) {
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("can.t.decode.pkcs7signeddata.object"));
        }
        if (!(pkcs instanceof ASN1Sequence)) {
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("not.a.valid.pkcs.7.object.not.a.sequence"));
        }
        ASN1Sequence signedData = (ASN1Sequence) pkcs;
        DERObjectIdentifier objId = (DERObjectIdentifier) signedData.getObjectAt(0);
        if (!objId.getId().equals(ID_PKCS7_SIGNED_DATA))
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("not.a.valid.pkcs.7.object.not.signed.data"));
        ASN1Sequence content = (ASN1Sequence) ((DERTaggedObject) signedData.getObjectAt(1)).getObject();
        // the positions that we care are:
        //     0 - version
        //     1 - digestAlgorithms
        //     2 - possible ID_PKCS7_DATA
        //     (the certificates and crls are taken out by other means)
        //     last - signerInfos

        // the version
        version = ((DERInteger) content.getObjectAt(0)).getValue().intValue();

        // the digestAlgorithms
        digestalgos = new HashSet<String>();
        Enumeration<ASN1Sequence> e = ((ASN1Set) content.getObjectAt(1)).getObjects();
        while (e.hasMoreElements()) {
            ASN1Sequence s = e.nextElement();
            DERObjectIdentifier o = (DERObjectIdentifier) s.getObjectAt(0);
            digestalgos.add(o.getId());
        }

        // the certificates
        X509CertParser cr = new X509CertParser();
        cr.engineInit(new ByteArrayInputStream(contentsKey));
        certs = cr.engineReadAll();

        // the possible ID_PKCS7_DATA
        ASN1Sequence rsaData = (ASN1Sequence) content.getObjectAt(2);
        if (rsaData.size() > 1) {
            DEROctetString rsaDataContent = (DEROctetString) ((DERTaggedObject) rsaData.getObjectAt(1))
                    .getObject();
            RSAdata = rsaDataContent.getOctets();
        }

        // the signerInfos
        int next = 3;
        while (content.getObjectAt(next) instanceof DERTaggedObject)
            ++next;
        ASN1Set signerInfos = (ASN1Set) content.getObjectAt(next);
        if (signerInfos.size() != 1)
            throw new IllegalArgumentException(MessageLocalization.getComposedMessage(
                    "this.pkcs.7.object.has.multiple.signerinfos.only.one.is.supported.at.this.time"));
        ASN1Sequence signerInfo = (ASN1Sequence) signerInfos.getObjectAt(0);
        // the positions that we care are
        //     0 - version
        //     1 - the signing certificate issuer and serial number
        //     2 - the digest algorithm
        //     3 or 4 - digestEncryptionAlgorithm
        //     4 or 5 - encryptedDigest
        signerversion = ((DERInteger) signerInfo.getObjectAt(0)).getValue().intValue();
        // Get the signing certificate
        ASN1Sequence issuerAndSerialNumber = (ASN1Sequence) signerInfo.getObjectAt(1);
        X509Principal issuer = new X509Principal(
                issuerAndSerialNumber.getObjectAt(0).getDERObject().getEncoded());
        BigInteger serialNumber = ((DERInteger) issuerAndSerialNumber.getObjectAt(1)).getValue();
        for (Object element : certs) {
            X509Certificate cert = (X509Certificate) element;
            if (issuer.equals(cert.getIssuerDN()) && serialNumber.equals(cert.getSerialNumber())) {
                signCert = cert;
                break;
            }
        }
        if (signCert == null) {
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("can.t.find.signing.certificate.with.serial.1",
                            issuer.getName() + " / " + serialNumber.toString(16)));
        }
        signCertificateChain();
        digestAlgorithm = ((DERObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(2)).getObjectAt(0))
                .getId();
        next = 3;
        if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) {
            ASN1TaggedObject tagsig = (ASN1TaggedObject) signerInfo.getObjectAt(next);
            ASN1Set sseq = ASN1Set.getInstance(tagsig, false);
            sigAttr = sseq.getEncoded(ASN1Encodable.DER);

            for (int k = 0; k < sseq.size(); ++k) {
                ASN1Sequence seq2 = (ASN1Sequence) sseq.getObjectAt(k);
                if (((DERObjectIdentifier) seq2.getObjectAt(0)).getId().equals(ID_MESSAGE_DIGEST)) {
                    ASN1Set set = (ASN1Set) seq2.getObjectAt(1);
                    digestAttr = ((DEROctetString) set.getObjectAt(0)).getOctets();
                } else if (((DERObjectIdentifier) seq2.getObjectAt(0)).getId().equals(ID_ADBE_REVOCATION)) {
                    ASN1Set setout = (ASN1Set) seq2.getObjectAt(1);
                    ASN1Sequence seqout = (ASN1Sequence) setout.getObjectAt(0);
                    for (int j = 0; j < seqout.size(); ++j) {
                        ASN1TaggedObject tg = (ASN1TaggedObject) seqout.getObjectAt(j);
                        if (tg.getTagNo() == 0) {
                            ASN1Sequence seqin = (ASN1Sequence) tg.getObject();
                            findCRL(seqin);
                        }
                        if (tg.getTagNo() == 1) {
                            ASN1Sequence seqin = (ASN1Sequence) tg.getObject();
                            findOcsp(seqin);
                        }
                    }
                }
            }
            if (digestAttr == null)
                throw new IllegalArgumentException(MessageLocalization
                        .getComposedMessage("authenticated.attribute.is.missing.the.digest"));
            ++next;
        }
        digestEncryptionAlgorithm = ((DERObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(next++))
                .getObjectAt(0)).getId();
        digest = ((DEROctetString) signerInfo.getObjectAt(next++)).getOctets();
        if (next < signerInfo.size() && signerInfo.getObjectAt(next) instanceof DERTaggedObject) {
            DERTaggedObject taggedObject = (DERTaggedObject) signerInfo.getObjectAt(next);
            ASN1Set unat = ASN1Set.getInstance(taggedObject, false);
            AttributeTable attble = new AttributeTable(unat);
            Attribute ts = attble.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
            if (ts != null && ts.getAttrValues().size() > 0) {
                ASN1Set attributeValues = ts.getAttrValues();
                ASN1Sequence tokenSequence = ASN1Sequence.getInstance(attributeValues.getObjectAt(0));
                ContentInfo contentInfo = new ContentInfo(tokenSequence);
                this.timeStampToken = new TimeStampToken(contentInfo);
            }
        }
        if (RSAdata != null || digestAttr != null) {
            if (provider == null || provider.startsWith("SunPKCS11"))
                messageDigest = MessageDigest.getInstance(getHashAlgorithm());
            else
                messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider);
        }
        if (provider == null)
            sig = Signature.getInstance(getDigestAlgorithm());
        else
            sig = Signature.getInstance(getDigestAlgorithm(), provider);
        sig.initVerify(signCert.getPublicKey());
    } catch (Exception e) {
        throw new ExceptionConverter(e);
    }
}

From source file:com.itextpdf.text.pdf.security.PdfPKCS7.java

License:Open Source License

/**
 * Use this constructor if you want to verify a signature.
 * @param contentsKey the /Contents key/*from   w ww .  j  av a2s  .  c  o m*/
 * @param filterSubtype the filtersubtype
 * @param provider the provider or <code>null</code> for the default provider
 */
@SuppressWarnings({ "unchecked" })
public PdfPKCS7(byte[] contentsKey, PdfName filterSubtype, String provider) {
    this.filterSubtype = filterSubtype;
    isTsp = PdfName.ETSI_RFC3161.equals(filterSubtype);
    isCades = PdfName.ETSI_CADES_DETACHED.equals(filterSubtype);
    try {
        this.provider = provider;
        ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey));

        //
        // Basic checks to make sure it's a PKCS#7 SignedData Object
        //
        ASN1Primitive pkcs;

        try {
            pkcs = din.readObject();
        } catch (IOException e) {
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("can.t.decode.pkcs7signeddata.object"));
        }
        if (!(pkcs instanceof ASN1Sequence)) {
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("not.a.valid.pkcs.7.object.not.a.sequence"));
        }
        ASN1Sequence signedData = (ASN1Sequence) pkcs;
        ASN1ObjectIdentifier objId = (ASN1ObjectIdentifier) signedData.getObjectAt(0);
        if (!objId.getId().equals(SecurityIDs.ID_PKCS7_SIGNED_DATA))
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("not.a.valid.pkcs.7.object.not.signed.data"));
        ASN1Sequence content = (ASN1Sequence) ((ASN1TaggedObject) signedData.getObjectAt(1)).getObject();
        // the positions that we care are:
        //     0 - version
        //     1 - digestAlgorithms
        //     2 - possible ID_PKCS7_DATA
        //     (the certificates and crls are taken out by other means)
        //     last - signerInfos

        // the version
        version = ((ASN1Integer) content.getObjectAt(0)).getValue().intValue();

        // the digestAlgorithms
        digestalgos = new HashSet<String>();
        Enumeration<ASN1Sequence> e = ((ASN1Set) content.getObjectAt(1)).getObjects();
        while (e.hasMoreElements()) {
            ASN1Sequence s = e.nextElement();
            ASN1ObjectIdentifier o = (ASN1ObjectIdentifier) s.getObjectAt(0);
            digestalgos.add(o.getId());
        }

        // the possible ID_PKCS7_DATA
        ASN1Sequence rsaData = (ASN1Sequence) content.getObjectAt(2);
        if (rsaData.size() > 1) {
            ASN1OctetString rsaDataContent = (ASN1OctetString) ((ASN1TaggedObject) rsaData.getObjectAt(1))
                    .getObject();
            RSAdata = rsaDataContent.getOctets();
        }

        int next = 3;
        while (content.getObjectAt(next) instanceof ASN1TaggedObject)
            ++next;

        // the certificates
        /*
                 This should work, but that's not always the case because of a bug in BouncyCastle:
        */
        X509CertParser cr = new X509CertParser();
        cr.engineInit(new ByteArrayInputStream(contentsKey));
        certs = cr.engineReadAll();
        /*    
                    The following workaround was provided by Alfonso Massa, but it doesn't always work either.
                
                    ASN1Set certSet = null;
                    ASN1Set crlSet = null;
                    while (content.getObjectAt(next) instanceof ASN1TaggedObject) {
        ASN1TaggedObject tagged = (ASN1TaggedObject)content.getObjectAt(next);
                
        switch (tagged.getTagNo()) {
        case 0:
            certSet = ASN1Set.getInstance(tagged, false);
            break;
        case 1:
            crlSet = ASN1Set.getInstance(tagged, false);
            break;
        default:
            throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
        }
        ++next;
                    }
                    certs = new ArrayList<Certificate>(certSet.size());
                
                    CertificateFactory certFact = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
                    for (Enumeration en = certSet.getObjects(); en.hasMoreElements();) {
        ASN1Primitive obj = ((ASN1Encodable)en.nextElement()).toASN1Primitive();
        if (obj instanceof ASN1Sequence) {
           ByteArrayInputStream stream = new ByteArrayInputStream(obj.getEncoded());
           X509Certificate x509Certificate = (X509Certificate)certFact.generateCertificate(stream);
           stream.close();
        certs.add(x509Certificate);
        }
                    }
        */
        // the signerInfos
        ASN1Set signerInfos = (ASN1Set) content.getObjectAt(next);
        if (signerInfos.size() != 1)
            throw new IllegalArgumentException(MessageLocalization.getComposedMessage(
                    "this.pkcs.7.object.has.multiple.signerinfos.only.one.is.supported.at.this.time"));
        ASN1Sequence signerInfo = (ASN1Sequence) signerInfos.getObjectAt(0);
        // the positions that we care are
        //     0 - version
        //     1 - the signing certificate issuer and serial number
        //     2 - the digest algorithm
        //     3 or 4 - digestEncryptionAlgorithm
        //     4 or 5 - encryptedDigest
        signerversion = ((ASN1Integer) signerInfo.getObjectAt(0)).getValue().intValue();
        // Get the signing certificate
        ASN1Sequence issuerAndSerialNumber = (ASN1Sequence) signerInfo.getObjectAt(1);
        X509Principal issuer = new X509Principal(
                issuerAndSerialNumber.getObjectAt(0).toASN1Primitive().getEncoded());
        BigInteger serialNumber = ((ASN1Integer) issuerAndSerialNumber.getObjectAt(1)).getValue();
        for (Object element : certs) {
            X509Certificate cert = (X509Certificate) element;
            if (cert.getIssuerDN().equals(issuer) && serialNumber.equals(cert.getSerialNumber())) {
                signCert = cert;
                break;
            }
        }
        if (signCert == null) {
            throw new IllegalArgumentException(
                    MessageLocalization.getComposedMessage("can.t.find.signing.certificate.with.serial.1",
                            issuer.getName() + " / " + serialNumber.toString(16)));
        }
        signCertificateChain();
        digestAlgorithmOid = ((ASN1ObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(2)).getObjectAt(0))
                .getId();
        next = 3;
        boolean foundCades = false;
        if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) {
            ASN1TaggedObject tagsig = (ASN1TaggedObject) signerInfo.getObjectAt(next);
            ASN1Set sseq = ASN1Set.getInstance(tagsig, false);
            sigAttr = sseq.getEncoded();
            // maybe not necessary, but we use the following line as fallback:
            sigAttrDer = sseq.getEncoded(ASN1Encoding.DER);

            for (int k = 0; k < sseq.size(); ++k) {
                ASN1Sequence seq2 = (ASN1Sequence) sseq.getObjectAt(k);
                String idSeq2 = ((ASN1ObjectIdentifier) seq2.getObjectAt(0)).getId();
                if (idSeq2.equals(SecurityIDs.ID_MESSAGE_DIGEST)) {
                    ASN1Set set = (ASN1Set) seq2.getObjectAt(1);
                    digestAttr = ((ASN1OctetString) set.getObjectAt(0)).getOctets();
                } else if (idSeq2.equals(SecurityIDs.ID_ADBE_REVOCATION)) {
                    ASN1Set setout = (ASN1Set) seq2.getObjectAt(1);
                    ASN1Sequence seqout = (ASN1Sequence) setout.getObjectAt(0);
                    for (int j = 0; j < seqout.size(); ++j) {
                        ASN1TaggedObject tg = (ASN1TaggedObject) seqout.getObjectAt(j);
                        if (tg.getTagNo() == 0) {
                            ASN1Sequence seqin = (ASN1Sequence) tg.getObject();
                            findCRL(seqin);
                        }
                        if (tg.getTagNo() == 1) {
                            ASN1Sequence seqin = (ASN1Sequence) tg.getObject();
                            findOcsp(seqin);
                        }
                    }
                } else if (isCades && idSeq2.equals(SecurityIDs.ID_AA_SIGNING_CERTIFICATE_V1)) {
                    ASN1Set setout = (ASN1Set) seq2.getObjectAt(1);
                    ASN1Sequence seqout = (ASN1Sequence) setout.getObjectAt(0);
                    SigningCertificate sv2 = SigningCertificate.getInstance(seqout);
                    ESSCertID[] cerv2m = sv2.getCerts();
                    ESSCertID cerv2 = cerv2m[0];
                    byte[] enc2 = signCert.getEncoded();
                    MessageDigest m2 = new BouncyCastleDigest().getMessageDigest("SHA-1");
                    byte[] signCertHash = m2.digest(enc2);
                    byte[] hs2 = cerv2.getCertHash();
                    if (!Arrays.equals(signCertHash, hs2))
                        throw new IllegalArgumentException(
                                "Signing certificate doesn't match the ESS information.");
                    foundCades = true;
                } else if (isCades && idSeq2.equals(SecurityIDs.ID_AA_SIGNING_CERTIFICATE_V2)) {
                    ASN1Set setout = (ASN1Set) seq2.getObjectAt(1);
                    ASN1Sequence seqout = (ASN1Sequence) setout.getObjectAt(0);
                    SigningCertificateV2 sv2 = SigningCertificateV2.getInstance(seqout);
                    ESSCertIDv2[] cerv2m = sv2.getCerts();
                    ESSCertIDv2 cerv2 = cerv2m[0];
                    AlgorithmIdentifier ai2 = cerv2.getHashAlgorithm();
                    byte[] enc2 = signCert.getEncoded();
                    MessageDigest m2 = new BouncyCastleDigest()
                            .getMessageDigest(DigestAlgorithms.getDigest(ai2.getAlgorithm().getId()));
                    byte[] signCertHash = m2.digest(enc2);
                    byte[] hs2 = cerv2.getCertHash();
                    if (!Arrays.equals(signCertHash, hs2))
                        throw new IllegalArgumentException(
                                "Signing certificate doesn't match the ESS information.");
                    foundCades = true;
                }
            }
            if (digestAttr == null)
                throw new IllegalArgumentException(MessageLocalization
                        .getComposedMessage("authenticated.attribute.is.missing.the.digest"));
            ++next;
        }
        if (isCades && !foundCades)
            throw new IllegalArgumentException("CAdES ESS information missing.");
        digestEncryptionAlgorithmOid = ((ASN1ObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(next++))
                .getObjectAt(0)).getId();
        digest = ((ASN1OctetString) signerInfo.getObjectAt(next++)).getOctets();
        if (next < signerInfo.size() && signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) {
            ASN1TaggedObject taggedObject = (ASN1TaggedObject) signerInfo.getObjectAt(next);
            ASN1Set unat = ASN1Set.getInstance(taggedObject, false);
            AttributeTable attble = new AttributeTable(unat);
            Attribute ts = attble.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
            if (ts != null && ts.getAttrValues().size() > 0) {
                ASN1Set attributeValues = ts.getAttrValues();
                ASN1Sequence tokenSequence = ASN1Sequence.getInstance(attributeValues.getObjectAt(0));
                ContentInfo contentInfo = new ContentInfo(tokenSequence);
                this.timeStampToken = new TimeStampToken(contentInfo);
            }
        }
        if (isTsp) {
            ContentInfo contentInfoTsp = new ContentInfo(signedData);
            this.timeStampToken = new TimeStampToken(contentInfoTsp);
            TimeStampTokenInfo info = timeStampToken.getTimeStampInfo();
            String algOID = info.getMessageImprintAlgOID().getId();
            messageDigest = DigestAlgorithms.getMessageDigestFromOid(algOID, null);
        } else {
            if (RSAdata != null || digestAttr != null) {
                if (PdfName.ADBE_PKCS7_SHA1.equals(getFilterSubtype())) {
                    messageDigest = DigestAlgorithms.getMessageDigest("SHA1", provider);
                } else {
                    messageDigest = DigestAlgorithms.getMessageDigest(getHashAlgorithm(), provider);
                }
                encContDigest = DigestAlgorithms.getMessageDigest(getHashAlgorithm(), provider);
            }
            sig = initSignature(signCert.getPublicKey());
        }
    } catch (Exception e) {
        throw new ExceptionConverter(e);
    }
}

From source file:ee.ria.xroad.common.asic.AsicContainerVerifier.java

License:Open Source License

private TimeStampToken getTimeStampToken() throws Exception {
    String timestampDerBase64 = asic.getEntryAsString(ENTRY_TIMESTAMP);
    byte[] tsDerDecoded = decodeBase64(timestampDerBase64);
    return new TimeStampToken(new ContentInfo((ASN1Sequence) ASN1Sequence.fromByteArray(tsDerDecoded)));
}

From source file:ee.ria.xroad.common.signature.TimestampVerifierTest.java

License:Open Source License

private static TimeStampToken getTimestampFromFile(String fileName) throws Exception {
    byte[] data = getBytesFromFile(fileName);
    TimeStampToken token = new TimeStampToken(new ContentInfo((ASN1Sequence) ASN1Sequence.fromByteArray(data)));
    assertNotNull(token);//from   w  w  w . j a v  a2s  .c om
    return token;
}

From source file:es.uji.security.crypto.pdf.PdfPKCS7TSA.java

License:Mozilla Public License

/**                                                                                                                        
 * Verifies a signature using the sub-filter adbe.pkcs7.detached or                                                        
 * adbe.pkcs7.sha1.                                                                                                        
 * @param contentsKey the /Contents key                                                                                    
 * @param provider the provider or <code>null</code> for the default provider                                              
 *///w  ww.j  av a 2s .  c  o m
public PdfPKCS7TSA(byte[] contentsKey, Provider provider) {
    try {
        this.provider = provider;
        ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey));

        //
        // Basic checks to make sure it's a PKCS#7 SignedData Object
        //                                                          
        DERObject pkcs;

        try {
            pkcs = din.readObject();
        } catch (IOException e) {
            throw new IllegalArgumentException("can't decode PKCS7SignedData object");
        }
        if (!(pkcs instanceof ASN1Sequence)) {
            throw new IllegalArgumentException("Not a valid PKCS#7 object - not a sequence");
        }
        ASN1Sequence signedData = (ASN1Sequence) pkcs;
        DERObjectIdentifier objId = (DERObjectIdentifier) signedData.getObjectAt(0);
        if (!objId.getId().equals(ID_PKCS7_SIGNED_DATA))
            throw new IllegalArgumentException("Not a valid PKCS#7 object - not signed data");
        ASN1Sequence content = (ASN1Sequence) ((DERTaggedObject) signedData.getObjectAt(1)).getObject();
        // the positions that we care are:                                                            
        //     0 - version                                                                            
        //     1 - digestAlgorithms                                                                   
        //     2 - possible ID_PKCS7_DATA                                                             
        //     (the certificates and crls are taken out by other means)                               
        //     last - signerInfos                                                                     

        // the version
        version = ((DERInteger) content.getObjectAt(0)).getValue().intValue();

        // the digestAlgorithms
        digestalgos = new HashSet();
        Enumeration e = ((ASN1Set) content.getObjectAt(1)).getObjects();
        while (e.hasMoreElements()) {
            ASN1Sequence s = (ASN1Sequence) e.nextElement();
            DERObjectIdentifier o = (DERObjectIdentifier) s.getObjectAt(0);
            digestalgos.add(o.getId());
        }

        // the certificates and crls
        X509CertParser cr = new X509CertParser();
        cr.engineInit(new ByteArrayInputStream(contentsKey));
        certs = cr.engineReadAll();
        X509CRLParser cl = new X509CRLParser();
        cl.engineInit(new ByteArrayInputStream(contentsKey));
        crls = cl.engineReadAll();

        // the possible ID_PKCS7_DATA
        ASN1Sequence rsaData = (ASN1Sequence) content.getObjectAt(2);
        if (rsaData.size() > 1) {
            DEROctetString rsaDataContent = (DEROctetString) ((DERTaggedObject) rsaData.getObjectAt(1))
                    .getObject();
            RSAdata = rsaDataContent.getOctets();
        }

        // the signerInfos
        int next = 3;
        while (content.getObjectAt(next) instanceof DERTaggedObject)
            ++next;
        ASN1Set signerInfos = (ASN1Set) content.getObjectAt(next);
        if (signerInfos.size() != 1)
            throw new IllegalArgumentException(
                    "This PKCS#7 object has multiple SignerInfos - only one is supported at this time");
        ASN1Sequence signerInfo = (ASN1Sequence) signerInfos.getObjectAt(0);
        // the positions that we care are                                                                                  
        //     0 - version                                                                                                 
        //     1 - the signing certificate serial number                                                                   
        //     2 - the digest algorithm                                                                                    
        //     3 or 4 - digestEncryptionAlgorithm                                                                          
        //     4 or 5 - encryptedDigest                                                                                    
        signerversion = ((DERInteger) signerInfo.getObjectAt(0)).getValue().intValue();
        // Get the signing certificate                                                                                     
        ASN1Sequence issuerAndSerialNumber = (ASN1Sequence) signerInfo.getObjectAt(1);
        BigInteger serialNumber = ((DERInteger) issuerAndSerialNumber.getObjectAt(1)).getValue();
        for (Iterator i = certs.iterator(); i.hasNext();) {
            X509Certificate cert = (X509Certificate) i.next();
            if (serialNumber.equals(cert.getSerialNumber())) {
                signCert = cert;
                break;
            }
        }
        if (signCert == null) {
            throw new IllegalArgumentException(
                    "Can't find signing certificate with serial " + serialNumber.toString(16));
        }
        signCertificateChain();
        digestAlgorithm = ((DERObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(2)).getObjectAt(0))
                .getId();
        next = 3;
        if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) {
            ASN1TaggedObject tagsig = (ASN1TaggedObject) signerInfo.getObjectAt(next);
            ASN1Set sseq = ASN1Set.getInstance(tagsig, false);
            sigAttr = sseq.getEncoded(ASN1Encodable.DER);

            for (int k = 0; k < sseq.size(); ++k) {
                ASN1Sequence seq2 = (ASN1Sequence) sseq.getObjectAt(k);
                if (((DERObjectIdentifier) seq2.getObjectAt(0)).getId().equals(ID_MESSAGE_DIGEST)) {
                    ASN1Set set = (ASN1Set) seq2.getObjectAt(1);
                    digestAttr = ((DEROctetString) set.getObjectAt(0)).getOctets();
                } else if (((DERObjectIdentifier) seq2.getObjectAt(0)).getId().equals(ID_ADBE_REVOCATION)) {
                    ASN1Set setout = (ASN1Set) seq2.getObjectAt(1);
                    ASN1Sequence seqout = (ASN1Sequence) setout.getObjectAt(0);
                    for (int j = 0; j < seqout.size(); ++j) {
                        ASN1TaggedObject tg = (ASN1TaggedObject) seqout.getObjectAt(j);
                        if (tg.getTagNo() != 1)
                            continue;
                        ASN1Sequence seqin = (ASN1Sequence) tg.getObject();
                        findOcsp(seqin);
                    }
                }
            }
            if (digestAttr == null)
                throw new IllegalArgumentException("Authenticated attribute is missing the digest.");
            ++next;
        }
        digestEncryptionAlgorithm = ((DERObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(next++))
                .getObjectAt(0)).getId();
        digest = ((DEROctetString) signerInfo.getObjectAt(next++)).getOctets();
        if (next < signerInfo.size() && (signerInfo.getObjectAt(next) instanceof DERTaggedObject)) {
            DERTaggedObject taggedObject = (DERTaggedObject) signerInfo.getObjectAt(next);
            ASN1Set unat = ASN1Set.getInstance(taggedObject, false);
            AttributeTable attble = new AttributeTable(unat);
            Attribute ts = attble.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
            if (ts != null) {
                ASN1Set attributeValues = ts.getAttrValues();
                ASN1Sequence tokenSequence = ASN1Sequence.getInstance(attributeValues.getObjectAt(0));
                ContentInfo contentInfo = new ContentInfo(tokenSequence);
                this.timeStampToken = new TimestampToken(contentInfo.getEncoded());
            }
        }
        if (RSAdata != null || digestAttr != null) {
            if (provider == null || provider.getName().startsWith("SunPKCS11"))
                messageDigest = MessageDigest.getInstance(getHashAlgorithm());
            else
                messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider);
        }
        if (provider == null)
            sig = Signature.getInstance(getDigestAlgorithm());
        else
            sig = Signature.getInstance(getDigestAlgorithm(), provider);
        sig.initVerify(signCert.getPublicKey());
    } catch (Exception e) {
        throw new ExceptionConverter(e);
    }
}

From source file:org.signserver.module.tsa.MSAuthCodeTimeStampSigner.java

License:Open Source License

/**
 * The main method performing the actual timestamp operation.
 * Expects the signRequest to be a GenericSignRequest contining a
 * TimeStampRequest/* w  w w  .  j a v  a  2 s.  co  m*/
 *
 * @param signRequest
 * @param requestContext
 * @return the sign response
 * @see org.signserver.server.IProcessable#processData(org.signserver.common.ProcessRequest, org.signserver.common.RequestContext)
 */
public ProcessResponse processData(final ProcessRequest signRequest, final RequestContext requestContext)
        throws IllegalRequestException, CryptoTokenOfflineException, SignServerException {

    // Log values
    final LogMap logMap = LogMap.getInstance(requestContext);

    try {
        final ISignRequest sReq = (ISignRequest) signRequest;
        final byte[] requestbytes = (byte[]) sReq.getRequestData();

        if (requestbytes == null || requestbytes.length == 0) {
            LOG.error("Request must contain data");
            throw new IllegalRequestException("Request must contain data");
        }

        // Check that the request contains a valid TimeStampRequest object.
        if (!(signRequest instanceof GenericSignRequest)) {
            final IllegalRequestException exception = new IllegalRequestException(
                    "Recieved request wasn't an expected GenericSignRequest. ");
            LOG.error("Received request wasn't an expected GenericSignRequest");
            throw exception;
        }

        if (!((sReq.getRequestData() instanceof TimeStampRequest)
                || (sReq.getRequestData() instanceof byte[]))) {
            final IllegalRequestException exception = new IllegalRequestException(
                    "Recieved request data wasn't an expected TimeStampRequest. ");
            LOG.error("Received request data wasn't an expected TimeStampRequest");
            throw exception;
        }

        if (!validChain) {
            LOG.error("Certificate chain not correctly configured");
            throw new CryptoTokenOfflineException("Certificate chain not correctly configured");
        }

        ASN1Primitive asn1obj = ASN1Primitive.fromByteArray(Base64.decode(requestbytes));
        ASN1Sequence asn1seq = ASN1Sequence.getInstance(asn1obj);

        if (asn1seq.size() != 2) {
            LOG.error("Wrong structure, should be an ASN1Sequence with 2 elements");
            throw new IllegalRequestException("Wrong structure, should be an ASN1Sequence with 2 elements");
        }

        ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(asn1seq.getObjectAt(0));
        ASN1Sequence asn1seq1 = ASN1Sequence.getInstance(asn1seq.getObjectAt(1));

        final ContentInfo ci = new ContentInfo(asn1seq1);

        if (!oid.getId().equals(msOID)) {
            LOG.error("Invalid OID in request: " + oid.getId());
            throw new IllegalRequestException("Invalid OID in request: " + oid.getId());
        }

        if (asn1seq1.size() != 2) {
            LOG.error(
                    "Wrong structure, should be an ASN1Sequence with 2 elements as the value of element 0 in the outer ASN1Sequence");
            throw new IllegalRequestException(
                    "Wrong structure, should be an ASN1Sequence with 2 elements as the value of element 0 in the outer ASN1Sequence");
        }

        oid = ASN1ObjectIdentifier.getInstance(asn1seq1.getObjectAt(0));

        if (!oid.getId().equals(dataOID)) {
            throw new IllegalRequestException("Wrong contentType OID: " + oid.getId());
        }

        ASN1TaggedObject tag = ASN1TaggedObject.getInstance(asn1seq1.getObjectAt(1));

        if (tag.getTagNo() != 0) {
            throw new IllegalRequestException("Wrong tag no (should be 0): " + tag.getTagNo());
        }

        ASN1OctetString octets = ASN1OctetString.getInstance(tag.getObject());
        byte[] content = octets.getOctets();

        final ITimeSource timeSrc;
        final Date date;
        byte[] der;
        ICryptoInstance crypto = null;
        try {
            crypto = acquireCryptoInstance(ICryptoToken.PURPOSE_SIGN, signRequest, requestContext);

            // get signing cert certificate chain and private key
            List<Certificate> certList = this.getSigningCertificateChain(crypto);
            if (certList == null) {
                throw new SignServerException("Null certificate chain. This signer needs a certificate.");
            }

            Certificate[] certs = (Certificate[]) certList.toArray(new Certificate[certList.size()]);

            // Sign
            X509Certificate x509cert = (X509Certificate) certs[0];

            timeSrc = getTimeSource();
            if (LOG.isDebugEnabled()) {
                LOG.debug("TimeSource: " + timeSrc.getClass().getName());
            }
            date = timeSrc.getGenTime();

            if (date == null) {
                throw new ServiceUnavailableException("Time source is not available");
            }

            ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
            signedAttributes.add(new Attribute(CMSAttributes.signingTime, new DERSet(new Time(date))));

            if (includeSigningCertificateAttribute) {
                try {
                    final DERInteger serial = new DERInteger(x509cert.getSerialNumber());
                    final X509CertificateHolder certHolder = new X509CertificateHolder(x509cert.getEncoded());
                    final X500Name issuer = certHolder.getIssuer();
                    final GeneralName name = new GeneralName(issuer);
                    final GeneralNames names = new GeneralNames(name);
                    final IssuerSerial is = new IssuerSerial(names, ASN1Integer.getInstance(serial));

                    final ESSCertID essCertid = new ESSCertID(
                            MessageDigest.getInstance("SHA-1").digest(x509cert.getEncoded()), is);
                    signedAttributes.add(new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificate,
                            new DERSet(new SigningCertificate(essCertid))));
                } catch (NoSuchAlgorithmException e) {
                    LOG.error("Can't find SHA-1 implementation: " + e.getMessage());
                    throw new SignServerException("Can't find SHA-1 implementation", e);
                }
            }

            AttributeTable signedAttributesTable = new AttributeTable(signedAttributes);
            DefaultSignedAttributeTableGenerator signedAttributeGenerator = new DefaultSignedAttributeTableGenerator(
                    signedAttributesTable);

            final String provider = cryptoToken.getProvider(ICryptoToken.PROVIDERUSAGE_SIGN);

            SignerInfoGeneratorBuilder signerInfoBuilder = new SignerInfoGeneratorBuilder(
                    new JcaDigestCalculatorProviderBuilder().setProvider("BC").build());
            signerInfoBuilder.setSignedAttributeGenerator(signedAttributeGenerator);

            JcaContentSignerBuilder contentSigner = new JcaContentSignerBuilder(signatureAlgo);
            contentSigner.setProvider(provider);

            final SignerInfoGenerator sig = signerInfoBuilder.build(contentSigner.build(crypto.getPrivateKey()),
                    new X509CertificateHolder(x509cert.getEncoded()));

            JcaCertStore cs = new JcaCertStore(certList);

            CMSTypedData cmspba = new CMSProcessableByteArray(content);
            CMSSignedData cmssd = MSAuthCodeCMSUtils.generate(cmspba, true, Arrays.asList(sig),
                    MSAuthCodeCMSUtils.getCertificatesFromStore(cs), Collections.emptyList(), ci);

            der = ASN1Primitive.fromByteArray(cmssd.getEncoded()).getEncoded();
        } finally {
            releaseCryptoInstance(crypto, requestContext);
        }

        // Log values
        logMap.put(ITimeStampLogger.LOG_TSA_TIME, String.valueOf(date.getTime()));
        logMap.put(ITimeStampLogger.LOG_TSA_TIMESOURCE, timeSrc.getClass().getSimpleName());

        final String archiveId = createArchiveId(requestbytes,
                (String) requestContext.get(RequestContext.TRANSACTION_ID));

        final GenericSignResponse signResponse;
        byte[] signedbytes = Base64.encode(der, false);

        logMap.put(ITimeStampLogger.LOG_TSA_TIMESTAMPRESPONSE_ENCODED, new String(signedbytes));

        final Collection<? extends Archivable> archivables = Arrays.asList(
                new DefaultArchivable(Archivable.TYPE_REQUEST, REQUEST_CONTENT_TYPE, requestbytes, archiveId),
                new DefaultArchivable(Archivable.TYPE_RESPONSE, RESPONSE_CONTENT_TYPE, signedbytes, archiveId));

        if (signRequest instanceof GenericServletRequest) {
            signResponse = new GenericServletResponse(sReq.getRequestID(), signedbytes,
                    getSigningCertificate(signRequest, requestContext), archiveId, archivables,
                    RESPONSE_CONTENT_TYPE);
        } else {
            signResponse = new GenericSignResponse(sReq.getRequestID(), signedbytes,
                    getSigningCertificate(signRequest, requestContext), archiveId, archivables);
        }

        // The client can be charged for the request
        requestContext.setRequestFulfilledByWorker(true);

        return signResponse;

    } catch (IOException e) {
        final IllegalRequestException exception = new IllegalRequestException("IOException: " + e.getMessage(),
                e);
        LOG.error("IOException: ", e);
        logMap.put(ITimeStampLogger.LOG_TSA_EXCEPTION, exception.getMessage());
        throw exception;
    } catch (CMSException e) {
        final SignServerException exception = new SignServerException(e.getMessage(), e);
        LOG.error("CMSException: ", e);
        logMap.put(ITimeStampLogger.LOG_TSA_EXCEPTION, exception.getMessage());
        throw exception;
    } catch (OperatorCreationException e) {
        final SignServerException exception = new SignServerException(e.getMessage(), e);
        LOG.error("OperatorCreationException: ", e);
        logMap.put(ITimeStampLogger.LOG_TSA_EXCEPTION, exception.getMessage());
        throw exception;
    } catch (CertificateEncodingException e) {
        final SignServerException exception = new SignServerException(e.getMessage(), e);
        LOG.error("CertificateEncodingException: ", e);
        logMap.put(ITimeStampLogger.LOG_TSA_EXCEPTION, exception.getMessage());
        throw exception;
    } catch (ArrayIndexOutOfBoundsException e) {
        // the BC base64 decoder doesn't check the the base64 input length...
        final IllegalRequestException exception = new IllegalRequestException(
                "ArrayIndexOutOfBoundsException: " + e.getMessage(), e);
        LOG.error("ArrayIndexOutOfBoundsException: ", e);
        logMap.put(ITimeStampLogger.LOG_TSA_EXCEPTION, exception.getMessage());
        throw exception;
    }
}

From source file:org.signserver.module.tsa.MSAuthCodeTimeStampSignerTest.java

License:Open Source License

/**
 * Performs test using specified signature algorithm, digest algorithm and with the optional SigningCertificate attribute included or not included.
 * /*from   ww w  .  j a  v a  2  s  . c o m*/
 * The SigningCertificate attribute is specified in RFC 2634.
 * 
 * SigningCertificate ::=  SEQUENCE {
 *  certs        SEQUENCE OF ESSCertID,
 *  policies     SEQUENCE OF PolicyInformation OPTIONAL
 * }
 *
 * id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
 *  member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
 *  smime(16) id-aa(2) 12 }
 *
 * ESSCertID ::=  SEQUENCE {
 *   certHash                 Hash,
 *   issuerSerial             IssuerSerial OPTIONAL
 * }
 * Hash ::= OCTET STRING -- SHA1 hash of entire certificate
 *
 * IssuerSerial ::= SEQUENCE {
 *   issuer                   GeneralNames,
 *   serialNumber             CertificateSerialNumber
 * }
 * 
 * @param signingAlgo Signature algorithm to use
 * @param expectedDigestOID Expected digest OID
 * @param requestData Request data to test with
 * @param includeSigningCertAttr If true, include and test the SigningCertificate attribute
 * @throws Exception
 */
private void testProcessDataWithAlgo(final String signingAlgo, final String expectedDigestOID,
        final byte[] requestData, final boolean includeSigningCertAttr, final String includeCertificateLevels)
        throws Exception {
    SignServerUtil.installBCProvider();

    final String CRYPTOTOKEN_CLASSNAME = "org.signserver.server.cryptotokens.HardCodedCryptoToken";

    final ProcessRequest signRequest;

    final GlobalConfigurationSessionMock globalConfig = new GlobalConfigurationSessionMock();
    final WorkerSessionMock workerMock = new WorkerSessionMock(globalConfig);

    final WorkerConfig config = new WorkerConfig();
    config.setProperty("NAME", "TestMSAuthCodeTimeStampSigner");
    config.setProperty("AUTHTYPE", "NOAUTH");
    config.setProperty("TIMESOURCE", "org.signserver.server.ZeroTimeSource");
    config.setProperty("SIGNATUREALGORITHM", signingAlgo);
    config.setProperty("DEFAULTKEY", HardCodedCryptoTokenAliases.KEY_ALIAS_1);

    if (includeSigningCertAttr) {
        config.setProperty("INCLUDE_SIGNING_CERTIFICATE_ATTRIBUTE", "true");
    }

    if (includeCertificateLevels != null) {
        config.setProperty(WorkerConfig.PROPERTY_INCLUDE_CERTIFICATE_LEVELS, includeCertificateLevels);
    }

    final MSAuthCodeTimeStampSigner worker = new MSAuthCodeTimeStampSigner() {
        @Override
        protected IGlobalConfigurationSession.IRemote getGlobalConfigurationSession() {
            return globalConfig;
        }
    };

    workerMock.setupWorker(SIGNER_ID, CRYPTOTOKEN_CLASSNAME, config, worker);
    workerMock.reloadConfiguration(SIGNER_ID);

    // if the INCLUDE_CERTIFICATE_LEVELS property has been set,
    // check that it gives a not supported error
    if (includeCertificateLevels != null) {
        final List<String> errors = worker.getFatalErrors();

        assertTrue("Should contain config error",
                errors.contains(WorkerConfig.PROPERTY_INCLUDE_CERTIFICATE_LEVELS + " is not supported."));
        return;
    }

    // create sample hard-coded request
    signRequest = new GenericSignRequest(REQUEST_ID, requestData);

    final RequestContext requestContext = new RequestContext();
    GenericSignResponse resp = (GenericSignResponse) workerMock.process(SIGNER_ID, signRequest, requestContext);

    // check that the response contains the needed attributes
    byte[] buf = resp.getProcessedData();
    ASN1Sequence asn1seq = ASN1Sequence.getInstance(Base64.decode(buf));

    ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(asn1seq.getObjectAt(0));
    ASN1TaggedObject ato = ASN1TaggedObject.getInstance(asn1seq.getObjectAt(1));

    assertEquals("Invalid OID in response", SIGNED_DATA_OID, oid.getId());

    ASN1Sequence asn1seq1 = ASN1Sequence.getInstance(ato.getObject());

    ASN1Set asn1set = ASN1Set.getInstance(asn1seq1.getObjectAt(4));
    ASN1Sequence asn1seq2 = ASN1Sequence.getInstance(asn1set.getObjectAt(0));
    ASN1TaggedObject ato1 = ASN1TaggedObject.getInstance(asn1seq2.getObjectAt(3));
    ASN1Sequence asn1seq3 = ASN1Sequence.getInstance(ato1.getObject());
    ASN1Sequence asn1seq4 = ASN1Sequence.getInstance(asn1seq3.getObjectAt(0));
    ASN1Sequence asn1seq5 = ASN1Sequence.getInstance(asn1seq3.getObjectAt(1));
    ASN1Sequence asn1seq6 = ASN1Sequence.getInstance(asn1seq3.getObjectAt(2));

    final X509Certificate cert = (X509Certificate) CertTools
            .getCertfromByteArray(HardCodedCryptoToken.certbytes1);
    // expected serial number
    final BigInteger sn = cert.getSerialNumber();

    // if INCLUDE_SIGNING_CERTIFICATE_ATTRIBUTE is set to false, the attribute should not be included
    if (!includeSigningCertAttr) {
        assertEquals("Number of attributes", 3, asn1seq3.size());
    } else {
        final ASN1Sequence scAttr = ASN1Sequence.getInstance(asn1seq3.getObjectAt(3));
        TestUtils.checkSigningCertificateAttribute(scAttr, cert);
    }

    ASN1ObjectIdentifier ctOID = ASN1ObjectIdentifier.getInstance(asn1seq4.getObjectAt(0));
    assertEquals("Invalid OID for content type", CONTENT_TYPE_OID, ctOID.getId());

    ASN1ObjectIdentifier stOID = ASN1ObjectIdentifier.getInstance(asn1seq5.getObjectAt(0));
    assertEquals("Invalid OID for signing time", SIGNING_TIME_OID, stOID.getId());

    ASN1ObjectIdentifier mdOID = ASN1ObjectIdentifier.getInstance(asn1seq6.getObjectAt(0));
    assertEquals("Invalid OID for content type", MESSAGE_DIGEST_OID, mdOID.getId());

    // get signing time from response
    ASN1Set set = ASN1Set.getInstance(asn1seq5.getObjectAt(1));
    ASN1Encodable t = set.getObjectAt(0);
    Time t2 = Time.getInstance(t);
    Date d = t2.getDate();

    // the expected time (the "starting point" of time according to java.util.Date, consistent with the behavior of ZeroTimeSource
    Date d0 = new Date(0);

    assertEquals("Unexpected signing time in response", d0, d);

    // check expected signing algo
    ASN1Set set1 = ASN1Set.getInstance(asn1seq1.getObjectAt(1));
    ASN1Sequence asn1seq7 = ASN1Sequence.getInstance(set1.getObjectAt(0));
    ASN1ObjectIdentifier algOid = ASN1ObjectIdentifier.getInstance(asn1seq7.getObjectAt(0));

    assertEquals("Unexpected digest OID in response", expectedDigestOID, algOid.getId());

    // check that the request is included
    final CMSSignedData signedData = new CMSSignedData(asn1seq.getEncoded());
    final byte[] content = (byte[]) signedData.getSignedContent().getContent();

    final ASN1Sequence seq = ASN1Sequence.getInstance(Base64.decode(requestData));
    final ASN1Sequence seq2 = ASN1Sequence.getInstance(seq.getObjectAt(1));
    final ASN1TaggedObject tag = ASN1TaggedObject.getInstance(seq2.getObjectAt(1));
    final ASN1OctetString data = ASN1OctetString.getInstance(tag.getObject());

    assertTrue("Contains request data", Arrays.equals(data.getOctets(), content));

    // check the signing certificate
    final X509Certificate signercert = (X509Certificate) resp.getSignerCertificate();
    assertEquals("Serial number", sn, signercert.getSerialNumber());
    assertEquals("Issuer", cert.getIssuerDN(), signercert.getIssuerDN());

    // check ContentInfo, according to the Microsoft specification, the contentInfo in the response is
    // identical to the contentInfo in the request
    final ContentInfo expCi = new ContentInfo(seq2);
    final ContentInfo ci = new ContentInfo(ASN1Sequence.getInstance(asn1seq1.getObjectAt(2)));

    assertEquals("Content info should match the request", expCi, ci);

    // Get signers
    final Collection signers = signedData.getSignerInfos().getSigners();
    final SignerInformation signer = (SignerInformation) signers.iterator().next();

    // Verify using the signer's certificate
    assertTrue("Verification using signer certificate", signer.verify(signercert.getPublicKey(), "BC"));

    // Check that the time source is being logged
    LogMap logMap = LogMap.getInstance(requestContext);
    assertEquals("timesource", ZeroTimeSource.class.getSimpleName(), logMap.get("TSA_TIMESOURCE"));

    assertNotNull("response", logMap.get(ITimeStampLogger.LOG_TSA_TIMESTAMPRESPONSE_ENCODED));
    assertEquals("log line doesn't contain newlines", -1,
            logMap.get(ITimeStampLogger.LOG_TSA_TIMESTAMPRESPONSE_ENCODED).lastIndexOf('\n'));
}