Source for gnu.java.security.pkcs.SignerInfo

   1: /* SignerInfo.java -- a SignerInfo object, from PKCS #7
   2:    Copyright (C) 2004, 2005, 2010  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 = Configuration.DEBUG ?
  63:                         Logger.getLogger(SignerInfo.class.getName()) : null;
  64: 
  65:   private final BigInteger version;
  66:   private final BigInteger serialNumber;
  67:   private final X500Principal issuer;
  68:   private final OID digestAlgorithmId;
  69:   private final byte[] digestAlgorithmParams;
  70:   private final byte[] authenticatedAttributes;
  71:   private final OID digestEncryptionAlgorithmId;
  72:   private final byte[] digestEncryptionAlgorithmParams;
  73:   private final byte[] encryptedDigest;
  74:   private final byte[] unauthenticatedAttributes;
  75: 
  76:   /**
  77:    * Parse a SignerInfo object.
  78:    * <p>
  79:    * A SignerInfo is a structure with the following ASN.1 syntax:
  80:    * <pre>
  81:    * SignerInfo ::= SEQUENCE {
  82:    *   version                       Version, -- always 1 for PKCS7 v1.5
  83:    *   issuerAndSerialNumber         IssuerAndSerialNumber, -- an INTEGER
  84:    *   digestAlgorithm               DigestAlgorithmIdentifier,
  85:    *   authenticatedAttributes   [0] IMPLICIT Attributes OPTIONAL,
  86:    *   digestEncryptionAlgorithm     DigestEncryptionAlgorithmIdentifier,
  87:    *   encryptedDigest               EncryptedDigest,
  88:    *   unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
  89:    *
  90:    * IssuerAndSerialNumber ::= SEQUENCE {
  91:    *   issuer       Name,
  92:    *   serialNumber CertificateSerialNumber
  93:    * }
  94:    *
  95:    * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
  96:    *
  97:    * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  98:    *
  99:    * EncryptedDigest ::= OCTET STRING
 100:    * </pre>
 101:    */
 102:   public SignerInfo(BERReader ber) throws IOException
 103:   {
 104:     DERValue val = ber.read();
 105:     if (Configuration.DEBUG)
 106:       log.fine("SignerInfo: " + val);
 107:     if (!val.isConstructed())
 108:       throw new BEREncodingException("malformed SignerInfo");
 109: 
 110:     val = ber.read();
 111:     if (val.getTag() != BER.INTEGER)
 112:       throw new BEREncodingException("malformed Version");
 113: 
 114:     version = (BigInteger) val.getValue();
 115:     if (Configuration.DEBUG)
 116:       log.fine("  Version: " + version);
 117: 
 118:     val = ber.read();
 119:     if (!val.isConstructed())
 120:       throw new BEREncodingException("malformed IssuerAndSerialNumber");
 121:     if (Configuration.DEBUG)
 122:       log.fine("  IssuerAndSerialNumber: " + val);
 123: 
 124:     val = ber.read();
 125:     if (!val.isConstructed())
 126:       throw new BEREncodingException("malformed Issuer");
 127: 
 128:     issuer = new X500Principal(val.getEncoded());
 129:     ber.skip(val.getLength());
 130:     if (Configuration.DEBUG)
 131:       log.fine("    Issuer: " + issuer);
 132: 
 133:     val = ber.read();
 134:     if (val.getTag() != BER.INTEGER)
 135:       throw new BEREncodingException("malformed SerialNumber");
 136: 
 137:     serialNumber = (BigInteger) val.getValue();
 138:     if (Configuration.DEBUG)
 139:       log.fine("    SerialNumber: " + serialNumber);
 140: 
 141:     val = ber.read();
 142:     if (!val.isConstructed())
 143:       throw new BEREncodingException("malformed DigestAlgorithmIdentifier");
 144:     if (Configuration.DEBUG)
 145:       log.fine("  DigestAlgorithmIdentifier: " + val);
 146: 
 147:     int count = 0;
 148:     DERValue val2 = ber.read();
 149:     if (val2.getTag() != BER.OBJECT_IDENTIFIER)
 150:       throw new BEREncodingException("malformed AlgorithmIdentifier");
 151: 
 152:     digestAlgorithmId = (OID) val2.getValue();
 153:     if (Configuration.DEBUG)
 154:       log.fine("    digestAlgorithm OID: " + digestAlgorithmId);
 155: 
 156:     if (BERValue.isIndefinite(val))
 157:       {
 158:         val2 = ber.read();
 159:         if (val2 != BER.END_OF_SEQUENCE)
 160:           {
 161:             digestAlgorithmParams = val2.getEncoded();
 162:             val2 = ber.read();
 163:             if (val2 != BER.END_OF_SEQUENCE)
 164:               throw new BEREncodingException("expecting BER end-of-sequence");
 165:           }
 166:         else
 167:           digestAlgorithmParams = null;
 168:       }
 169:     else if (val2.getEncodedLength() < val.getLength())
 170:       {
 171:         val2 = ber.read();
 172:         digestAlgorithmParams = val2.getEncoded();
 173:         if (val2.isConstructed())
 174:           ber.skip(val2.getLength());
 175:       }
 176:     else
 177:       digestAlgorithmParams = null;
 178: 
 179:     if (Configuration.DEBUG)
 180:       {
 181:         log.fine("    digestAlgorithm params: ");
 182:         log.fine(Util.dumpString(digestAlgorithmParams,
 183:                                  "    digestAlgorithm params: "));
 184:       }
 185:     val = ber.read();
 186:     if (val.getTag() == 0)
 187:       {
 188:         authenticatedAttributes = val.getEncoded();
 189:         val = ber.read();
 190:         if (val.isConstructed())
 191:           ber.skip(val.getLength());
 192: 
 193:         val = ber.read();
 194:       }
 195:     else
 196:       authenticatedAttributes = null;
 197: 
 198:     if (Configuration.DEBUG)
 199:       {
 200:         log.fine("  AuthenticatedAttributes: ");
 201:         log.fine(Util.dumpString(authenticatedAttributes,
 202:                                  "  AuthenticatedAttributes: "));
 203:       }
 204:     if (!val.isConstructed())
 205:       throw new BEREncodingException("malformed DigestEncryptionAlgorithmIdentifier");
 206:     if (Configuration.DEBUG)
 207:       log.fine("  DigestEncryptionAlgorithmIdentifier: " + val);
 208:     count = 0;
 209:     val2 = ber.read();
 210:     if (val2.getTag() != BER.OBJECT_IDENTIFIER)
 211:       throw new BEREncodingException("malformed AlgorithmIdentifier");
 212: 
 213:     digestEncryptionAlgorithmId = (OID) val2.getValue();
 214:     if (Configuration.DEBUG)
 215:       log.fine("    digestEncryptionAlgorithm OID: " + digestEncryptionAlgorithmId);
 216: 
 217:     if (BERValue.isIndefinite(val))
 218:       {
 219:         val2 = ber.read();
 220:         if (val2 != BER.END_OF_SEQUENCE)
 221:           {
 222:             digestEncryptionAlgorithmParams = val2.getEncoded();
 223:             val2 = ber.read();
 224:             if (val2 != BER.END_OF_SEQUENCE)
 225:               throw new BEREncodingException("expecting BER end-of-sequence");
 226:           }
 227:         else
 228:           digestEncryptionAlgorithmParams = null;
 229:       }
 230:     else if (val2.getEncodedLength() < val.getLength())
 231:       {
 232:         val2 = ber.read();
 233:         digestEncryptionAlgorithmParams = val2.getEncoded();
 234:         if (val2.isConstructed())
 235:           ber.skip(val2.getLength());
 236:       }
 237:     else
 238:       digestEncryptionAlgorithmParams = null;
 239: 
 240:     if (Configuration.DEBUG)
 241:       {
 242:         log.fine("    digestEncryptionAlgorithm params: ");
 243:         log.fine(Util.dumpString(digestEncryptionAlgorithmParams,
 244:                                  "    digestEncryptionAlgorithm params: "));
 245:       }
 246:     val = ber.read();
 247:     if (val.getTag() != BER.OCTET_STRING)
 248:       throw new BEREncodingException("malformed EncryptedDigest");
 249: 
 250:     encryptedDigest = (byte[]) val.getValue();
 251:     if (Configuration.DEBUG)
 252:       {
 253:         log.fine("  EncryptedDigest: ");
 254:         log.fine(Util.dumpString(encryptedDigest, "  EncryptedDigest: "));
 255:       }
 256:     if (ber.peek() == 1)
 257:       unauthenticatedAttributes = ber.read().getEncoded();
 258:     else
 259:       unauthenticatedAttributes = null;
 260: 
 261:     if (Configuration.DEBUG)
 262:       {
 263:         log.fine("  UnauthenticatedAttributes: ");
 264:         log.fine(Util.dumpString(unauthenticatedAttributes,
 265:                                  "  UnauthenticatedAttributes: "));
 266:       }
 267:     if (ber.peek() == 0)
 268:       ber.read();
 269:   }
 270: 
 271:   /**
 272:    * Constructs a new instance of <code>SignerInfo</code> given a designated
 273:    * set of fields.
 274:    *
 275:    * @param issuer the X.500 Principal name of the signer referenced by this
 276:    *          instance.
 277:    * @param serialNumber the serial number of the certificate being used. Both
 278:    *          this and the previous arguments are gleaned from the signer's
 279:    *          certificate.
 280:    * @param digestAlgorithmOID the OID of the digest algorithm. When
 281:    *          constructing the DigestAlgorithmIdentifier with this OID, the
 282:    *          parameters part will be NULL.
 283:    * @param authenticatedAttributes the encoding of the set of authenticated
 284:    *          attributes to use.
 285:    * @param digestEncryptionAlgorithmOID the OID of the digest encryption
 286:    *          algorithm. When constructing the
 287:    *          DigestEncryptionAlgorithmIdentifier with this OID, the parameters
 288:    *          part will be NULL.
 289:    * @param encryptedDigest the encrypted hash generated with this signer's
 290:    *          private key.
 291:    * @param unauthenticatedAttributes the encoding of the set of
 292:    *          unauthencticated attributes.
 293:    */
 294:   public SignerInfo(X500Principal issuer, BigInteger serialNumber,
 295:                     OID digestAlgorithmOID, byte[] authenticatedAttributes,
 296:                     OID digestEncryptionAlgorithmOID,
 297:                     byte[] encryptedDigest, byte[] unauthenticatedAttributes)
 298:   {
 299:     super();
 300: 
 301:     this.version = BigInteger.ONE;
 302:     this.issuer = issuer;
 303:     this.serialNumber = serialNumber;
 304:     this.digestAlgorithmId = digestAlgorithmOID;
 305:     this.digestAlgorithmParams = null;
 306:     this.authenticatedAttributes = authenticatedAttributes;
 307:     this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmOID;
 308:     this.digestEncryptionAlgorithmParams = null;
 309:     this.encryptedDigest = encryptedDigest;
 310:     this.unauthenticatedAttributes = unauthenticatedAttributes;
 311:   }
 312: 
 313:   public BigInteger getVersion()
 314:   {
 315:     return version;
 316:   }
 317: 
 318:   public BigInteger getSerialNumber()
 319:   {
 320:     return serialNumber;
 321:   }
 322: 
 323:   public X500Principal getIssuer()
 324:   {
 325:     return issuer;
 326:   }
 327: 
 328:   public OID getDigestAlgorithmId()
 329:   {
 330:     return digestAlgorithmId;
 331:   }
 332: 
 333:   public byte[] getDigestAlgorithmParams()
 334:   {
 335:     return (digestAlgorithmParams != null
 336:             ? (byte[]) digestAlgorithmParams.clone()
 337:             : null);
 338:   }
 339: 
 340:   public byte[] getAuthenticatedAttributes()
 341:   {
 342:     return (authenticatedAttributes != null
 343:             ? (byte[]) authenticatedAttributes.clone()
 344:             : null);
 345:   }
 346: 
 347:   public OID getDigestEncryptionAlgorithmId()
 348:   {
 349:     return digestEncryptionAlgorithmId;
 350:   }
 351: 
 352:   public byte[] getDigestEncryptionAlgorithmParams()
 353:   {
 354:     return (digestEncryptionAlgorithmParams != null
 355:             ? (byte[]) digestEncryptionAlgorithmParams.clone()
 356:             : null);
 357:   }
 358: 
 359:   public byte[] getEncryptedDigest()
 360:   {
 361:     return (encryptedDigest != null ? (byte[]) encryptedDigest.clone() : null);
 362:   }
 363: 
 364:   public byte[] getUnauthenticatedAttributes()
 365:   {
 366:     return (unauthenticatedAttributes != null
 367:             ? (byte[]) unauthenticatedAttributes.clone()
 368:             : null);
 369:   }
 370: 
 371:   /**
 372:    * Writes to the designated output stream the DER encoding of the current
 373:    * contents of this instance.
 374:    *
 375:    * @param out the destination output stream.
 376:    * @throws IOException if an I/O related exception occurs during the process.
 377:    */
 378:   public void encode(OutputStream out) throws IOException
 379:   {
 380:     DERValue derVersion = new DERValue(DER.INTEGER, version);
 381: 
 382:     ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
 383:     baos.write(issuer.getEncoded());
 384:     DERValue derSerialNumber = new DERValue(DER.INTEGER, serialNumber);
 385:     DERWriter.write(baos, derSerialNumber);
 386:     baos.flush();
 387:     byte[] b = baos.toByteArray();
 388:     DERValue derIssuerAndSerialNumber =
 389:         new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, b.length, b, null);
 390: 
 391:     DERValue derDigestAlgorithmOID = new DERValue(DER.OBJECT_IDENTIFIER,
 392:                                                   digestAlgorithmId);
 393:     ArrayList digestAlgorithmIdentifier = new ArrayList(1);
 394:     digestAlgorithmIdentifier.add(derDigestAlgorithmOID);
 395:     DERValue derDigestAlgorithmIdentifier =
 396:         new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, digestAlgorithmIdentifier);
 397: 
 398:     DERValue derAuthenticatedAttributes;
 399:     if (authenticatedAttributes == null)
 400:       derAuthenticatedAttributes = new DERValue(DER.NULL, null);
 401:     else
 402:       derAuthenticatedAttributes = new DERValue(DER.CONSTRUCTED | DER.SET,
 403:                                                 authenticatedAttributes);
 404: 
 405:     DERValue derDigestEncryptionAlgorithmOID =
 406:         new DERValue(DER.OBJECT_IDENTIFIER, digestEncryptionAlgorithmId);
 407:     ArrayList digestEncryptionAlgorithmIdentifier = new ArrayList(1);
 408:     digestEncryptionAlgorithmIdentifier.add(derDigestEncryptionAlgorithmOID);
 409:     DERValue derDigestEncryptionAlgorithmIdentifier =
 410:         new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, digestEncryptionAlgorithmIdentifier);
 411: 
 412:     DERValue derEncryptedDigest = new DERValue(DER.OCTET_STRING, encryptedDigest);
 413: 
 414:     DERValue derUnauthenticatedAttributes;
 415:     if (unauthenticatedAttributes == null)
 416:       derUnauthenticatedAttributes = new DERValue(DER.NULL, null);
 417:     else
 418:       derUnauthenticatedAttributes = new DERValue(DER.CONSTRUCTED | DER.SET,
 419:                                                   unauthenticatedAttributes);
 420: 
 421:     ArrayList signerInfo = new ArrayList(5);
 422:     signerInfo.add(derVersion);
 423:     signerInfo.add(derIssuerAndSerialNumber);
 424:     signerInfo.add(derDigestAlgorithmIdentifier);
 425:     signerInfo.add(derDigestEncryptionAlgorithmIdentifier);
 426:     signerInfo.add(derEncryptedDigest);
 427:     DERValue derSignerInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
 428:                                           signerInfo);
 429:     DERWriter.write(out, derSignerInfo);
 430:   }
 431: }