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    
026    import javax.crypto.interfaces.DHPublicKey;
027    import javax.crypto.spec.DHParameterSpec;
028    import javax.crypto.spec.DHPublicKeySpec;
029    
030    import org.apache.geronimo.util.asn1.ASN1Sequence;
031    import org.apache.geronimo.util.asn1.DERInteger;
032    import org.apache.geronimo.util.asn1.DEROutputStream;
033    import org.apache.geronimo.util.asn1.pkcs.DHParameter;
034    import org.apache.geronimo.util.asn1.x509.AlgorithmIdentifier;
035    import org.apache.geronimo.util.asn1.x509.SubjectPublicKeyInfo;
036    import org.apache.geronimo.util.asn1.x9.X9ObjectIdentifiers;
037    import org.apache.geronimo.util.crypto.params.DHPublicKeyParameters;
038    
039    public class JCEDHPublicKey
040        implements DHPublicKey
041    {
042        private BigInteger              y;
043        private DHParameterSpec         dhSpec;
044    
045        JCEDHPublicKey(
046            DHPublicKeySpec    spec)
047        {
048            this.y = spec.getY();
049            this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG());
050        }
051    
052        JCEDHPublicKey(
053            DHPublicKey    key)
054        {
055            this.y = key.getY();
056            this.dhSpec = key.getParams();
057        }
058    
059        JCEDHPublicKey(
060            DHPublicKeyParameters  params)
061        {
062            this.y = params.getY();
063            this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), 0);
064        }
065    
066        JCEDHPublicKey(
067            BigInteger        y,
068            DHParameterSpec   dhSpec)
069        {
070            this.y = y;
071            this.dhSpec = dhSpec;
072        }
073    
074        JCEDHPublicKey(
075            SubjectPublicKeyInfo    info)
076        {
077            DHParameter             params = new DHParameter((ASN1Sequence)info.getAlgorithmId().getParameters());
078            DERInteger              derY = null;
079    
080            try
081            {
082                derY = (DERInteger)info.getPublicKey();
083            }
084            catch (IOException e)
085            {
086                throw new IllegalArgumentException("invalid info structure in DH public key", e);
087            }
088    
089            this.y = derY.getValue();
090            if (params.getL() != null)
091            {
092                this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue());
093            }
094            else
095            {
096                this.dhSpec = new DHParameterSpec(params.getP(), params.getG());
097            }
098        }
099    
100        public String getAlgorithm()
101        {
102            return "DH";
103        }
104    
105        public String getFormat()
106        {
107            return "X.509";
108        }
109    
110        public byte[] getEncoded()
111        {
112            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
113            DEROutputStream         dOut = new DEROutputStream(bOut);
114            SubjectPublicKeyInfo    info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.dhpublicnumber, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).getDERObject()), new DERInteger(y));
115    
116            try
117            {
118                dOut.writeObject(info);
119                dOut.close();
120            }
121            catch (IOException e)
122            {
123                throw new RuntimeException("Error encoding DH public key", e);
124            }
125    
126            return bOut.toByteArray();
127    
128        }
129    
130        public DHParameterSpec getParams()
131        {
132            return dhSpec;
133        }
134    
135        public BigInteger getY()
136        {
137            return y;
138        }
139    
140        private void readObject(
141            ObjectInputStream   in)
142            throws IOException, ClassNotFoundException
143        {
144            this.y = (BigInteger)in.readObject();
145            this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt());
146        }
147    
148        private void writeObject(
149            ObjectOutputStream  out)
150            throws IOException
151        {
152            out.writeObject(this.getY());
153            out.writeObject(dhSpec.getP());
154            out.writeObject(dhSpec.getG());
155            out.writeInt(dhSpec.getL());
156        }
157    }