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