001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.crypto.asn1.pkcs;
019    
020    import java.io.ByteArrayInputStream;
021    import java.io.IOException;
022    import java.math.BigInteger;
023    import java.util.Enumeration;
024    
025    import org.apache.geronimo.crypto.asn1.ASN1Encodable;
026    import org.apache.geronimo.crypto.asn1.ASN1EncodableVector;
027    import org.apache.geronimo.crypto.asn1.ASN1InputStream;
028    import org.apache.geronimo.crypto.asn1.ASN1OctetString;
029    import org.apache.geronimo.crypto.asn1.ASN1Sequence;
030    import org.apache.geronimo.crypto.asn1.ASN1Set;
031    import org.apache.geronimo.crypto.asn1.ASN1TaggedObject;
032    import org.apache.geronimo.crypto.asn1.DERInteger;
033    import org.apache.geronimo.crypto.asn1.DERObject;
034    import org.apache.geronimo.crypto.asn1.DEROctetString;
035    import org.apache.geronimo.crypto.asn1.DERSequence;
036    import org.apache.geronimo.crypto.asn1.DERTaggedObject;
037    import org.apache.geronimo.crypto.asn1.x509.AlgorithmIdentifier;
038    
039    public class PrivateKeyInfo
040        extends ASN1Encodable
041    {
042        private DERObject               privKey;
043        private AlgorithmIdentifier     algId;
044        private ASN1Set                 attributes;
045    
046        public static PrivateKeyInfo getInstance(
047            ASN1TaggedObject obj,
048            boolean          explicit)
049        {
050            return getInstance(ASN1Sequence.getInstance(obj, explicit));
051        }
052    
053        public static PrivateKeyInfo getInstance(
054            Object  obj)
055        {
056            if (obj instanceof PrivateKeyInfo)
057            {
058                return (PrivateKeyInfo)obj;
059            }
060            else if (obj instanceof ASN1Sequence)
061            {
062                return new PrivateKeyInfo((ASN1Sequence)obj);
063            }
064    
065            throw new IllegalArgumentException("unknown object in factory");
066        }
067    
068        public PrivateKeyInfo(
069            AlgorithmIdentifier algId,
070            DERObject           privateKey)
071        {
072            this.privKey = privateKey;
073            this.algId = algId;
074        }
075    
076        public PrivateKeyInfo(
077            ASN1Sequence  seq)
078        {
079            Enumeration e = seq.getObjects();
080    
081            BigInteger  version = ((DERInteger)e.nextElement()).getValue();
082            if (version.intValue() != 0)
083            {
084                throw new IllegalArgumentException("wrong version for private key info");
085            }
086    
087            algId = new AlgorithmIdentifier((ASN1Sequence)e.nextElement());
088    
089            try
090            {
091                ByteArrayInputStream    bIn = new ByteArrayInputStream(((ASN1OctetString)e.nextElement()).getOctets());
092                ASN1InputStream         aIn = new ASN1InputStream(bIn);
093    
094                privKey = aIn.readObject();
095            }
096            catch (IOException ex)
097            {
098                throw new IllegalArgumentException("Error recoverying private key from sequence", ex);
099            }
100    
101            if (e.hasMoreElements())
102            {
103               attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
104            }
105        }
106    
107        public AlgorithmIdentifier getAlgorithmId()
108        {
109            return algId;
110        }
111    
112        public DERObject getPrivateKey()
113        {
114            return privKey;
115        }
116    
117        public ASN1Set getAttributes()
118        {
119            return attributes;
120        }
121    
122        /**
123         * write out an RSA private key with it's asscociated information
124         * as described in PKCS8.
125         * <pre>
126         *      PrivateKeyInfo ::= SEQUENCE {
127         *                              version Version,
128         *                              privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
129         *                              privateKey PrivateKey,
130         *                              attributes [0] IMPLICIT Attributes OPTIONAL
131         *                          }
132         *      Version ::= INTEGER {v1(0)} (v1,...)
133         *
134         *      PrivateKey ::= OCTET STRING
135         *
136         *      Attributes ::= SET OF Attribute
137         * </pre>
138         */
139        public DERObject toASN1Object()
140        {
141            ASN1EncodableVector v = new ASN1EncodableVector();
142    
143            v.add(new DERInteger(0));
144            v.add(algId);
145            v.add(new DEROctetString(privKey));
146    
147            if (attributes != null)
148            {
149                v.add(new DERTaggedObject(false, 0, attributes));
150            }
151    
152            return new DERSequence(v);
153        }
154    }