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