001package org.apache.commons.ssl.org.bouncycastle.asn1.cms;
002
003import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
004import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
010import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
012import org.apache.commons.ssl.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
013
014/**
015 * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.7">RFC 5652</a>:
016 * Content encryption key delivery mechanisms.
017 * <pre>
018 * PasswordRecipientInfo ::= SEQUENCE {
019 *     version       CMSVersion,   -- Always set to 0
020 *     keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
021 *                             OPTIONAL,
022 *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
023 *     encryptedKey  EncryptedKey }
024 * </pre>
025 */
026public class PasswordRecipientInfo
027    extends ASN1Object
028{
029    private ASN1Integer          version;
030    private AlgorithmIdentifier keyDerivationAlgorithm;
031    private AlgorithmIdentifier keyEncryptionAlgorithm;
032    private ASN1OctetString     encryptedKey;
033
034    public PasswordRecipientInfo(
035        AlgorithmIdentifier     keyEncryptionAlgorithm,
036        ASN1OctetString         encryptedKey)
037    {
038        this.version = new ASN1Integer(0);
039        this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
040        this.encryptedKey = encryptedKey;
041    }
042    
043    public PasswordRecipientInfo(
044        AlgorithmIdentifier     keyDerivationAlgorithm,
045        AlgorithmIdentifier     keyEncryptionAlgorithm,
046        ASN1OctetString         encryptedKey)
047    {
048        this.version = new ASN1Integer(0);
049        this.keyDerivationAlgorithm = keyDerivationAlgorithm;
050        this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
051        this.encryptedKey = encryptedKey;
052    }
053
054    /**
055     * @deprecated use getInstance() method.
056     */
057    public PasswordRecipientInfo(
058        ASN1Sequence seq)
059    {
060        version = (ASN1Integer)seq.getObjectAt(0);
061        if (seq.getObjectAt(1) instanceof ASN1TaggedObject)
062        {
063            keyDerivationAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
064            keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
065            encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
066        }
067        else
068        {
069            keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
070            encryptedKey = (ASN1OctetString)seq.getObjectAt(2);
071        }
072    }
073
074    /**
075     * Return a PasswordRecipientInfo object from a tagged object.
076     *
077     * @param obj the tagged object holding the object we want.
078     * @param explicit true if the object is meant to be explicitly
079     *              tagged false otherwise.
080     * @exception IllegalArgumentException if the object held by the
081     *          tagged object cannot be converted.
082     */
083    public static PasswordRecipientInfo getInstance(
084        ASN1TaggedObject    obj,
085        boolean             explicit)
086    {
087        return getInstance(ASN1Sequence.getInstance(obj, explicit));
088    }
089    
090    /**
091     * Return a PasswordRecipientInfo object from the given object.
092     * <p>
093     * Accepted inputs:
094     * <ul>
095     * <li> null &rarr; null
096     * <li> {@link PasswordRecipientInfo} object
097     * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with PasswordRecipientInfo structure inside
098     * </ul>
099     *
100     * @param obj the object we want converted.
101     * @exception IllegalArgumentException if the object cannot be converted.
102     */
103    public static PasswordRecipientInfo getInstance(
104        Object obj)
105    {
106        if (obj instanceof PasswordRecipientInfo)
107        {
108            return (PasswordRecipientInfo)obj;
109        }
110        
111        if (obj != null)
112        {
113            return new PasswordRecipientInfo(ASN1Sequence.getInstance(obj));
114        }
115        
116        return null;
117    }
118
119    public ASN1Integer getVersion()
120    {
121        return version;
122    }
123
124    public AlgorithmIdentifier getKeyDerivationAlgorithm()
125    {
126        return keyDerivationAlgorithm;
127    }
128
129    public AlgorithmIdentifier getKeyEncryptionAlgorithm()
130    {
131        return keyEncryptionAlgorithm;
132    }
133
134    public ASN1OctetString getEncryptedKey()
135    {
136        return encryptedKey;
137    }
138
139    /** 
140     * Produce an object suitable for an ASN1OutputStream.
141     */
142    public ASN1Primitive toASN1Primitive()
143    {
144        ASN1EncodableVector  v = new ASN1EncodableVector();
145
146        v.add(version);
147        
148        if (keyDerivationAlgorithm != null)
149        {
150            v.add(new DERTaggedObject(false, 0, keyDerivationAlgorithm));
151        }
152        v.add(keyEncryptionAlgorithm);
153        v.add(encryptedKey);
154
155        return new DERSequence(v);
156    }
157}