001: package org.bouncycastle.cms;
002:
003: import org.bouncycastle.asn1.ASN1Null;
004: import org.bouncycastle.asn1.ASN1Object;
005: import org.bouncycastle.asn1.ASN1OutputStream;
006: import org.bouncycastle.asn1.DEREncodable;
007: import org.bouncycastle.asn1.DERNull;
008: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
009:
010: import javax.crypto.Cipher;
011: import javax.crypto.CipherInputStream;
012: import javax.crypto.NoSuchPaddingException;
013: import javax.crypto.spec.IvParameterSpec;
014: import java.io.ByteArrayInputStream;
015: import java.io.ByteArrayOutputStream;
016: import java.io.IOException;
017: import java.io.InputStream;
018: import java.security.AlgorithmParameters;
019: import java.security.InvalidAlgorithmParameterException;
020: import java.security.InvalidKeyException;
021: import java.security.Key;
022: import java.security.NoSuchAlgorithmException;
023: import java.security.NoSuchProviderException;
024:
025: public abstract class RecipientInformation {
026: private static final ASN1Null asn1Null = new DERNull();
027:
028: protected RecipientId _rid = new RecipientId();
029: protected AlgorithmIdentifier _encAlg;
030: protected AlgorithmIdentifier _keyEncAlg;
031: protected InputStream _data;
032:
033: protected RecipientInformation(AlgorithmIdentifier encAlg,
034: AlgorithmIdentifier keyEncAlg, InputStream data) {
035: this ._encAlg = encAlg;
036: this ._keyEncAlg = keyEncAlg;
037: this ._data = data;
038: }
039:
040: public RecipientId getRID() {
041: return _rid;
042: }
043:
044: private byte[] encodeObj(DEREncodable obj) throws IOException {
045: if (obj != null) {
046: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
047: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
048:
049: aOut.writeObject(obj);
050:
051: return bOut.toByteArray();
052: }
053:
054: return null;
055: }
056:
057: /**
058: * return the object identifier for the key encryption algorithm.
059: * @return OID for key encryption algorithm.
060: */
061: public String getKeyEncryptionAlgOID() {
062: return _keyEncAlg.getObjectId().getId();
063: }
064:
065: /**
066: * return the ASN.1 encoded key encryption algorithm parameters, or null if
067: * there aren't any.
068: * @return ASN.1 encoding of key encryption algorithm parameters.
069: */
070: public byte[] getKeyEncryptionAlgParams() {
071: try {
072: return encodeObj(_keyEncAlg.getParameters());
073: } catch (Exception e) {
074: throw new RuntimeException(
075: "exception getting encryption parameters " + e);
076: }
077: }
078:
079: /**
080: * Return an AlgorithmParameters object giving the encryption parameters
081: * used to encrypt the key this recipient holds.
082: *
083: * @param provider the provider to generate the parameters for.
084: * @return the parameters object, null if there is not one.
085: * @throws CMSException if the algorithm cannot be found, or the parameters can't be parsed.
086: * @throws NoSuchProviderException if the provider cannot be found.
087: */
088: public AlgorithmParameters getKeyEncryptionAlgorithmParameters(
089: String provider) throws CMSException,
090: NoSuchProviderException {
091: try {
092: byte[] enc = this .encodeObj(_keyEncAlg.getParameters());
093: if (enc == null) {
094: return null;
095: }
096:
097: AlgorithmParameters params = CMSEnvelopedHelper.INSTANCE
098: .createAlgorithmParameters(
099: getKeyEncryptionAlgOID(), provider);
100:
101: params.init(enc, "ASN.1");
102:
103: return params;
104: } catch (NoSuchAlgorithmException e) {
105: throw new CMSException(
106: "can't find parameters for algorithm", e);
107: } catch (IOException e) {
108: throw new CMSException("can't find parse parameters", e);
109: }
110: }
111:
112: protected CMSTypedStream getContentFromSessionKey(Key sKey,
113: String provider) throws CMSException,
114: NoSuchProviderException {
115: String encAlg = _encAlg.getObjectId().getId();
116:
117: try {
118: Cipher cipher;
119:
120: cipher = CMSEnvelopedHelper.INSTANCE.getSymmetricCipher(
121: encAlg, provider);
122:
123: ASN1Object sParams = (ASN1Object) _encAlg.getParameters();
124:
125: if (sParams != null && !asn1Null.equals(sParams)) {
126: AlgorithmParameters params = CMSEnvelopedHelper.INSTANCE
127: .createAlgorithmParameters(encAlg, cipher
128: .getProvider().getName());
129:
130: params.init(sParams.getEncoded(), "ASN.1");
131:
132: cipher.init(Cipher.DECRYPT_MODE, sKey, params);
133: } else {
134: if (encAlg
135: .equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC)
136: || encAlg
137: .equals(CMSEnvelopedDataGenerator.IDEA_CBC)
138: || encAlg
139: .equals(CMSEnvelopedDataGenerator.CAST5_CBC)) {
140: cipher.init(Cipher.DECRYPT_MODE, sKey,
141: new IvParameterSpec(new byte[8]));
142: } else {
143: cipher.init(Cipher.DECRYPT_MODE, sKey);
144: }
145: }
146:
147: return new CMSTypedStream(new CipherInputStream(_data,
148: cipher));
149: } catch (NoSuchAlgorithmException e) {
150: throw new CMSException("can't find algorithm.", e);
151: } catch (InvalidKeyException e) {
152: throw new CMSException("key invalid in message.", e);
153: } catch (NoSuchPaddingException e) {
154: throw new CMSException("required padding not supported.", e);
155: } catch (InvalidAlgorithmParameterException e) {
156: throw new CMSException("algorithm parameters invalid.", e);
157: } catch (IOException e) {
158: throw new CMSException(
159: "error decoding algorithm parameters.", e);
160: }
161: }
162:
163: public byte[] getContent(Key key, String provider)
164: throws CMSException, NoSuchProviderException {
165: try {
166: if (_data instanceof ByteArrayInputStream) {
167: _data.reset();
168: }
169:
170: return CMSUtils.streamToByteArray(getContentStream(key,
171: provider).getContentStream());
172: } catch (IOException e) {
173: throw new RuntimeException(
174: "unable to parse internal stream: " + e);
175: }
176: }
177:
178: abstract public CMSTypedStream getContentStream(Key key,
179: String provider) throws CMSException,
180: NoSuchProviderException;
181: }
|