1 /* SignerInfo.java -- a SignerInfo object, from PKCS #7
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
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
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. */
38 package gnu
.java
.security
.pkcs
;
40 import gnu
.java
.security
.OID
;
41 import gnu
.java
.security
.ber
.BER
;
42 import gnu
.java
.security
.ber
.BEREncodingException
;
43 import gnu
.java
.security
.ber
.BERReader
;
44 import gnu
.java
.security
.ber
.BERValue
;
45 import gnu
.java
.security
.der
.DER
;
46 import gnu
.java
.security
.der
.DERValue
;
47 import gnu
.java
.security
.der
.DERWriter
;
48 import gnu
.java
.security
.util
.Util
;
50 import java
.io
.ByteArrayOutputStream
;
51 import java
.io
.IOException
;
52 import java
.io
.OutputStream
;
54 import java
.math
.BigInteger
;
55 import java
.util
.ArrayList
;
56 import java
.util
.logging
.Logger
;
58 import javax
.security
.auth
.x500
.X500Principal
;
60 public class SignerInfo
62 private static final Logger log
= Logger
.getLogger(SignerInfo
.class.getName());
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
;
76 * Parse a SignerInfo object.
78 * A SignerInfo is a structure with the following ASN.1 syntax:
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 }
89 * IssuerAndSerialNumber ::= SEQUENCE {
91 * serialNumber CertificateSerialNumber
94 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
96 * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
98 * EncryptedDigest ::= OCTET STRING
101 public SignerInfo(BERReader ber
) throws IOException
103 DERValue val
= ber
.read();
104 log
.finest("SignerInfo: " + val
);
105 if (!val
.isConstructed())
106 throw new BEREncodingException("malformed SignerInfo");
109 if (val
.getTag() != BER
.INTEGER
)
110 throw new BEREncodingException("malformed Version");
112 version
= (BigInteger
) val
.getValue();
113 log
.finest(" Version: " + version
);
116 if (!val
.isConstructed())
117 throw new BEREncodingException("malformed IssuerAndSerialNumber");
119 log
.finest(" IssuerAndSerialNumber: " + val
);
122 if (!val
.isConstructed())
123 throw new BEREncodingException("malformed Issuer");
125 issuer
= new X500Principal(val
.getEncoded());
126 ber
.skip(val
.getLength());
127 log
.finest(" Issuer: " + issuer
);
130 if (val
.getTag() != BER
.INTEGER
)
131 throw new BEREncodingException("malformed SerialNumber");
133 serialNumber
= (BigInteger
) val
.getValue();
134 log
.finest(" SerialNumber: " + serialNumber
);
137 if (!val
.isConstructed())
138 throw new BEREncodingException("malformed DigestAlgorithmIdentifier");
140 log
.finest(" DigestAlgorithmIdentifier: " + val
);
143 DERValue val2
= ber
.read();
144 if (val2
.getTag() != BER
.OBJECT_IDENTIFIER
)
145 throw new BEREncodingException("malformed AlgorithmIdentifier");
147 digestAlgorithmId
= (OID
) val2
.getValue();
148 log
.finest(" digestAlgorithm OID: " + digestAlgorithmId
);
150 if (BERValue
.isIndefinite(val
))
153 if (val2
!= BER
.END_OF_SEQUENCE
)
155 digestAlgorithmParams
= val2
.getEncoded();
157 if (val2
!= BER
.END_OF_SEQUENCE
)
158 throw new BEREncodingException("expecting BER end-of-sequence");
161 digestAlgorithmParams
= null;
163 else if (val2
.getEncodedLength() < val
.getLength())
166 digestAlgorithmParams
= val2
.getEncoded();
167 if (val2
.isConstructed())
168 ber
.skip(val2
.getLength());
171 digestAlgorithmParams
= null;
173 log
.finest(" digestAlgorithm params: ");
174 log
.finest(Util
.dumpString(digestAlgorithmParams
,
175 " digestAlgorithm params: "));
178 if (val
.getTag() == 0)
180 authenticatedAttributes
= val
.getEncoded();
182 if (val
.isConstructed())
183 ber
.skip(val
.getLength());
188 authenticatedAttributes
= null;
190 log
.finest(" AuthenticatedAttributes: ");
191 log
.finest(Util
.dumpString(authenticatedAttributes
,
192 " AuthenticatedAttributes: "));
194 if (!val
.isConstructed())
195 throw new BEREncodingException("malformed DigestEncryptionAlgorithmIdentifier");
197 log
.finest(" DigestEncryptionAlgorithmIdentifier: " + val
);
200 if (val2
.getTag() != BER
.OBJECT_IDENTIFIER
)
201 throw new BEREncodingException("malformed AlgorithmIdentifier");
203 digestEncryptionAlgorithmId
= (OID
) val2
.getValue();
204 log
.finest(" digestEncryptionAlgorithm OID: " + digestEncryptionAlgorithmId
);
206 if (BERValue
.isIndefinite(val
))
209 if (val2
!= BER
.END_OF_SEQUENCE
)
211 digestEncryptionAlgorithmParams
= val2
.getEncoded();
213 if (val2
!= BER
.END_OF_SEQUENCE
)
214 throw new BEREncodingException("expecting BER end-of-sequence");
217 digestEncryptionAlgorithmParams
= null;
219 else if (val2
.getEncodedLength() < val
.getLength())
222 digestEncryptionAlgorithmParams
= val2
.getEncoded();
223 if (val2
.isConstructed())
224 ber
.skip(val2
.getLength());
227 digestEncryptionAlgorithmParams
= null;
229 log
.finest(" digestEncryptionAlgorithm params: ");
230 log
.finest(Util
.dumpString(digestEncryptionAlgorithmParams
,
231 " digestEncryptionAlgorithm params: "));
234 if (val
.getTag() != BER
.OCTET_STRING
)
235 throw new BEREncodingException("malformed EncryptedDigest");
237 encryptedDigest
= (byte[]) val
.getValue();
238 log
.finest(" EncryptedDigest: ");
239 log
.finest(Util
.dumpString(encryptedDigest
, " EncryptedDigest: "));
242 unauthenticatedAttributes
= ber
.read().getEncoded();
244 unauthenticatedAttributes
= null;
246 log
.finest(" UnauthenticatedAttributes: ");
247 log
.finest(Util
.dumpString(unauthenticatedAttributes
,
248 " UnauthenticatedAttributes: "));
255 * Constructs a new instance of <code>SignerInfo</code> given a designated
258 * @param issuer the X.500 Principal name of the signer referenced by this
260 * @param serialNumber the serial number of the certificate being used. Both
261 * this and the previous arguments are gleaned from the signer's
263 * @param digestAlgorithmOID the OID of the digest algorithm. When
264 * constructing the DigestAlgorithmIdentifier with this OID, the
265 * parameters part will be NULL.
266 * @param authenticatedAttributes the encoding of the set of authenticated
268 * @param digestEncryptionAlgorithmOID the OID of the digest encryption
269 * algorithm. When constructing the
270 * DigestEncryptionAlgorithmIdentifier with this OID, the parameters
272 * @param encryptedDigest the encrypted hash generated with this signer's
274 * @param unauthenticatedAttributes the encoding of the set of
275 * unauthencticated attributes.
277 public SignerInfo(X500Principal issuer
, BigInteger serialNumber
,
278 OID digestAlgorithmOID
, byte[] authenticatedAttributes
,
279 OID digestEncryptionAlgorithmOID
,
280 byte[] encryptedDigest
, byte[] unauthenticatedAttributes
)
284 this.version
= BigInteger
.ONE
;
285 this.issuer
= issuer
;
286 this.serialNumber
= serialNumber
;
287 this.digestAlgorithmId
= digestAlgorithmOID
;
288 this.digestAlgorithmParams
= null;
289 this.authenticatedAttributes
= authenticatedAttributes
;
290 this.digestEncryptionAlgorithmId
= digestEncryptionAlgorithmOID
;
291 this.digestEncryptionAlgorithmParams
= null;
292 this.encryptedDigest
= encryptedDigest
;
293 this.unauthenticatedAttributes
= unauthenticatedAttributes
;
296 public BigInteger
getVersion()
301 public BigInteger
getSerialNumber()
306 public X500Principal
getIssuer()
311 public OID
getDigestAlgorithmId()
313 return digestAlgorithmId
;
316 public byte[] getDigestAlgorithmParams()
318 return (digestAlgorithmParams
!= null
319 ?
(byte[]) digestAlgorithmParams
.clone()
323 public byte[] getAuthenticatedAttributes()
325 return (authenticatedAttributes
!= null
326 ?
(byte[]) authenticatedAttributes
.clone()
330 public OID
getDigestEncryptionAlgorithmId()
332 return digestEncryptionAlgorithmId
;
335 public byte[] getDigestEncryptionAlgorithmParams()
337 return (digestEncryptionAlgorithmParams
!= null
338 ?
(byte[]) digestEncryptionAlgorithmParams
.clone()
342 public byte[] getEncryptedDigest()
344 return (encryptedDigest
!= null ?
(byte[]) encryptedDigest
.clone() : null);
347 public byte[] getUnauthenticatedAttributes()
349 return (unauthenticatedAttributes
!= null
350 ?
(byte[]) unauthenticatedAttributes
.clone()
355 * Writes to the designated output stream the DER encoding of the current
356 * contents of this instance.
358 * @param out the destination output stream.
359 * @throws IOException if an I/O related exception occurs during the process.
361 public void encode(OutputStream out
) throws IOException
363 DERValue derVersion
= new DERValue(DER
.INTEGER
, version
);
365 ByteArrayOutputStream baos
= new ByteArrayOutputStream(4096);
366 baos
.write(issuer
.getEncoded());
367 DERValue derSerialNumber
= new DERValue(DER
.INTEGER
, serialNumber
);
368 DERWriter
.write(baos
, derSerialNumber
);
370 byte[] b
= baos
.toByteArray();
371 DERValue derIssuerAndSerialNumber
=
372 new DERValue(DER
.CONSTRUCTED
| DER
.SEQUENCE
, b
.length
, b
, null);
374 DERValue derDigestAlgorithmOID
= new DERValue(DER
.OBJECT_IDENTIFIER
,
376 ArrayList digestAlgorithmIdentifier
= new ArrayList(1);
377 digestAlgorithmIdentifier
.add(derDigestAlgorithmOID
);
378 DERValue derDigestAlgorithmIdentifier
=
379 new DERValue(DER
.CONSTRUCTED
| DER
.SEQUENCE
, digestAlgorithmIdentifier
);
381 DERValue derAuthenticatedAttributes
;
382 if (authenticatedAttributes
== null)
383 derAuthenticatedAttributes
= new DERValue(DER
.NULL
, null);
385 derAuthenticatedAttributes
= new DERValue(DER
.CONSTRUCTED
| DER
.SET
,
386 authenticatedAttributes
);
388 DERValue derDigestEncryptionAlgorithmOID
=
389 new DERValue(DER
.OBJECT_IDENTIFIER
, digestEncryptionAlgorithmId
);
390 ArrayList digestEncryptionAlgorithmIdentifier
= new ArrayList(1);
391 digestEncryptionAlgorithmIdentifier
.add(derDigestEncryptionAlgorithmOID
);
392 DERValue derDigestEncryptionAlgorithmIdentifier
=
393 new DERValue(DER
.CONSTRUCTED
| DER
.SEQUENCE
, digestEncryptionAlgorithmIdentifier
);
395 DERValue derEncryptedDigest
= new DERValue(DER
.OCTET_STRING
, encryptedDigest
);
397 DERValue derUnauthenticatedAttributes
;
398 if (unauthenticatedAttributes
== null)
399 derUnauthenticatedAttributes
= new DERValue(DER
.NULL
, null);
401 derUnauthenticatedAttributes
= new DERValue(DER
.CONSTRUCTED
| DER
.SET
,
402 unauthenticatedAttributes
);
404 ArrayList signerInfo
= new ArrayList(5);
405 signerInfo
.add(derVersion
);
406 signerInfo
.add(derIssuerAndSerialNumber
);
407 signerInfo
.add(derDigestAlgorithmIdentifier
);
408 signerInfo
.add(derDigestEncryptionAlgorithmIdentifier
);
409 signerInfo
.add(derEncryptedDigest
);
410 DERValue derSignerInfo
= new DERValue(DER
.CONSTRUCTED
| DER
.SEQUENCE
,
412 DERWriter
.write(out
, derSignerInfo
);