001/* 002 * $Id: PdfPKCS7.java 4784 2011-03-15 08:33:00Z blowagie $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text.pdf; 045 046import java.io.ByteArrayInputStream; 047import java.io.ByteArrayOutputStream; 048import java.io.File; 049import java.io.FileInputStream; 050import java.io.IOException; 051import java.math.BigInteger; 052import java.security.InvalidKeyException; 053import java.security.KeyStore; 054import java.security.MessageDigest; 055import java.security.NoSuchAlgorithmException; 056import java.security.NoSuchProviderException; 057import java.security.PrivateKey; 058import java.security.Signature; 059import java.security.SignatureException; 060import java.security.cert.CRL; 061import java.security.cert.CRLException; 062import java.security.cert.Certificate; 063import java.security.cert.CertificateException; 064import java.security.cert.CertificateFactory; 065import java.security.cert.CertificateParsingException; 066import java.security.cert.X509CRL; 067import java.security.cert.X509Certificate; 068import java.util.ArrayList; 069import java.util.Arrays; 070import java.util.Calendar; 071import java.util.Collection; 072import java.util.Date; 073import java.util.Enumeration; 074import java.util.GregorianCalendar; 075import java.util.HashMap; 076import java.util.HashSet; 077import java.util.Set; 078 079import org.bouncycastle.asn1.ASN1Encodable; 080import org.bouncycastle.asn1.ASN1EncodableVector; 081import org.bouncycastle.asn1.ASN1InputStream; 082import org.bouncycastle.asn1.ASN1OctetString; 083import org.bouncycastle.asn1.ASN1OutputStream; 084import org.bouncycastle.asn1.ASN1Sequence; 085import org.bouncycastle.asn1.ASN1Set; 086import org.bouncycastle.asn1.ASN1TaggedObject; 087import org.bouncycastle.asn1.DEREnumerated; 088import org.bouncycastle.asn1.DERInteger; 089import org.bouncycastle.asn1.DERNull; 090import org.bouncycastle.asn1.DERObject; 091import org.bouncycastle.asn1.DERObjectIdentifier; 092import org.bouncycastle.asn1.DEROctetString; 093import org.bouncycastle.asn1.DERSequence; 094import org.bouncycastle.asn1.DERSet; 095import org.bouncycastle.asn1.DERString; 096import org.bouncycastle.asn1.DERTaggedObject; 097import org.bouncycastle.asn1.DERUTCTime; 098import org.bouncycastle.asn1.cms.Attribute; 099import org.bouncycastle.asn1.cms.AttributeTable; 100import org.bouncycastle.asn1.cms.ContentInfo; 101import org.bouncycastle.asn1.ocsp.BasicOCSPResponse; 102import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers; 103import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 104import org.bouncycastle.asn1.tsp.MessageImprint; 105import org.bouncycastle.asn1.x509.X509Extensions; 106import org.bouncycastle.jce.X509Principal; 107import org.bouncycastle.jce.provider.X509CertParser; 108import org.bouncycastle.ocsp.BasicOCSPResp; 109import org.bouncycastle.ocsp.CertificateID; 110import org.bouncycastle.ocsp.SingleResp; 111import org.bouncycastle.tsp.TimeStampToken; 112 113import com.itextpdf.text.ExceptionConverter; 114import com.itextpdf.text.error_messages.MessageLocalization; 115 116/** 117 * This class does all the processing related to signing and verifying a PKCS#7 118 * signature. 119 * <p> 120 * It's based in code found at org.bouncycastle. 121 */ 122public class PdfPKCS7 { 123 124 private byte sigAttr[]; 125 private byte digestAttr[]; 126 private int version, signerversion; 127 private Set<String> digestalgos; 128 private Collection<Certificate> certs; 129 private Collection<CRL> crls; 130 private Collection<Certificate> signCerts; 131 private X509Certificate signCert; 132 private byte[] digest; 133 private MessageDigest messageDigest; 134 private String digestAlgorithm, digestEncryptionAlgorithm; 135 private Signature sig; 136 private transient PrivateKey privKey; 137 private byte RSAdata[]; 138 private boolean verified; 139 private boolean verifyResult; 140 private byte externalDigest[]; 141 private byte externalRSAdata[]; 142 private String provider; 143 144 private static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1"; 145 private static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2"; 146 private static final String ID_RSA = "1.2.840.113549.1.1.1"; 147 private static final String ID_DSA = "1.2.840.10040.4.1"; 148 private static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3"; 149 private static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4"; 150 private static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5"; 151 private static final String ID_ADBE_REVOCATION = "1.2.840.113583.1.1.8"; 152 /** 153 * Holds value of property reason. 154 */ 155 private String reason; 156 157 /** 158 * Holds value of property location. 159 */ 160 private String location; 161 162 /** 163 * Holds value of property signDate. 164 */ 165 private Calendar signDate; 166 167 /** 168 * Holds value of property signName. 169 */ 170 private String signName; 171 172 private TimeStampToken timeStampToken; 173 174 private static final HashMap<String, String> digestNames = new HashMap<String, String>(); 175 private static final HashMap<String, String> algorithmNames = new HashMap<String, String>(); 176 private static final HashMap<String, String> allowedDigests = new HashMap<String, String>(); 177 178 static { 179 digestNames.put("1.2.840.113549.2.5", "MD5"); 180 digestNames.put("1.2.840.113549.2.2", "MD2"); 181 digestNames.put("1.3.14.3.2.26", "SHA1"); 182 digestNames.put("2.16.840.1.101.3.4.2.4", "SHA224"); 183 digestNames.put("2.16.840.1.101.3.4.2.1", "SHA256"); 184 digestNames.put("2.16.840.1.101.3.4.2.2", "SHA384"); 185 digestNames.put("2.16.840.1.101.3.4.2.3", "SHA512"); 186 digestNames.put("1.3.36.3.2.2", "RIPEMD128"); 187 digestNames.put("1.3.36.3.2.1", "RIPEMD160"); 188 digestNames.put("1.3.36.3.2.3", "RIPEMD256"); 189 digestNames.put("1.2.840.113549.1.1.4", "MD5"); 190 digestNames.put("1.2.840.113549.1.1.2", "MD2"); 191 digestNames.put("1.2.840.113549.1.1.5", "SHA1"); 192 digestNames.put("1.2.840.113549.1.1.14", "SHA224"); 193 digestNames.put("1.2.840.113549.1.1.11", "SHA256"); 194 digestNames.put("1.2.840.113549.1.1.12", "SHA384"); 195 digestNames.put("1.2.840.113549.1.1.13", "SHA512"); 196 digestNames.put("1.2.840.113549.2.5", "MD5"); 197 digestNames.put("1.2.840.113549.2.2", "MD2"); 198 digestNames.put("1.2.840.10040.4.3", "SHA1"); 199 digestNames.put("2.16.840.1.101.3.4.3.1", "SHA224"); 200 digestNames.put("2.16.840.1.101.3.4.3.2", "SHA256"); 201 digestNames.put("2.16.840.1.101.3.4.3.3", "SHA384"); 202 digestNames.put("2.16.840.1.101.3.4.3.4", "SHA512"); 203 digestNames.put("1.3.36.3.3.1.3", "RIPEMD128"); 204 digestNames.put("1.3.36.3.3.1.2", "RIPEMD160"); 205 digestNames.put("1.3.36.3.3.1.4", "RIPEMD256"); 206 207 algorithmNames.put("1.2.840.113549.1.1.1", "RSA"); 208 algorithmNames.put("1.2.840.10040.4.1", "DSA"); 209 algorithmNames.put("1.2.840.113549.1.1.2", "RSA"); 210 algorithmNames.put("1.2.840.113549.1.1.4", "RSA"); 211 algorithmNames.put("1.2.840.113549.1.1.5", "RSA"); 212 algorithmNames.put("1.2.840.113549.1.1.14", "RSA"); 213 algorithmNames.put("1.2.840.113549.1.1.11", "RSA"); 214 algorithmNames.put("1.2.840.113549.1.1.12", "RSA"); 215 algorithmNames.put("1.2.840.113549.1.1.13", "RSA"); 216 algorithmNames.put("1.2.840.10040.4.3", "DSA"); 217 algorithmNames.put("2.16.840.1.101.3.4.3.1", "DSA"); 218 algorithmNames.put("2.16.840.1.101.3.4.3.2", "DSA"); 219 algorithmNames.put("1.3.36.3.3.1.3", "RSA"); 220 algorithmNames.put("1.3.36.3.3.1.2", "RSA"); 221 algorithmNames.put("1.3.36.3.3.1.4", "RSA"); 222 223 allowedDigests.put("MD5", "1.2.840.113549.2.5"); 224 allowedDigests.put("MD2", "1.2.840.113549.2.2"); 225 allowedDigests.put("SHA1", "1.3.14.3.2.26"); 226 allowedDigests.put("SHA224", "2.16.840.1.101.3.4.2.4"); 227 allowedDigests.put("SHA256", "2.16.840.1.101.3.4.2.1"); 228 allowedDigests.put("SHA384", "2.16.840.1.101.3.4.2.2"); 229 allowedDigests.put("SHA512", "2.16.840.1.101.3.4.2.3"); 230 allowedDigests.put("MD-5", "1.2.840.113549.2.5"); 231 allowedDigests.put("MD-2", "1.2.840.113549.2.2"); 232 allowedDigests.put("SHA-1", "1.3.14.3.2.26"); 233 allowedDigests.put("SHA-224", "2.16.840.1.101.3.4.2.4"); 234 allowedDigests.put("SHA-256", "2.16.840.1.101.3.4.2.1"); 235 allowedDigests.put("SHA-384", "2.16.840.1.101.3.4.2.2"); 236 allowedDigests.put("SHA-512", "2.16.840.1.101.3.4.2.3"); 237 allowedDigests.put("RIPEMD128", "1.3.36.3.2.2"); 238 allowedDigests.put("RIPEMD-128", "1.3.36.3.2.2"); 239 allowedDigests.put("RIPEMD160", "1.3.36.3.2.1"); 240 allowedDigests.put("RIPEMD-160", "1.3.36.3.2.1"); 241 allowedDigests.put("RIPEMD256", "1.3.36.3.2.3"); 242 allowedDigests.put("RIPEMD-256", "1.3.36.3.2.3"); 243 } 244 245 /** 246 * Gets the digest name for a certain id 247 * @param oid an id (for instance "1.2.840.113549.2.5") 248 * @return a digest name (for instance "MD5") 249 * @since 2.1.6 250 */ 251 public static String getDigest(String oid) { 252 String ret = digestNames.get(oid); 253 if (ret == null) 254 return oid; 255 else 256 return ret; 257 } 258 259 /** 260 * Gets the algorithm name for a certain id. 261 * @param oid an id (for instance "1.2.840.113549.1.1.1") 262 * @return an algorithm name (for instance "RSA") 263 * @since 2.1.6 264 */ 265 public static String getAlgorithm(String oid) { 266 String ret = algorithmNames.get(oid); 267 if (ret == null) 268 return oid; 269 else 270 return ret; 271 } 272 273 /** 274 * Gets the timestamp token if there is one. 275 * @return the timestamp token or null 276 * @since 2.1.6 277 */ 278 public TimeStampToken getTimeStampToken() { 279 return timeStampToken; 280 } 281 282 /** 283 * Gets the timestamp date 284 * @return a date 285 * @since 2.1.6 286 */ 287 public Calendar getTimeStampDate() { 288 if (timeStampToken == null) 289 return null; 290 Calendar cal = new GregorianCalendar(); 291 Date date = timeStampToken.getTimeStampInfo().getGenTime(); 292 cal.setTime(date); 293 return cal; 294 } 295 296 /** 297 * Verifies a signature using the sub-filter adbe.x509.rsa_sha1. 298 * @param contentsKey the /Contents key 299 * @param certsKey the /Cert key 300 * @param provider the provider or <code>null</code> for the default provider 301 */ 302 @SuppressWarnings("unchecked") 303 public PdfPKCS7(byte[] contentsKey, byte[] certsKey, String provider) { 304 try { 305 this.provider = provider; 306 X509CertParser cr = new X509CertParser(); 307 cr.engineInit(new ByteArrayInputStream(certsKey)); 308 certs = cr.engineReadAll(); 309 signCerts = certs; 310 signCert = (X509Certificate)certs.iterator().next(); 311 crls = new ArrayList<CRL>(); 312 ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(contentsKey)); 313 digest = ((DEROctetString)in.readObject()).getOctets(); 314 if (provider == null) 315 sig = Signature.getInstance("SHA1withRSA"); 316 else 317 sig = Signature.getInstance("SHA1withRSA", provider); 318 sig.initVerify(signCert.getPublicKey()); 319 } 320 catch (Exception e) { 321 throw new ExceptionConverter(e); 322 } 323 } 324 325 private BasicOCSPResp basicResp; 326 327 /** 328 * Gets the OCSP basic response if there is one. 329 * @return the OCSP basic response or null 330 * @since 2.1.6 331 */ 332 public BasicOCSPResp getOcsp() { 333 return basicResp; 334 } 335 336 private void findCRL(ASN1Sequence seq) throws IOException, CertificateException, CRLException { 337 try { 338 crls = new ArrayList<CRL>(); 339 for (int k = 0; k < seq.size(); ++k) { 340 ByteArrayInputStream ar = new ByteArrayInputStream(seq.getObjectAt(k).getDERObject().getDEREncoded()); 341 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 342 X509CRL crl = (X509CRL)cf.generateCRL(ar); 343 crls.add(crl); 344 } 345 } 346 catch (Exception ex) { 347 // ignore 348 } 349 } 350 351 private void findOcsp(ASN1Sequence seq) throws IOException { 352 basicResp = null; 353 boolean ret = false; 354 while (true) { 355 if (seq.getObjectAt(0) instanceof DERObjectIdentifier 356 && ((DERObjectIdentifier)seq.getObjectAt(0)).getId().equals(OCSPObjectIdentifiers.id_pkix_ocsp_basic.getId())) { 357 break; 358 } 359 ret = true; 360 for (int k = 0; k < seq.size(); ++k) { 361 if (seq.getObjectAt(k) instanceof ASN1Sequence) { 362 seq = (ASN1Sequence)seq.getObjectAt(0); 363 ret = false; 364 break; 365 } 366 if (seq.getObjectAt(k) instanceof ASN1TaggedObject) { 367 ASN1TaggedObject tag = (ASN1TaggedObject)seq.getObjectAt(k); 368 if (tag.getObject() instanceof ASN1Sequence) { 369 seq = (ASN1Sequence)tag.getObject(); 370 ret = false; 371 break; 372 } 373 else 374 return; 375 } 376 } 377 if (ret) 378 return; 379 } 380 DEROctetString os = (DEROctetString)seq.getObjectAt(1); 381 ASN1InputStream inp = new ASN1InputStream(os.getOctets()); 382 BasicOCSPResponse resp = BasicOCSPResponse.getInstance(inp.readObject()); 383 basicResp = new BasicOCSPResp(resp); 384 } 385 386 /** 387 * Verifies a signature using the sub-filter adbe.pkcs7.detached or 388 * adbe.pkcs7.sha1. 389 * @param contentsKey the /Contents key 390 * @param provider the provider or <code>null</code> for the default provider 391 */ 392 @SuppressWarnings("unchecked") 393 public PdfPKCS7(byte[] contentsKey, String provider) { 394 try { 395 this.provider = provider; 396 ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey)); 397 398 // 399 // Basic checks to make sure it's a PKCS#7 SignedData Object 400 // 401 DERObject pkcs; 402 403 try { 404 pkcs = din.readObject(); 405 } 406 catch (IOException e) { 407 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("can.t.decode.pkcs7signeddata.object")); 408 } 409 if (!(pkcs instanceof ASN1Sequence)) { 410 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("not.a.valid.pkcs.7.object.not.a.sequence")); 411 } 412 ASN1Sequence signedData = (ASN1Sequence)pkcs; 413 DERObjectIdentifier objId = (DERObjectIdentifier)signedData.getObjectAt(0); 414 if (!objId.getId().equals(ID_PKCS7_SIGNED_DATA)) 415 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("not.a.valid.pkcs.7.object.not.signed.data")); 416 ASN1Sequence content = (ASN1Sequence)((DERTaggedObject)signedData.getObjectAt(1)).getObject(); 417 // the positions that we care are: 418 // 0 - version 419 // 1 - digestAlgorithms 420 // 2 - possible ID_PKCS7_DATA 421 // (the certificates and crls are taken out by other means) 422 // last - signerInfos 423 424 // the version 425 version = ((DERInteger)content.getObjectAt(0)).getValue().intValue(); 426 427 // the digestAlgorithms 428 digestalgos = new HashSet<String>(); 429 Enumeration<ASN1Sequence> e = ((ASN1Set)content.getObjectAt(1)).getObjects(); 430 while (e.hasMoreElements()) 431 { 432 ASN1Sequence s = e.nextElement(); 433 DERObjectIdentifier o = (DERObjectIdentifier)s.getObjectAt(0); 434 digestalgos.add(o.getId()); 435 } 436 437 // the certificates 438 X509CertParser cr = new X509CertParser(); 439 cr.engineInit(new ByteArrayInputStream(contentsKey)); 440 certs = cr.engineReadAll(); 441 442 // the possible ID_PKCS7_DATA 443 ASN1Sequence rsaData = (ASN1Sequence)content.getObjectAt(2); 444 if (rsaData.size() > 1) { 445 DEROctetString rsaDataContent = (DEROctetString)((DERTaggedObject)rsaData.getObjectAt(1)).getObject(); 446 RSAdata = rsaDataContent.getOctets(); 447 } 448 449 // the signerInfos 450 int next = 3; 451 while (content.getObjectAt(next) instanceof DERTaggedObject) 452 ++next; 453 ASN1Set signerInfos = (ASN1Set)content.getObjectAt(next); 454 if (signerInfos.size() != 1) 455 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("this.pkcs.7.object.has.multiple.signerinfos.only.one.is.supported.at.this.time")); 456 ASN1Sequence signerInfo = (ASN1Sequence)signerInfos.getObjectAt(0); 457 // the positions that we care are 458 // 0 - version 459 // 1 - the signing certificate issuer and serial number 460 // 2 - the digest algorithm 461 // 3 or 4 - digestEncryptionAlgorithm 462 // 4 or 5 - encryptedDigest 463 signerversion = ((DERInteger)signerInfo.getObjectAt(0)).getValue().intValue(); 464 // Get the signing certificate 465 ASN1Sequence issuerAndSerialNumber = (ASN1Sequence)signerInfo.getObjectAt(1); 466 X509Principal issuer = new X509Principal(issuerAndSerialNumber.getObjectAt(0).getDERObject().getEncoded()); 467 BigInteger serialNumber = ((DERInteger)issuerAndSerialNumber.getObjectAt(1)).getValue(); 468 for (Object element : certs) { 469 X509Certificate cert = (X509Certificate)element; 470 if (issuer.equals(cert.getIssuerDN()) && serialNumber.equals(cert.getSerialNumber())) { 471 signCert = cert; 472 break; 473 } 474 } 475 if (signCert == null) { 476 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("can.t.find.signing.certificate.with.serial.1", 477 issuer.getName() + " / " + serialNumber.toString(16))); 478 } 479 signCertificateChain(); 480 digestAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(2)).getObjectAt(0)).getId(); 481 next = 3; 482 if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) { 483 ASN1TaggedObject tagsig = (ASN1TaggedObject)signerInfo.getObjectAt(next); 484 ASN1Set sseq = ASN1Set.getInstance(tagsig, false); 485 sigAttr = sseq.getEncoded(ASN1Encodable.DER); 486 487 for (int k = 0; k < sseq.size(); ++k) { 488 ASN1Sequence seq2 = (ASN1Sequence)sseq.getObjectAt(k); 489 if (((DERObjectIdentifier)seq2.getObjectAt(0)).getId().equals(ID_MESSAGE_DIGEST)) { 490 ASN1Set set = (ASN1Set)seq2.getObjectAt(1); 491 digestAttr = ((DEROctetString)set.getObjectAt(0)).getOctets(); 492 } 493 else if (((DERObjectIdentifier)seq2.getObjectAt(0)).getId().equals(ID_ADBE_REVOCATION)) { 494 ASN1Set setout = (ASN1Set)seq2.getObjectAt(1); 495 ASN1Sequence seqout = (ASN1Sequence)setout.getObjectAt(0); 496 for (int j = 0; j < seqout.size(); ++j) { 497 ASN1TaggedObject tg = (ASN1TaggedObject)seqout.getObjectAt(j); 498 if (tg.getTagNo() == 0) { 499 ASN1Sequence seqin = (ASN1Sequence)tg.getObject(); 500 findCRL(seqin); 501 } 502 if (tg.getTagNo() == 1) { 503 ASN1Sequence seqin = (ASN1Sequence)tg.getObject(); 504 findOcsp(seqin); 505 } 506 } 507 } 508 } 509 if (digestAttr == null) 510 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("authenticated.attribute.is.missing.the.digest")); 511 ++next; 512 } 513 digestEncryptionAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(next++)).getObjectAt(0)).getId(); 514 digest = ((DEROctetString)signerInfo.getObjectAt(next++)).getOctets(); 515 if (next < signerInfo.size() && signerInfo.getObjectAt(next) instanceof DERTaggedObject) { 516 DERTaggedObject taggedObject = (DERTaggedObject) signerInfo.getObjectAt(next); 517 ASN1Set unat = ASN1Set.getInstance(taggedObject, false); 518 AttributeTable attble = new AttributeTable(unat); 519 Attribute ts = attble.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken); 520 if (ts != null && ts.getAttrValues().size() > 0) { 521 ASN1Set attributeValues = ts.getAttrValues(); 522 ASN1Sequence tokenSequence = ASN1Sequence.getInstance(attributeValues.getObjectAt(0)); 523 ContentInfo contentInfo = new ContentInfo(tokenSequence); 524 this.timeStampToken = new TimeStampToken(contentInfo); 525 } 526 } 527 if (RSAdata != null || digestAttr != null) { 528 if (provider == null || provider.startsWith("SunPKCS11")) 529 messageDigest = MessageDigest.getInstance(getHashAlgorithm()); 530 else 531 messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider); 532 } 533 if (provider == null) 534 sig = Signature.getInstance(getDigestAlgorithm()); 535 else 536 sig = Signature.getInstance(getDigestAlgorithm(), provider); 537 sig.initVerify(signCert.getPublicKey()); 538 } 539 catch (Exception e) { 540 throw new ExceptionConverter(e); 541 } 542 } 543 544 /** 545 * Generates a signature. 546 * @param privKey the private key 547 * @param certChain the certificate chain 548 * @param crlList the certificate revocation list 549 * @param hashAlgorithm the hash algorithm 550 * @param provider the provider or <code>null</code> for the default provider 551 * @param hasRSAdata <CODE>true</CODE> if the sub-filter is adbe.pkcs7.sha1 552 * @throws InvalidKeyException on error 553 * @throws NoSuchProviderException on error 554 * @throws NoSuchAlgorithmException on error 555 */ 556 public PdfPKCS7(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, 557 String hashAlgorithm, String provider, boolean hasRSAdata) 558 throws InvalidKeyException, NoSuchProviderException, 559 NoSuchAlgorithmException 560 { 561 this.privKey = privKey; 562 this.provider = provider; 563 564 digestAlgorithm = allowedDigests.get(hashAlgorithm.toUpperCase()); 565 if (digestAlgorithm == null) 566 throw new NoSuchAlgorithmException(MessageLocalization.getComposedMessage("unknown.hash.algorithm.1", hashAlgorithm)); 567 568 version = signerversion = 1; 569 certs = new ArrayList<Certificate>(); 570 crls = new ArrayList<CRL>(); 571 digestalgos = new HashSet<String>(); 572 digestalgos.add(digestAlgorithm); 573 574 // 575 // Copy in the certificates and crls used to sign the private key. 576 // 577 signCert = (X509Certificate)certChain[0]; 578 for (Certificate element : certChain) { 579 certs.add(element); 580 } 581 582 if (crlList != null) { 583 for (CRL element : crlList) { 584 crls.add(element); 585 } 586 } 587 588 if (privKey != null) { 589 // 590 // Now we have private key, find out what the digestEncryptionAlgorithm is. 591 // 592 digestEncryptionAlgorithm = privKey.getAlgorithm(); 593 if (digestEncryptionAlgorithm.equals("RSA")) { 594 digestEncryptionAlgorithm = ID_RSA; 595 } 596 else if (digestEncryptionAlgorithm.equals("DSA")) { 597 digestEncryptionAlgorithm = ID_DSA; 598 } 599 else { 600 throw new NoSuchAlgorithmException(MessageLocalization.getComposedMessage("unknown.key.algorithm.1", digestEncryptionAlgorithm)); 601 } 602 } 603 if (hasRSAdata) { 604 RSAdata = new byte[0]; 605 if (provider == null || provider.startsWith("SunPKCS11")) 606 messageDigest = MessageDigest.getInstance(getHashAlgorithm()); 607 else 608 messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider); 609 } 610 611 if (privKey != null) { 612 if (provider == null) 613 sig = Signature.getInstance(getDigestAlgorithm()); 614 else 615 sig = Signature.getInstance(getDigestAlgorithm(), provider); 616 617 sig.initSign(privKey); 618 } 619 } 620 621 /** 622 * Update the digest with the specified bytes. This method is used both for signing and verifying 623 * @param buf the data buffer 624 * @param off the offset in the data buffer 625 * @param len the data length 626 * @throws SignatureException on error 627 */ 628 public void update(byte[] buf, int off, int len) throws SignatureException { 629 if (RSAdata != null || digestAttr != null) 630 messageDigest.update(buf, off, len); 631 else 632 sig.update(buf, off, len); 633 } 634 635 /** 636 * Verify the digest. 637 * @throws SignatureException on error 638 * @return <CODE>true</CODE> if the signature checks out, <CODE>false</CODE> otherwise 639 */ 640 public boolean verify() throws SignatureException { 641 if (verified) 642 return verifyResult; 643 if (sigAttr != null) { 644 final byte [] msgDigestBytes = messageDigest.digest(); 645 boolean verifyRSAdata = true; 646 sig.update(sigAttr); 647 if (RSAdata != null) 648 verifyRSAdata = Arrays.equals(msgDigestBytes, RSAdata); 649 verifyResult = Arrays.equals(msgDigestBytes, digestAttr) && sig.verify(digest) && verifyRSAdata; 650 } 651 else { 652 if (RSAdata != null) 653 sig.update(messageDigest.digest()); 654 verifyResult = sig.verify(digest); 655 } 656 verified = true; 657 return verifyResult; 658 } 659 660 /** 661 * Checks if the timestamp refers to this document. 662 * @throws java.security.NoSuchAlgorithmException on error 663 * @return true if it checks false otherwise 664 * @since 2.1.6 665 */ 666 public boolean verifyTimestampImprint() throws NoSuchAlgorithmException { 667 if (timeStampToken == null) 668 return false; 669 MessageImprint imprint = timeStampToken.getTimeStampInfo().toTSTInfo().getMessageImprint(); 670 byte[] md = MessageDigest.getInstance("SHA-1").digest(digest); 671 byte[] imphashed = imprint.getHashedMessage(); 672 boolean res = Arrays.equals(md, imphashed); 673 return res; 674 } 675 676 /** 677 * Get all the X.509 certificates associated with this PKCS#7 object in no particular order. 678 * Other certificates, from OCSP for example, will also be included. 679 * @return the X.509 certificates associated with this PKCS#7 object 680 */ 681 public Certificate[] getCertificates() { 682 return certs.toArray(new X509Certificate[certs.size()]); 683 } 684 685 /** 686 * Get the X.509 sign certificate chain associated with this PKCS#7 object. 687 * Only the certificates used for the main signature will be returned, with 688 * the signing certificate first. 689 * @return the X.509 certificates associated with this PKCS#7 object 690 * @since 2.1.6 691 */ 692 public Certificate[] getSignCertificateChain() { 693 return signCerts.toArray(new X509Certificate[signCerts.size()]); 694 } 695 696 private void signCertificateChain() { 697 ArrayList<Certificate> cc = new ArrayList<Certificate>(); 698 cc.add(signCert); 699 ArrayList<Certificate> oc = new ArrayList<Certificate>(certs); 700 for (int k = 0; k < oc.size(); ++k) { 701 if (signCert.equals(oc.get(k))) { 702 oc.remove(k); 703 --k; 704 continue; 705 } 706 } 707 boolean found = true; 708 while (found) { 709 X509Certificate v = (X509Certificate)cc.get(cc.size() - 1); 710 found = false; 711 for (int k = 0; k < oc.size(); ++k) { 712 try { 713 if (provider == null) 714 v.verify(((X509Certificate)oc.get(k)).getPublicKey()); 715 else 716 v.verify(((X509Certificate)oc.get(k)).getPublicKey(), provider); 717 found = true; 718 cc.add(oc.get(k)); 719 oc.remove(k); 720 break; 721 } 722 catch (Exception e) { 723 } 724 } 725 } 726 signCerts = cc; 727 } 728 729 /** 730 * Get the X.509 certificate revocation lists associated with this PKCS#7 object 731 * @return the X.509 certificate revocation lists associated with this PKCS#7 object 732 */ 733 public Collection<CRL> getCRLs() { 734 return crls; 735 } 736 737 /** 738 * Get the X.509 certificate actually used to sign the digest. 739 * @return the X.509 certificate actually used to sign the digest 740 */ 741 public X509Certificate getSigningCertificate() { 742 return signCert; 743 } 744 745 /** 746 * Get the version of the PKCS#7 object. Always 1 747 * @return the version of the PKCS#7 object. Always 1 748 */ 749 public int getVersion() { 750 return version; 751 } 752 753 /** 754 * Get the version of the PKCS#7 "SignerInfo" object. Always 1 755 * @return the version of the PKCS#7 "SignerInfo" object. Always 1 756 */ 757 public int getSigningInfoVersion() { 758 return signerversion; 759 } 760 761 /** 762 * Get the algorithm used to calculate the message digest 763 * @return the algorithm used to calculate the message digest 764 */ 765 public String getDigestAlgorithm() { 766 String dea = getAlgorithm(digestEncryptionAlgorithm); 767 if (dea == null) 768 dea = digestEncryptionAlgorithm; 769 770 return getHashAlgorithm() + "with" + dea; 771 } 772 773 /** 774 * Returns the algorithm. 775 * @return the digest algorithm 776 */ 777 public String getHashAlgorithm() { 778 return getDigest(digestAlgorithm); 779 } 780 781 /** 782 * Loads the default root certificates at <java.home>/lib/security/cacerts 783 * with the default provider. 784 * @return a <CODE>KeyStore</CODE> 785 */ 786 public static KeyStore loadCacertsKeyStore() { 787 return loadCacertsKeyStore(null); 788 } 789 790 /** 791 * Loads the default root certificates at <java.home>/lib/security/cacerts. 792 * @param provider the provider or <code>null</code> for the default provider 793 * @return a <CODE>KeyStore</CODE> 794 */ 795 public static KeyStore loadCacertsKeyStore(String provider) { 796 File file = new File(System.getProperty("java.home"), "lib"); 797 file = new File(file, "security"); 798 file = new File(file, "cacerts"); 799 FileInputStream fin = null; 800 try { 801 fin = new FileInputStream(file); 802 KeyStore k; 803 if (provider == null) 804 k = KeyStore.getInstance("JKS"); 805 else 806 k = KeyStore.getInstance("JKS", provider); 807 k.load(fin, null); 808 return k; 809 } 810 catch (Exception e) { 811 throw new ExceptionConverter(e); 812 } 813 finally { 814 try{if (fin != null) {fin.close();}}catch(Exception ex){} 815 } 816 } 817 818 /** 819 * Verifies a single certificate. 820 * @param cert the certificate to verify 821 * @param crls the certificate revocation list or <CODE>null</CODE> 822 * @param calendar the date or <CODE>null</CODE> for the current date 823 * @return a <CODE>String</CODE> with the error description or <CODE>null</CODE> 824 * if no error 825 */ 826 public static String verifyCertificate(X509Certificate cert, Collection<CRL> crls, Calendar calendar) { 827 if (calendar == null) 828 calendar = new GregorianCalendar(); 829 if (cert.hasUnsupportedCriticalExtension()) 830 return "Has unsupported critical extension"; 831 try { 832 cert.checkValidity(calendar.getTime()); 833 } 834 catch (Exception e) { 835 return e.getMessage(); 836 } 837 if (crls != null) { 838 for (CRL crl : crls) { 839 if (crl.isRevoked(cert)) 840 return "Certificate revoked"; 841 } 842 } 843 return null; 844 } 845 846 /** 847 * Verifies a certificate chain against a KeyStore. 848 * @param certs the certificate chain 849 * @param keystore the <CODE>KeyStore</CODE> 850 * @param crls the certificate revocation list or <CODE>null</CODE> 851 * @param calendar the date or <CODE>null</CODE> for the current date 852 * @return <CODE>null</CODE> if the certificate chain could be validated or a 853 * <CODE>Object[]{cert,error}</CODE> where <CODE>cert</CODE> is the 854 * failed certificate and <CODE>error</CODE> is the error message 855 */ 856 public static Object[] verifyCertificates(Certificate certs[], KeyStore keystore, Collection<CRL> crls, Calendar calendar) { 857 if (calendar == null) 858 calendar = new GregorianCalendar(); 859 for (int k = 0; k < certs.length; ++k) { 860 X509Certificate cert = (X509Certificate)certs[k]; 861 String err = verifyCertificate(cert, crls, calendar); 862 if (err != null) 863 return new Object[]{cert, err}; 864 try { 865 for (Enumeration<String> aliases = keystore.aliases(); aliases.hasMoreElements();) { 866 try { 867 String alias = aliases.nextElement(); 868 if (!keystore.isCertificateEntry(alias)) 869 continue; 870 X509Certificate certStoreX509 = (X509Certificate)keystore.getCertificate(alias); 871 if (verifyCertificate(certStoreX509, crls, calendar) != null) 872 continue; 873 try { 874 cert.verify(certStoreX509.getPublicKey()); 875 return null; 876 } 877 catch (Exception e) { 878 continue; 879 } 880 } 881 catch (Exception ex) { 882 } 883 } 884 } 885 catch (Exception e) { 886 } 887 int j; 888 for (j = 0; j < certs.length; ++j) { 889 if (j == k) 890 continue; 891 X509Certificate certNext = (X509Certificate)certs[j]; 892 try { 893 cert.verify(certNext.getPublicKey()); 894 break; 895 } 896 catch (Exception e) { 897 } 898 } 899 if (j == certs.length) 900 return new Object[]{cert, "Cannot be verified against the KeyStore or the certificate chain"}; 901 } 902 return new Object[]{null, "Invalid state. Possible circular certificate chain"}; 903 } 904 905 /** 906 * Verifies an OCSP response against a KeyStore. 907 * @param ocsp the OCSP response 908 * @param keystore the <CODE>KeyStore</CODE> 909 * @param provider the provider or <CODE>null</CODE> to use the BouncyCastle provider 910 * @return <CODE>true</CODE> is a certificate was found 911 * @since 2.1.6 912 */ 913 public static boolean verifyOcspCertificates(BasicOCSPResp ocsp, KeyStore keystore, String provider) { 914 if (provider == null) 915 provider = "BC"; 916 try { 917 for (Enumeration<String> aliases = keystore.aliases(); aliases.hasMoreElements();) { 918 try { 919 String alias = aliases.nextElement(); 920 if (!keystore.isCertificateEntry(alias)) 921 continue; 922 X509Certificate certStoreX509 = (X509Certificate)keystore.getCertificate(alias); 923 if (ocsp.verify(certStoreX509.getPublicKey(), provider)) 924 return true; 925 } 926 catch (Exception ex) { 927 } 928 } 929 } 930 catch (Exception e) { 931 } 932 return false; 933 } 934 935 /** 936 * Verifies a timestamp against a KeyStore. 937 * @param ts the timestamp 938 * @param keystore the <CODE>KeyStore</CODE> 939 * @param provider the provider or <CODE>null</CODE> to use the BouncyCastle provider 940 * @return <CODE>true</CODE> is a certificate was found 941 * @since 2.1.6 942 */ 943 public static boolean verifyTimestampCertificates(TimeStampToken ts, KeyStore keystore, String provider) { 944 if (provider == null) 945 provider = "BC"; 946 try { 947 for (Enumeration<String> aliases = keystore.aliases(); aliases.hasMoreElements();) { 948 try { 949 String alias = aliases.nextElement(); 950 if (!keystore.isCertificateEntry(alias)) 951 continue; 952 X509Certificate certStoreX509 = (X509Certificate)keystore.getCertificate(alias); 953 ts.validate(certStoreX509, provider); 954 return true; 955 } 956 catch (Exception ex) { 957 } 958 } 959 } 960 catch (Exception e) { 961 } 962 return false; 963 } 964 965 /** 966 * Retrieves the OCSP URL from the given certificate. 967 * @param certificate the certificate 968 * @return the URL or null 969 * @throws CertificateParsingException on error 970 * @since 2.1.6 971 */ 972 public static String getOCSPURL(X509Certificate certificate) throws CertificateParsingException { 973 try { 974 DERObject obj = getExtensionValue(certificate, X509Extensions.AuthorityInfoAccess.getId()); 975 if (obj == null) { 976 return null; 977 } 978 979 ASN1Sequence AccessDescriptions = (ASN1Sequence) obj; 980 for (int i = 0; i < AccessDescriptions.size(); i++) { 981 ASN1Sequence AccessDescription = (ASN1Sequence) AccessDescriptions.getObjectAt(i); 982 if ( AccessDescription.size() != 2 ) { 983 continue; 984 } else { 985 if (AccessDescription.getObjectAt(0) instanceof DERObjectIdentifier && ((DERObjectIdentifier)AccessDescription.getObjectAt(0)).getId().equals("1.3.6.1.5.5.7.48.1")) { 986 String AccessLocation = getStringFromGeneralName((DERObject)AccessDescription.getObjectAt(1)); 987 if ( AccessLocation == null ) { 988 return "" ; 989 } else { 990 return AccessLocation ; 991 } 992 } 993 } 994 } 995 } catch (Exception e) { 996 } 997 return null; 998 } 999 1000 /** 1001 * Checks if OCSP revocation refers to the document signing certificate. 1002 * @return true if it checks false otherwise 1003 * @since 2.1.6 1004 */ 1005 public boolean isRevocationValid() { 1006 if (basicResp == null) 1007 return false; 1008 if (signCerts.size() < 2) 1009 return false; 1010 try { 1011 X509Certificate[] cs = (X509Certificate[])getSignCertificateChain(); 1012 SingleResp sr = basicResp.getResponses()[0]; 1013 CertificateID cid = sr.getCertID(); 1014 X509Certificate sigcer = getSigningCertificate(); 1015 X509Certificate isscer = cs[1]; 1016 CertificateID tis = new CertificateID(CertificateID.HASH_SHA1, isscer, sigcer.getSerialNumber()); 1017 return tis.equals(cid); 1018 } 1019 catch (Exception ex) { 1020 } 1021 return false; 1022 } 1023 1024 private static DERObject getExtensionValue(X509Certificate cert, String oid) throws IOException { 1025 byte[] bytes = cert.getExtensionValue(oid); 1026 if (bytes == null) { 1027 return null; 1028 } 1029 ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes)); 1030 ASN1OctetString octs = (ASN1OctetString) aIn.readObject(); 1031 aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets())); 1032 return aIn.readObject(); 1033 } 1034 1035 private static String getStringFromGeneralName(DERObject names) throws IOException { 1036 DERTaggedObject taggedObject = (DERTaggedObject) names ; 1037 return new String(ASN1OctetString.getInstance(taggedObject, false).getOctets(), "ISO-8859-1"); 1038 } 1039 1040 /** 1041 * Get the "issuer" from the TBSCertificate bytes that are passed in 1042 * @param enc a TBSCertificate in a byte array 1043 * @return a DERObject 1044 */ 1045 private static DERObject getIssuer(byte[] enc) { 1046 try { 1047 ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc)); 1048 ASN1Sequence seq = (ASN1Sequence)in.readObject(); 1049 return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2); 1050 } 1051 catch (IOException e) { 1052 throw new ExceptionConverter(e); 1053 } 1054 } 1055 1056 /** 1057 * Get the "subject" from the TBSCertificate bytes that are passed in 1058 * @param enc A TBSCertificate in a byte array 1059 * @return a DERObject 1060 */ 1061 private static DERObject getSubject(byte[] enc) { 1062 try { 1063 ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc)); 1064 ASN1Sequence seq = (ASN1Sequence)in.readObject(); 1065 return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 5 : 4); 1066 } 1067 catch (IOException e) { 1068 throw new ExceptionConverter(e); 1069 } 1070 } 1071 1072 /** 1073 * Get the issuer fields from an X509 Certificate 1074 * @param cert an X509Certificate 1075 * @return an X509Name 1076 */ 1077 public static X509Name getIssuerFields(X509Certificate cert) { 1078 try { 1079 return new X509Name((ASN1Sequence)getIssuer(cert.getTBSCertificate())); 1080 } 1081 catch (Exception e) { 1082 throw new ExceptionConverter(e); 1083 } 1084 } 1085 1086 /** 1087 * Get the subject fields from an X509 Certificate 1088 * @param cert an X509Certificate 1089 * @return an X509Name 1090 */ 1091 public static X509Name getSubjectFields(X509Certificate cert) { 1092 try { 1093 return new X509Name((ASN1Sequence)getSubject(cert.getTBSCertificate())); 1094 } 1095 catch (Exception e) { 1096 throw new ExceptionConverter(e); 1097 } 1098 } 1099 1100 /** 1101 * Gets the bytes for the PKCS#1 object. 1102 * @return a byte array 1103 */ 1104 public byte[] getEncodedPKCS1() { 1105 try { 1106 if (externalDigest != null) 1107 digest = externalDigest; 1108 else 1109 digest = sig.sign(); 1110 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 1111 1112 ASN1OutputStream dout = new ASN1OutputStream(bOut); 1113 dout.writeObject(new DEROctetString(digest)); 1114 dout.close(); 1115 1116 return bOut.toByteArray(); 1117 } 1118 catch (Exception e) { 1119 throw new ExceptionConverter(e); 1120 } 1121 } 1122 1123 /** 1124 * Sets the digest/signature to an external calculated value. 1125 * @param digest the digest. This is the actual signature 1126 * @param RSAdata the extra data that goes into the data tag in PKCS#7 1127 * @param digestEncryptionAlgorithm the encryption algorithm. It may must be <CODE>null</CODE> if the <CODE>digest</CODE> 1128 * is also <CODE>null</CODE>. If the <CODE>digest</CODE> is not <CODE>null</CODE> 1129 * then it may be "RSA" or "DSA" 1130 */ 1131 public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) { 1132 externalDigest = digest; 1133 externalRSAdata = RSAdata; 1134 if (digestEncryptionAlgorithm != null) { 1135 if (digestEncryptionAlgorithm.equals("RSA")) { 1136 this.digestEncryptionAlgorithm = ID_RSA; 1137 } 1138 else if (digestEncryptionAlgorithm.equals("DSA")) { 1139 this.digestEncryptionAlgorithm = ID_DSA; 1140 } 1141 else 1142 throw new ExceptionConverter(new NoSuchAlgorithmException(MessageLocalization.getComposedMessage("unknown.key.algorithm.1", digestEncryptionAlgorithm))); 1143 } 1144 } 1145 1146 /** 1147 * Gets the bytes for the PKCS7SignedData object. 1148 * @return the bytes for the PKCS7SignedData object 1149 */ 1150 public byte[] getEncodedPKCS7() { 1151 return getEncodedPKCS7(null, null, null, null); 1152 } 1153 1154 /** 1155 * Gets the bytes for the PKCS7SignedData object. Optionally the authenticatedAttributes 1156 * in the signerInfo can also be set. If either of the parameters is <CODE>null</CODE>, none will be used. 1157 * @param secondDigest the digest in the authenticatedAttributes 1158 * @param signingTime the signing time in the authenticatedAttributes 1159 * @return the bytes for the PKCS7SignedData object 1160 */ 1161 public byte[] getEncodedPKCS7(byte secondDigest[], Calendar signingTime) { 1162 return getEncodedPKCS7(secondDigest, signingTime, null, null); 1163 } 1164 1165 /** 1166 * Gets the bytes for the PKCS7SignedData object. Optionally the authenticatedAttributes 1167 * in the signerInfo can also be set, OR a time-stamp-authority client 1168 * may be provided. 1169 * @param secondDigest the digest in the authenticatedAttributes 1170 * @param signingTime the signing time in the authenticatedAttributes 1171 * @param tsaClient TSAClient - null or an optional time stamp authority client 1172 * @return byte[] the bytes for the PKCS7SignedData object 1173 * @since 2.1.6 1174 */ 1175 public byte[] getEncodedPKCS7(byte secondDigest[], Calendar signingTime, TSAClient tsaClient, byte[] ocsp) { 1176 try { 1177 if (externalDigest != null) { 1178 digest = externalDigest; 1179 if (RSAdata != null) 1180 RSAdata = externalRSAdata; 1181 } 1182 else if (externalRSAdata != null && RSAdata != null) { 1183 RSAdata = externalRSAdata; 1184 sig.update(RSAdata); 1185 digest = sig.sign(); 1186 } 1187 else { 1188 if (RSAdata != null) { 1189 RSAdata = messageDigest.digest(); 1190 sig.update(RSAdata); 1191 } 1192 digest = sig.sign(); 1193 } 1194 1195 // Create the set of Hash algorithms 1196 ASN1EncodableVector digestAlgorithms = new ASN1EncodableVector(); 1197 for (Object element : digestalgos) { 1198 ASN1EncodableVector algos = new ASN1EncodableVector(); 1199 algos.add(new DERObjectIdentifier((String)element)); 1200 algos.add(DERNull.INSTANCE); 1201 digestAlgorithms.add(new DERSequence(algos)); 1202 } 1203 1204 // Create the contentInfo. 1205 ASN1EncodableVector v = new ASN1EncodableVector(); 1206 v.add(new DERObjectIdentifier(ID_PKCS7_DATA)); 1207 if (RSAdata != null) 1208 v.add(new DERTaggedObject(0, new DEROctetString(RSAdata))); 1209 DERSequence contentinfo = new DERSequence(v); 1210 1211 // Get all the certificates 1212 // 1213 v = new ASN1EncodableVector(); 1214 for (Object element : certs) { 1215 ASN1InputStream tempstream = new ASN1InputStream(new ByteArrayInputStream(((X509Certificate)element).getEncoded())); 1216 v.add(tempstream.readObject()); 1217 } 1218 1219 DERSet dercertificates = new DERSet(v); 1220 1221 // Create signerinfo structure. 1222 // 1223 ASN1EncodableVector signerinfo = new ASN1EncodableVector(); 1224 1225 // Add the signerInfo version 1226 // 1227 signerinfo.add(new DERInteger(signerversion)); 1228 1229 v = new ASN1EncodableVector(); 1230 v.add(getIssuer(signCert.getTBSCertificate())); 1231 v.add(new DERInteger(signCert.getSerialNumber())); 1232 signerinfo.add(new DERSequence(v)); 1233 1234 // Add the digestAlgorithm 1235 v = new ASN1EncodableVector(); 1236 v.add(new DERObjectIdentifier(digestAlgorithm)); 1237 v.add(new DERNull()); 1238 signerinfo.add(new DERSequence(v)); 1239 1240 // add the authenticated attribute if present 1241 if (secondDigest != null && signingTime != null) { 1242 signerinfo.add(new DERTaggedObject(false, 0, getAuthenticatedAttributeSet(secondDigest, signingTime, ocsp))); 1243 } 1244 // Add the digestEncryptionAlgorithm 1245 v = new ASN1EncodableVector(); 1246 v.add(new DERObjectIdentifier(digestEncryptionAlgorithm)); 1247 v.add(new DERNull()); 1248 signerinfo.add(new DERSequence(v)); 1249 1250 // Add the digest 1251 signerinfo.add(new DEROctetString(digest)); 1252 1253 // When requested, go get and add the timestamp. May throw an exception. 1254 // Added by Martin Brunecky, 07/12/2007 folowing Aiken Sam, 2006-11-15 1255 // Sam found Adobe expects time-stamped SHA1-1 of the encrypted digest 1256 if (tsaClient != null) { 1257 byte[] tsImprint = MessageDigest.getInstance("SHA-1").digest(digest); 1258 byte[] tsToken = tsaClient.getTimeStampToken(this, tsImprint); 1259 if (tsToken != null) { 1260 ASN1EncodableVector unauthAttributes = buildUnauthenticatedAttributes(tsToken); 1261 if (unauthAttributes != null) { 1262 signerinfo.add(new DERTaggedObject(false, 1, new DERSet(unauthAttributes))); 1263 } 1264 } 1265 } 1266 1267 // Finally build the body out of all the components above 1268 ASN1EncodableVector body = new ASN1EncodableVector(); 1269 body.add(new DERInteger(version)); 1270 body.add(new DERSet(digestAlgorithms)); 1271 body.add(contentinfo); 1272 body.add(new DERTaggedObject(false, 0, dercertificates)); 1273 1274 // Only allow one signerInfo 1275 body.add(new DERSet(new DERSequence(signerinfo))); 1276 1277 // Now we have the body, wrap it in it's PKCS7Signed shell 1278 // and return it 1279 // 1280 ASN1EncodableVector whole = new ASN1EncodableVector(); 1281 whole.add(new DERObjectIdentifier(ID_PKCS7_SIGNED_DATA)); 1282 whole.add(new DERTaggedObject(0, new DERSequence(body))); 1283 1284 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 1285 1286 ASN1OutputStream dout = new ASN1OutputStream(bOut); 1287 dout.writeObject(new DERSequence(whole)); 1288 dout.close(); 1289 1290 return bOut.toByteArray(); 1291 } 1292 catch (Exception e) { 1293 throw new ExceptionConverter(e); 1294 } 1295 } 1296 1297 /** 1298 * Added by Aiken Sam, 2006-11-15, modifed by Martin Brunecky 07/12/2007 1299 * to start with the timeStampToken (signedData 1.2.840.113549.1.7.2). 1300 * Token is the TSA response without response status, which is usually 1301 * handled by the (vendor supplied) TSA request/response interface). 1302 * @param timeStampToken byte[] - time stamp token, DER encoded signedData 1303 * @return ASN1EncodableVector 1304 * @throws IOException 1305 */ 1306 private ASN1EncodableVector buildUnauthenticatedAttributes(byte[] timeStampToken) throws IOException { 1307 if (timeStampToken == null) 1308 return null; 1309 1310 // @todo: move this together with the rest of the defintions 1311 String ID_TIME_STAMP_TOKEN = "1.2.840.113549.1.9.16.2.14"; // RFC 3161 id-aa-timeStampToken 1312 1313 ASN1InputStream tempstream = new ASN1InputStream(new ByteArrayInputStream(timeStampToken)); 1314 ASN1EncodableVector unauthAttributes = new ASN1EncodableVector(); 1315 1316 ASN1EncodableVector v = new ASN1EncodableVector(); 1317 v.add(new DERObjectIdentifier(ID_TIME_STAMP_TOKEN)); // id-aa-timeStampToken 1318 ASN1Sequence seq = (ASN1Sequence) tempstream.readObject(); 1319 v.add(new DERSet(seq)); 1320 1321 unauthAttributes.add(new DERSequence(v)); 1322 return unauthAttributes; 1323 } 1324 1325 1326 /** 1327 * When using authenticatedAttributes the authentication process is different. 1328 * The document digest is generated and put inside the attribute. The signing is done over the DER encoded 1329 * authenticatedAttributes. This method provides that encoding and the parameters must be 1330 * exactly the same as in {@link #getEncodedPKCS7(byte[],Calendar)}. 1331 * <p> 1332 * A simple example: 1333 * <p> 1334 * <pre> 1335 * Calendar cal = Calendar.getInstance(); 1336 * PdfPKCS7 pk7 = new PdfPKCS7(key, chain, null, "SHA1", null, false); 1337 * MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); 1338 * byte buf[] = new byte[8192]; 1339 * int n; 1340 * InputStream inp = sap.getRangeStream(); 1341 * while ((n = inp.read(buf)) > 0) { 1342 * messageDigest.update(buf, 0, n); 1343 * } 1344 * byte hash[] = messageDigest.digest(); 1345 * byte sh[] = pk7.getAuthenticatedAttributeBytes(hash, cal); 1346 * pk7.update(sh, 0, sh.length); 1347 * byte sg[] = pk7.getEncodedPKCS7(hash, cal); 1348 * </pre> 1349 * @param secondDigest the content digest 1350 * @param signingTime the signing time 1351 * @return the byte array representation of the authenticatedAttributes ready to be signed 1352 */ 1353 public byte[] getAuthenticatedAttributeBytes(byte secondDigest[], Calendar signingTime, byte[] ocsp) { 1354 try { 1355 return getAuthenticatedAttributeSet(secondDigest, signingTime, ocsp).getEncoded(ASN1Encodable.DER); 1356 } 1357 catch (Exception e) { 1358 throw new ExceptionConverter(e); 1359 } 1360 } 1361 1362 private DERSet getAuthenticatedAttributeSet(byte secondDigest[], Calendar signingTime, byte[] ocsp) { 1363 try { 1364 ASN1EncodableVector attribute = new ASN1EncodableVector(); 1365 ASN1EncodableVector v = new ASN1EncodableVector(); 1366 v.add(new DERObjectIdentifier(ID_CONTENT_TYPE)); 1367 v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA))); 1368 attribute.add(new DERSequence(v)); 1369 v = new ASN1EncodableVector(); 1370 v.add(new DERObjectIdentifier(ID_SIGNING_TIME)); 1371 v.add(new DERSet(new DERUTCTime(signingTime.getTime()))); 1372 attribute.add(new DERSequence(v)); 1373 v = new ASN1EncodableVector(); 1374 v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST)); 1375 v.add(new DERSet(new DEROctetString(secondDigest))); 1376 attribute.add(new DERSequence(v)); 1377 if (ocsp != null || !crls.isEmpty()) { 1378 v = new ASN1EncodableVector(); 1379 v.add(new DERObjectIdentifier(ID_ADBE_REVOCATION)); 1380 1381 ASN1EncodableVector revocationV = new ASN1EncodableVector(); 1382 1383 if (!crls.isEmpty()) { 1384 ASN1EncodableVector v2 = new ASN1EncodableVector(); 1385 for (Object element : crls) { 1386 ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream(((X509CRL)element).getEncoded())); 1387 v2.add(t.readObject()); 1388 } 1389 revocationV.add(new DERTaggedObject(true, 0, new DERSequence(v2))); 1390 } 1391 1392 if (ocsp != null) { 1393 DEROctetString doctet = new DEROctetString(ocsp); 1394 ASN1EncodableVector vo1 = new ASN1EncodableVector(); 1395 ASN1EncodableVector v2 = new ASN1EncodableVector(); 1396 v2.add(OCSPObjectIdentifiers.id_pkix_ocsp_basic); 1397 v2.add(doctet); 1398 DEREnumerated den = new DEREnumerated(0); 1399 ASN1EncodableVector v3 = new ASN1EncodableVector(); 1400 v3.add(den); 1401 v3.add(new DERTaggedObject(true, 0, new DERSequence(v2))); 1402 vo1.add(new DERSequence(v3)); 1403 revocationV.add(new DERTaggedObject(true, 1, new DERSequence(vo1))); 1404 } 1405 1406 v.add(new DERSet(new DERSequence(revocationV))); 1407 attribute.add(new DERSequence(v)); 1408 } 1409 1410 return new DERSet(attribute); 1411 } 1412 catch (Exception e) { 1413 throw new ExceptionConverter(e); 1414 } 1415 } 1416 1417 /** 1418 * Getter for property reason. 1419 * @return Value of property reason. 1420 */ 1421 public String getReason() { 1422 return this.reason; 1423 } 1424 1425 /** 1426 * Setter for property reason. 1427 * @param reason New value of property reason. 1428 */ 1429 public void setReason(String reason) { 1430 this.reason = reason; 1431 } 1432 1433 /** 1434 * Getter for property location. 1435 * @return Value of property location. 1436 */ 1437 public String getLocation() { 1438 return this.location; 1439 } 1440 1441 /** 1442 * Setter for property location. 1443 * @param location New value of property location. 1444 */ 1445 public void setLocation(String location) { 1446 this.location = location; 1447 } 1448 1449 /** 1450 * Getter for property signDate. 1451 * @return Value of property signDate. 1452 */ 1453 public Calendar getSignDate() { 1454 return this.signDate; 1455 } 1456 1457 /** 1458 * Setter for property signDate. 1459 * @param signDate New value of property signDate. 1460 */ 1461 public void setSignDate(Calendar signDate) { 1462 this.signDate = signDate; 1463 } 1464 1465 /** 1466 * Getter for property sigName. 1467 * @return Value of property sigName. 1468 */ 1469 public String getSignName() { 1470 return this.signName; 1471 } 1472 1473 /** 1474 * Setter for property sigName. 1475 * @param signName New value of property sigName. 1476 */ 1477 public void setSignName(String signName) { 1478 this.signName = signName; 1479 } 1480 1481 /** 1482 * a class that holds an X509 name 1483 */ 1484 public static class X509Name { 1485 /** 1486 * country code - StringType(SIZE(2)) 1487 */ 1488 public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6"); 1489 1490 /** 1491 * organization - StringType(SIZE(1..64)) 1492 */ 1493 public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10"); 1494 1495 /** 1496 * organizational unit name - StringType(SIZE(1..64)) 1497 */ 1498 public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11"); 1499 1500 /** 1501 * Title 1502 */ 1503 public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12"); 1504 1505 /** 1506 * common name - StringType(SIZE(1..64)) 1507 */ 1508 public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3"); 1509 1510 /** 1511 * device serial number name - StringType(SIZE(1..64)) 1512 */ 1513 public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5"); 1514 1515 /** 1516 * locality name - StringType(SIZE(1..64)) 1517 */ 1518 public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7"); 1519 1520 /** 1521 * state, or province name - StringType(SIZE(1..64)) 1522 */ 1523 public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8"); 1524 1525 /** Naming attribute of type X520name */ 1526 public static final DERObjectIdentifier SURNAME = new DERObjectIdentifier("2.5.4.4"); 1527 /** Naming attribute of type X520name */ 1528 public static final DERObjectIdentifier GIVENNAME = new DERObjectIdentifier("2.5.4.42"); 1529 /** Naming attribute of type X520name */ 1530 public static final DERObjectIdentifier INITIALS = new DERObjectIdentifier("2.5.4.43"); 1531 /** Naming attribute of type X520name */ 1532 public static final DERObjectIdentifier GENERATION = new DERObjectIdentifier("2.5.4.44"); 1533 /** Naming attribute of type X520name */ 1534 public static final DERObjectIdentifier UNIQUE_IDENTIFIER = new DERObjectIdentifier("2.5.4.45"); 1535 1536 /** 1537 * Email address (RSA PKCS#9 extension) - IA5String. 1538 * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here. 1539 */ 1540 public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1"); 1541 1542 /** 1543 * email address in Verisign certificates 1544 */ 1545 public static final DERObjectIdentifier E = EmailAddress; 1546 1547 /** object identifier */ 1548 public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25"); 1549 1550 /** LDAP User id. */ 1551 public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1"); 1552 1553 /** A HashMap with default symbols */ 1554 public static HashMap<DERObjectIdentifier, String> DefaultSymbols = new HashMap<DERObjectIdentifier, String>(); 1555 1556 static { 1557 DefaultSymbols.put(C, "C"); 1558 DefaultSymbols.put(O, "O"); 1559 DefaultSymbols.put(T, "T"); 1560 DefaultSymbols.put(OU, "OU"); 1561 DefaultSymbols.put(CN, "CN"); 1562 DefaultSymbols.put(L, "L"); 1563 DefaultSymbols.put(ST, "ST"); 1564 DefaultSymbols.put(SN, "SN"); 1565 DefaultSymbols.put(EmailAddress, "E"); 1566 DefaultSymbols.put(DC, "DC"); 1567 DefaultSymbols.put(UID, "UID"); 1568 DefaultSymbols.put(SURNAME, "SURNAME"); 1569 DefaultSymbols.put(GIVENNAME, "GIVENNAME"); 1570 DefaultSymbols.put(INITIALS, "INITIALS"); 1571 DefaultSymbols.put(GENERATION, "GENERATION"); 1572 } 1573 /** A HashMap with values */ 1574 public HashMap<String, ArrayList<String>> values = new HashMap<String, ArrayList<String>>(); 1575 1576 /** 1577 * Constructs an X509 name 1578 * @param seq an ASN1 Sequence 1579 */ 1580 @SuppressWarnings("unchecked") 1581 public X509Name(ASN1Sequence seq) { 1582 Enumeration<ASN1Set> e = seq.getObjects(); 1583 1584 while (e.hasMoreElements()) { 1585 ASN1Set set = e.nextElement(); 1586 1587 for (int i = 0; i < set.size(); i++) { 1588 ASN1Sequence s = (ASN1Sequence)set.getObjectAt(i); 1589 String id = DefaultSymbols.get(s.getObjectAt(0)); 1590 if (id == null) 1591 continue; 1592 ArrayList<String> vs = values.get(id); 1593 if (vs == null) { 1594 vs = new ArrayList<String>(); 1595 values.put(id, vs); 1596 } 1597 vs.add(((DERString)s.getObjectAt(1)).getString()); 1598 } 1599 } 1600 } 1601 /** 1602 * Constructs an X509 name 1603 * @param dirName a directory name 1604 */ 1605 public X509Name(String dirName) { 1606 X509NameTokenizer nTok = new X509NameTokenizer(dirName); 1607 1608 while (nTok.hasMoreTokens()) { 1609 String token = nTok.nextToken(); 1610 int index = token.indexOf('='); 1611 1612 if (index == -1) { 1613 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("badly.formated.directory.string")); 1614 } 1615 1616 String id = token.substring(0, index).toUpperCase(); 1617 String value = token.substring(index + 1); 1618 ArrayList<String> vs = values.get(id); 1619 if (vs == null) { 1620 vs = new ArrayList<String>(); 1621 values.put(id, vs); 1622 } 1623 vs.add(value); 1624 } 1625 1626 } 1627 1628 public String getField(String name) { 1629 ArrayList<String> vs = values.get(name); 1630 return vs == null ? null : (String)vs.get(0); 1631 } 1632 1633 /** 1634 * gets a field array from the values Hashmap 1635 * @param name 1636 * @return an ArrayList 1637 */ 1638 public ArrayList<String> getFieldArray(String name) { 1639 ArrayList<String> vs = values.get(name); 1640 return vs == null ? null : vs; 1641 } 1642 1643 /** 1644 * getter for values 1645 * @return a HashMap with the fields of the X509 name 1646 */ 1647 public HashMap<String, ArrayList<String>> getFields() { 1648 return values; 1649 } 1650 1651 /** 1652 * @see java.lang.Object#toString() 1653 */ 1654 @Override 1655 public String toString() { 1656 return values.toString(); 1657 } 1658 } 1659 1660 /** 1661 * class for breaking up an X500 Name into it's component tokens, ala 1662 * java.util.StringTokenizer. We need this class as some of the 1663 * lightweight Java environment don't support classes like 1664 * StringTokenizer. 1665 */ 1666 public static class X509NameTokenizer { 1667 private String oid; 1668 private int index; 1669 private StringBuffer buf = new StringBuffer(); 1670 1671 public X509NameTokenizer( 1672 String oid) { 1673 this.oid = oid; 1674 this.index = -1; 1675 } 1676 1677 public boolean hasMoreTokens() { 1678 return index != oid.length(); 1679 } 1680 1681 public String nextToken() { 1682 if (index == oid.length()) { 1683 return null; 1684 } 1685 1686 int end = index + 1; 1687 boolean quoted = false; 1688 boolean escaped = false; 1689 1690 buf.setLength(0); 1691 1692 while (end != oid.length()) { 1693 char c = oid.charAt(end); 1694 1695 if (c == '"') { 1696 if (!escaped) { 1697 quoted = !quoted; 1698 } 1699 else { 1700 buf.append(c); 1701 } 1702 escaped = false; 1703 } 1704 else { 1705 if (escaped || quoted) { 1706 buf.append(c); 1707 escaped = false; 1708 } 1709 else if (c == '\\') { 1710 escaped = true; 1711 } 1712 else if (c == ',') { 1713 break; 1714 } 1715 else { 1716 buf.append(c); 1717 } 1718 } 1719 end++; 1720 } 1721 1722 index = end; 1723 return buf.toString().trim(); 1724 } 1725 } 1726}