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