001: package org.bouncycastle.cms;
002:
003: import org.bouncycastle.asn1.ASN1Object;
004: import org.bouncycastle.asn1.ASN1OctetString;
005: import org.bouncycastle.asn1.ASN1OutputStream;
006: import org.bouncycastle.asn1.ASN1Sequence;
007: import org.bouncycastle.asn1.DERObjectIdentifier;
008: import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
009: import org.bouncycastle.asn1.cms.KeyAgreeRecipientInfo;
010: import org.bouncycastle.asn1.cms.OriginatorPublicKey;
011: import org.bouncycastle.asn1.cms.RecipientEncryptedKey;
012: import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
013: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
014: import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
015:
016: import javax.crypto.Cipher;
017: import javax.crypto.KeyAgreement;
018: import javax.crypto.NoSuchPaddingException;
019: import java.io.ByteArrayOutputStream;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.security.InvalidKeyException;
023: import java.security.Key;
024: import java.security.KeyFactory;
025: import java.security.NoSuchAlgorithmException;
026: import java.security.NoSuchProviderException;
027: import java.security.spec.InvalidKeySpecException;
028: import java.security.spec.X509EncodedKeySpec;
029:
030: /**
031: * the RecipientInfo class for a recipient who has been sent a message
032: * encrypted using key agreement.
033: */
034: public class KeyAgreeRecipientInformation extends RecipientInformation {
035: private KeyAgreeRecipientInfo _info;
036: private AlgorithmIdentifier _encAlg;
037: private ASN1OctetString _encryptedKey;
038:
039: public KeyAgreeRecipientInformation(KeyAgreeRecipientInfo info,
040: AlgorithmIdentifier encAlg, InputStream data) {
041: super (encAlg, AlgorithmIdentifier.getInstance(info
042: .getKeyEncryptionAlgorithm()), data);
043:
044: _info = info;
045: _encAlg = encAlg;
046:
047: try {
048: ASN1Sequence s = _info.getRecipientEncryptedKeys();
049: RecipientEncryptedKey id = RecipientEncryptedKey
050: .getInstance(s.getObjectAt(0));
051:
052: IssuerAndSerialNumber iAnds = id.getIdentifier()
053: .getIssuerAndSerialNumber();
054:
055: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
056: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
057:
058: aOut.writeObject(iAnds.getName());
059:
060: _rid = new RecipientId();
061:
062: _rid.setIssuer(bOut.toByteArray());
063: _rid.setSerialNumber(iAnds.getSerialNumber().getValue());
064:
065: _encryptedKey = id.getEncryptedKey();
066: } catch (IOException e) {
067: throw new IllegalArgumentException(
068: "invalid rid in KeyAgreeRecipientInformation");
069: }
070: }
071:
072: /**
073: * decrypt the content and return an input stream.
074: */
075: public CMSTypedStream getContentStream(Key key, String prov)
076: throws CMSException, NoSuchProviderException {
077: try {
078: OriginatorPublicKey origK = _info.getOriginator()
079: .getOriginatorKey();
080: PrivateKeyInfo privInfo = PrivateKeyInfo
081: .getInstance(ASN1Object.fromByteArray(key
082: .getEncoded()));
083: SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(
084: privInfo.getAlgorithmId(), origK.getPublicKey()
085: .getBytes());
086: X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubInfo
087: .getEncoded());
088: KeyFactory fact = KeyFactory.getInstance(_keyEncAlg
089: .getObjectId().getId(), prov);
090: KeyAgreement agreement = KeyAgreement.getInstance(
091: _keyEncAlg.getObjectId().getId(), prov);
092:
093: agreement.init(key);
094:
095: agreement.doPhase(fact.generatePublic(pubSpec), true);
096:
097: String wrapAlg = DERObjectIdentifier.getInstance(
098: ASN1Sequence
099: .getInstance(_keyEncAlg.getParameters())
100: .getObjectAt(0)).getId();
101:
102: Key wKey = agreement.generateSecret(wrapAlg);
103:
104: Cipher keyCipher = Cipher.getInstance(wrapAlg, prov);
105:
106: keyCipher.init(Cipher.UNWRAP_MODE, wKey);
107:
108: AlgorithmIdentifier aid = _encAlg;
109: String alg = aid.getObjectId().getId();
110:
111: byte[] encryptedKey = _encryptedKey.getOctets();
112: Key sKey = keyCipher.unwrap(encryptedKey, alg,
113: Cipher.SECRET_KEY);
114:
115: return getContentFromSessionKey(sKey, prov);
116: } catch (NoSuchAlgorithmException e) {
117: throw new CMSException("can't find algorithm.", e);
118: } catch (InvalidKeyException e) {
119: throw new CMSException("key invalid in message.", e);
120: } catch (InvalidKeySpecException e) {
121: throw new CMSException("originator key spec invalid.", e);
122: } catch (NoSuchPaddingException e) {
123: throw new CMSException("required padding not supported.", e);
124: } catch (Exception e) {
125: throw new CMSException("originator key invalid.", e);
126: }
127: }
128: }
|