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.util.jce.provider;
019    
020    import java.io.ByteArrayOutputStream;
021    import java.io.IOException;
022    import java.io.ObjectInputStream;
023    import java.io.ObjectOutputStream;
024    import java.math.BigInteger;
025    import java.util.Enumeration;
026    import java.util.Hashtable;
027    import java.util.Vector;
028    
029    import javax.crypto.interfaces.DHPrivateKey;
030    import javax.crypto.spec.DHParameterSpec;
031    import javax.crypto.spec.DHPrivateKeySpec;
032    
033    import org.apache.geronimo.util.asn1.ASN1Sequence;
034    import org.apache.geronimo.util.asn1.DEREncodable;
035    import org.apache.geronimo.util.asn1.DERInteger;
036    import org.apache.geronimo.util.asn1.DERObjectIdentifier;
037    import org.apache.geronimo.util.asn1.DEROutputStream;
038    import org.apache.geronimo.util.asn1.pkcs.DHParameter;
039    import org.apache.geronimo.util.asn1.pkcs.PKCSObjectIdentifiers;
040    import org.apache.geronimo.util.asn1.pkcs.PrivateKeyInfo;
041    import org.apache.geronimo.util.asn1.x509.AlgorithmIdentifier;
042    import org.apache.geronimo.util.crypto.params.DHPrivateKeyParameters;
043    import org.apache.geronimo.util.jce.interfaces.PKCS12BagAttributeCarrier;
044    
045    public class JCEDHPrivateKey
046        implements DHPrivateKey, PKCS12BagAttributeCarrier
047    {
048        BigInteger      x;
049    
050        DHParameterSpec dhSpec;
051    
052        private Hashtable   pkcs12Attributes = new Hashtable();
053        private Vector      pkcs12Ordering = new Vector();
054    
055        protected JCEDHPrivateKey()
056        {
057        }
058    
059        JCEDHPrivateKey(
060            DHPrivateKey    key)
061        {
062            this.x = key.getX();
063            this.dhSpec = key.getParams();
064        }
065    
066        JCEDHPrivateKey(
067            DHPrivateKeySpec    spec)
068        {
069            this.x = spec.getX();
070            this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG());
071        }
072    
073        JCEDHPrivateKey(
074            PrivateKeyInfo  info)
075        {
076            DHParameter     params = new DHParameter((ASN1Sequence)info.getAlgorithmId().getParameters());
077            DERInteger      derX = (DERInteger)info.getPrivateKey();
078    
079            this.x = derX.getValue();
080            if (params.getL() != null)
081            {
082                this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue());
083            }
084            else
085            {
086                this.dhSpec = new DHParameterSpec(params.getP(), params.getG());
087            }
088        }
089    
090        JCEDHPrivateKey(
091            DHPrivateKeyParameters  params)
092        {
093            this.x = params.getX();
094            this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG());
095        }
096    
097        public String getAlgorithm()
098        {
099            return "DH";
100        }
101    
102        /**
103         * return the encoding format we produce in getEncoded().
104         *
105         * @return the string "PKCS#8"
106         */
107        public String getFormat()
108        {
109            return "PKCS#8";
110        }
111    
112        /**
113         * Return a PKCS8 representation of the key. The sequence returned
114         * represents a full PrivateKeyInfo object.
115         *
116         * @return a PKCS8 representation of the key.
117         */
118        public byte[] getEncoded()
119        {
120            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
121            DEROutputStream         dOut = new DEROutputStream(bOut);
122            PrivateKeyInfo          info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).getDERObject()), new DERInteger(getX()));
123    
124            try
125            {
126                dOut.writeObject(info);
127                dOut.close();
128            }
129            catch (IOException e)
130            {
131                throw new RuntimeException("Error encoding DH private key", e);
132            }
133    
134            return bOut.toByteArray();
135        }
136    
137        public DHParameterSpec getParams()
138        {
139            return dhSpec;
140        }
141    
142        public BigInteger getX()
143        {
144            return x;
145        }
146    
147        private void readObject(
148            ObjectInputStream   in)
149            throws IOException, ClassNotFoundException
150        {
151            x = (BigInteger)in.readObject();
152    
153            this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt());
154        }
155    
156        private void writeObject(
157            ObjectOutputStream  out)
158            throws IOException
159        {
160            out.writeObject(this.getX());
161            out.writeObject(dhSpec.getP());
162            out.writeObject(dhSpec.getG());
163            out.writeInt(dhSpec.getL());
164        }
165    
166        public void setBagAttribute(
167            DERObjectIdentifier oid,
168            DEREncodable        attribute)
169        {
170            pkcs12Attributes.put(oid, attribute);
171            pkcs12Ordering.addElement(oid);
172        }
173    
174        public DEREncodable getBagAttribute(
175            DERObjectIdentifier oid)
176        {
177            return (DEREncodable)pkcs12Attributes.get(oid);
178        }
179    
180        public Enumeration getBagAttributeKeys()
181        {
182            return pkcs12Ordering.elements();
183        }
184    }