Source for gnu.java.security.pkcs.SignerInfo

   1: /* SignerInfo.java -- a SignerInfo object, from PKCS #7
   2:    Copyright (C) 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.java.security.pkcs;
  39: 
  40: import gnu.java.security.Configuration;
  41: import gnu.java.security.OID;
  42: import gnu.java.security.ber.BER;
  43: import gnu.java.security.ber.BEREncodingException;
  44: import gnu.java.security.ber.BERReader;
  45: import gnu.java.security.ber.BERValue;
  46: import gnu.java.security.der.DER;
  47: import gnu.java.security.der.DERValue;
  48: import gnu.java.security.der.DERWriter;
  49: import gnu.java.security.util.Util;
  50: 
  51: import java.io.ByteArrayOutputStream;
  52: import java.io.IOException;
  53: import java.io.OutputStream;
  54: import java.math.BigInteger;
  55: import java.util.ArrayList;
  56: import java.util.logging.Logger;
  57: 
  58: import javax.security.auth.x500.X500Principal;
  59: 
  60: public class SignerInfo
  61: {
  62:   private static final Logger log = Logger.getLogger(SignerInfo.class.getName());
  63: 
  64:   private final BigInteger version;
  65:   private final BigInteger serialNumber;
  66:   private final X500Principal issuer;
  67:   private final OID digestAlgorithmId;
  68:   private final byte[] digestAlgorithmParams;
  69:   private final byte[] authenticatedAttributes;
  70:   private final OID digestEncryptionAlgorithmId;
  71:   private final byte[] digestEncryptionAlgorithmParams;
  72:   private final byte[] encryptedDigest;
  73:   private final byte[] unauthenticatedAttributes;
  74: 
  75:   /**
  76:    * Parse a SignerInfo object.
  77:    * <p>
  78:    * A SignerInfo is a structure with the following ASN.1 syntax:
  79:    * <pre>
  80:    * SignerInfo ::= SEQUENCE {
  81:    *   version                       Version, -- always 1 for PKCS7 v1.5
  82:    *   issuerAndSerialNumber         IssuerAndSerialNumber, -- an INTEGER
  83:    *   digestAlgorithm               DigestAlgorithmIdentifier,
  84:    *   authenticatedAttributes   [0] IMPLICIT Attributes OPTIONAL,
  85:    *   digestEncryptionAlgorithm     DigestEncryptionAlgorithmIdentifier,
  86:    *   encryptedDigest               EncryptedDigest,
  87:    *   unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
  88:    *
  89:    * IssuerAndSerialNumber ::= SEQUENCE {
  90:    *   issuer       Name,
  91:    *   serialNumber CertificateSerialNumber
  92:    * }
  93:    *
  94:    * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
  95:    *
  96:    * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  97:    *
  98:    * EncryptedDigest ::= OCTET STRING
  99:    * </pre>
 100:    */
 101:   public SignerInfo(BERReader ber) throws IOException
 102:   {
 103:     DERValue val = ber.read();
 104:     if (Configuration.DEBUG)
 105:       log.fine("SignerInfo: " + val);
 106:     if (!val.isConstructed())
 107:       throw new BEREncodingException("malformed SignerInfo");
 108: 
 109:     val = ber.read();
 110:     if (val.getTag() != BER.INTEGER)
 111:       throw new BEREncodingException("malformed Version");
 112: 
 113:     version = (BigInteger) val.getValue();
 114:     log.fine("  Version: " + version);
 115: 
 116:     val = ber.read();
 117:     if (!val.isConstructed())
 118:       throw new BEREncodingException("malformed IssuerAndSerialNumber");
 119:     if (Configuration.DEBUG)
 120:       log.fine("  IssuerAndSerialNumber: " + val);
 121: 
 122:     val = ber.read();
 123:     if (!val.isConstructed())
 124:       throw new BEREncodingException("malformed Issuer");
 125: 
 126:     issuer = new X500Principal(val.getEncoded());
 127:     ber.skip(val.getLength());
 128:     if (Configuration.DEBUG)
 129:       log.fine("    Issuer: " + issuer);
 130: 
 131:     val = ber.read();
 132:     if (val.getTag() != BER.INTEGER)
 133:       throw new BEREncodingException("malformed SerialNumber");
 134: 
 135:     serialNumber = (BigInteger) val.getValue();
 136:     if (Configuration.DEBUG)
 137:       log.fine("    SerialNumber: " + serialNumber);
 138: 
 139:     val = ber.read();
 140:     if (!val.isConstructed())
 141:       throw new BEREncodingException("malformed DigestAlgorithmIdentifier");
 142:     if (Configuration.DEBUG)
 143:       log.fine("  DigestAlgorithmIdentifier: " + val);
 144: 
 145:     int count = 0;
 146:     DERValue val2 = ber.read();
 147:     if (val2.getTag() != BER.OBJECT_IDENTIFIER)
 148:       throw new BEREncodingException("malformed AlgorithmIdentifier");
 149: 
 150:     digestAlgorithmId = (OID) val2.getValue();
 151:     if (Configuration.DEBUG)
 152:       log.fine("    digestAlgorithm OID: " + digestAlgorithmId);
 153: 
 154:     if (BERValue.isIndefinite(val))
 155:       {
 156:         val2 = ber.read();
 157:         if (val2 != BER.END_OF_SEQUENCE)
 158:           {
 159:             digestAlgorithmParams = val2.getEncoded();
 160:             val2 = ber.read();
 161:             if (val2 != BER.END_OF_SEQUENCE)
 162:               throw new BEREncodingException("expecting BER end-of-sequence");
 163:           }
 164:         else
 165:           digestAlgorithmParams = null;
 166:       }
 167:     else if (val2.getEncodedLength() < val.getLength())
 168:       {
 169:         val2 = ber.read();
 170:         digestAlgorithmParams = val2.getEncoded();
 171:         if (val2.isConstructed())
 172:           ber.skip(val2.getLength());
 173:       }
 174:     else
 175:       digestAlgorithmParams = null;
 176: 
 177:     if (Configuration.DEBUG)
 178:       {
 179:         log.fine("    digestAlgorithm params: ");
 180:         log.fine(Util.dumpString(digestAlgorithmParams,
 181:                                  "    digestAlgorithm params: "));
 182:       }
 183:     val = ber.read();
 184:     if (val.getTag() == 0)
 185:       {
 186:         authenticatedAttributes = val.getEncoded();
 187:         val = ber.read();
 188:         if (val.isConstructed())
 189:           ber.skip(val.getLength());
 190: 
 191:         val = ber.read();
 192:       }
 193:     else
 194:       authenticatedAttributes = null;
 195: 
 196:     if (Configuration.DEBUG)
 197:       {
 198:         log.fine("  AuthenticatedAttributes: ");
 199:         log.fine(Util.dumpString(authenticatedAttributes,
 200:                                  "  AuthenticatedAttributes: "));
 201:       }
 202:     if (!val.isConstructed())
 203:       throw new BEREncodingException("malformed DigestEncryptionAlgorithmIdentifier");
 204:     if (Configuration.DEBUG)
 205:       log.fine("  DigestEncryptionAlgorithmIdentifier: " + val);
 206:     count = 0;
 207:     val2 = ber.read();
 208:     if (val2.getTag() != BER.OBJECT_IDENTIFIER)
 209:       throw new BEREncodingException("malformed AlgorithmIdentifier");
 210: 
 211:     digestEncryptionAlgorithmId = (OID) val2.getValue();
 212:     if (Configuration.DEBUG)
 213:       log.fine("    digestEncryptionAlgorithm OID: " + digestEncryptionAlgorithmId);
 214: 
 215:     if (BERValue.isIndefinite(val))
 216:       {
 217:         val2 = ber.read();
 218:         if (val2 != BER.END_OF_SEQUENCE)
 219:           {
 220:             digestEncryptionAlgorithmParams = val2.getEncoded();
 221:             val2 = ber.read();
 222:             if (val2 != BER.END_OF_SEQUENCE)
 223:               throw new BEREncodingException("expecting BER end-of-sequence");
 224:           }
 225:         else
 226:           digestEncryptionAlgorithmParams = null;
 227:       }
 228:     else if (val2.getEncodedLength() < val.getLength())
 229:       {
 230:         val2 = ber.read();
 231:         digestEncryptionAlgorithmParams = val2.getEncoded();
 232:         if (val2.isConstructed())
 233:           ber.skip(val2.getLength());
 234:       }
 235:     else
 236:       digestEncryptionAlgorithmParams = null;
 237: 
 238:     if (Configuration.DEBUG)
 239:       {
 240:         log.fine("    digestEncryptionAlgorithm params: ");
 241:         log.fine(Util.dumpString(digestEncryptionAlgorithmParams,
 242:                                  "    digestEncryptionAlgorithm params: "));
 243:       }
 244:     val = ber.read();
 245:     if (val.getTag() != BER.OCTET_STRING)
 246:       throw new BEREncodingException("malformed EncryptedDigest");
 247: 
 248:     encryptedDigest = (byte[]) val.getValue();
 249:     if (Configuration.DEBUG)
 250:       {
 251:         log.fine("  EncryptedDigest: ");
 252:         log.fine(Util.dumpString(encryptedDigest, "  EncryptedDigest: "));
 253:       }
 254:     if (ber.peek() == 1)
 255:       unauthenticatedAttributes = ber.read().getEncoded();
 256:     else
 257:       unauthenticatedAttributes = null;
 258: 
 259:     if (Configuration.DEBUG)
 260:       {
 261:         log.fine("  UnauthenticatedAttributes: ");
 262:         log.fine(Util.dumpString(unauthenticatedAttributes,
 263:                                  "  UnauthenticatedAttributes: "));
 264:       }
 265:     if (ber.peek() == 0)
 266:       ber.read();
 267:   }
 268: 
 269:   /**
 270:    * Constructs a new instance of <code>SignerInfo</code> given a designated
 271:    * set of fields.
 272:    *
 273:    * @param issuer the X.500 Principal name of the signer referenced by this
 274:    *          instance.
 275:    * @param serialNumber the serial number of the certificate being used. Both
 276:    *          this and the previous arguments are gleaned from the signer's
 277:    *          certificate.
 278:    * @param digestAlgorithmOID the OID of the digest algorithm. When
 279:    *          constructing the DigestAlgorithmIdentifier with this OID, the
 280:    *          parameters part will be NULL.
 281:    * @param authenticatedAttributes the encoding of the set of authenticated
 282:    *          attributes to use.
 283:    * @param digestEncryptionAlgorithmOID the OID of the digest encryption
 284:    *          algorithm. When constructing the
 285:    *          DigestEncryptionAlgorithmIdentifier with this OID, the parameters
 286:    *          part will be NULL.
 287:    * @param encryptedDigest the encrypted hash generated with this signer's
 288:    *          private key.
 289:    * @param unauthenticatedAttributes the encoding of the set of
 290:    *          unauthencticated attributes.
 291:    */
 292:   public SignerInfo(X500Principal issuer, BigInteger serialNumber,
 293:                     OID digestAlgorithmOID, byte[] authenticatedAttributes,
 294:                     OID digestEncryptionAlgorithmOID,
 295:                     byte[] encryptedDigest, byte[] unauthenticatedAttributes)
 296:   {
 297:     super();
 298: 
 299:     this.version = BigInteger.ONE;
 300:     this.issuer = issuer;
 301:     this.serialNumber = serialNumber;
 302:     this.digestAlgorithmId = digestAlgorithmOID;
 303:     this.digestAlgorithmParams = null;
 304:     this.authenticatedAttributes = authenticatedAttributes;
 305:     this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmOID;
 306:     this.digestEncryptionAlgorithmParams = null;
 307:     this.encryptedDigest = encryptedDigest;
 308:     this.unauthenticatedAttributes = unauthenticatedAttributes;
 309:   }
 310: 
 311:   public BigInteger getVersion()
 312:   {
 313:     return version;
 314:   }
 315: 
 316:   public BigInteger getSerialNumber()
 317:   {
 318:     return serialNumber;
 319:   }
 320: 
 321:   public X500Principal getIssuer()
 322:   {
 323:     return issuer;
 324:   }
 325: 
 326:   public OID getDigestAlgorithmId()
 327:   {
 328:     return digestAlgorithmId;
 329:   }
 330: 
 331:   public byte[] getDigestAlgorithmParams()
 332:   {
 333:     return (digestAlgorithmParams != null
 334:             ? (byte[]) digestAlgorithmParams.clone()
 335:             : null);
 336:   }
 337: 
 338:   public byte[] getAuthenticatedAttributes()
 339:   {
 340:     return (authenticatedAttributes != null
 341:             ? (byte[]) authenticatedAttributes.clone()
 342:             : null);
 343:   }
 344: 
 345:   public OID getDigestEncryptionAlgorithmId()
 346:   {
 347:     return digestEncryptionAlgorithmId;
 348:   }
 349: 
 350:   public byte[] getDigestEncryptionAlgorithmParams()
 351:   {
 352:     return (digestEncryptionAlgorithmParams != null
 353:             ? (byte[]) digestEncryptionAlgorithmParams.clone()
 354:             : null);
 355:   }
 356: 
 357:   public byte[] getEncryptedDigest()
 358:   {
 359:     return (encryptedDigest != null ? (byte[]) encryptedDigest.clone() : null);
 360:   }
 361: 
 362:   public byte[] getUnauthenticatedAttributes()
 363:   {
 364:     return (unauthenticatedAttributes != null
 365:             ? (byte[]) unauthenticatedAttributes.clone()
 366:             : null);
 367:   }
 368: 
 369:   /**
 370:    * Writes to the designated output stream the DER encoding of the current
 371:    * contents of this instance.
 372:    *
 373:    * @param out the destination output stream.
 374:    * @throws IOException if an I/O related exception occurs during the process.
 375:    */
 376:   public void encode(OutputStream out) throws IOException
 377:   {
 378:     DERValue derVersion = new DERValue(DER.INTEGER, version);
 379: 
 380:     ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
 381:     baos.write(issuer.getEncoded());
 382:     DERValue derSerialNumber = new DERValue(DER.INTEGER, serialNumber);
 383:     DERWriter.write(baos, derSerialNumber);
 384:     baos.flush();
 385:     byte[] b = baos.toByteArray();
 386:     DERValue derIssuerAndSerialNumber =
 387:         new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, b.length, b, null);
 388: 
 389:     DERValue derDigestAlgorithmOID = new DERValue(DER.OBJECT_IDENTIFIER,
 390:                                                   digestAlgorithmId);
 391:     ArrayList digestAlgorithmIdentifier = new ArrayList(1);
 392:     digestAlgorithmIdentifier.add(derDigestAlgorithmOID);
 393:     DERValue derDigestAlgorithmIdentifier =
 394:         new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, digestAlgorithmIdentifier);
 395: 
 396:     DERValue derAuthenticatedAttributes;
 397:     if (authenticatedAttributes == null)
 398:       derAuthenticatedAttributes = new DERValue(DER.NULL, null);
 399:     else
 400:       derAuthenticatedAttributes = new DERValue(DER.CONSTRUCTED | DER.SET,
 401:                                                 authenticatedAttributes);
 402: 
 403:     DERValue derDigestEncryptionAlgorithmOID =
 404:         new DERValue(DER.OBJECT_IDENTIFIER, digestEncryptionAlgorithmId);
 405:     ArrayList digestEncryptionAlgorithmIdentifier = new ArrayList(1);
 406:     digestEncryptionAlgorithmIdentifier.add(derDigestEncryptionAlgorithmOID);
 407:     DERValue derDigestEncryptionAlgorithmIdentifier =
 408:         new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, digestEncryptionAlgorithmIdentifier);
 409: 
 410:     DERValue derEncryptedDigest = new DERValue(DER.OCTET_STRING, encryptedDigest);
 411: 
 412:     DERValue derUnauthenticatedAttributes;
 413:     if (unauthenticatedAttributes == null)
 414:       derUnauthenticatedAttributes = new DERValue(DER.NULL, null);
 415:     else
 416:       derUnauthenticatedAttributes = new DERValue(DER.CONSTRUCTED | DER.SET,
 417:                                                   unauthenticatedAttributes);
 418: 
 419:     ArrayList signerInfo = new ArrayList(5);
 420:     signerInfo.add(derVersion);
 421:     signerInfo.add(derIssuerAndSerialNumber);
 422:     signerInfo.add(derDigestAlgorithmIdentifier);
 423:     signerInfo.add(derDigestEncryptionAlgorithmIdentifier);
 424:     signerInfo.add(derEncryptedDigest);
 425:     DERValue derSignerInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
 426:                                           signerInfo);
 427:     DERWriter.write(out, derSignerInfo);
 428:   }
 429: }