1 package org.bouncycastle.jcajce.provider.asymmetric.elgamal;
2 
3 import java.io.IOException;
4 import java.io.ObjectInputStream;
5 import java.io.ObjectOutputStream;
6 import java.math.BigInteger;
7 
8 import javax.crypto.interfaces.DHPublicKey;
9 import javax.crypto.spec.DHParameterSpec;
10 import javax.crypto.spec.DHPublicKeySpec;
11 
12 import org.bouncycastle.asn1.ASN1Encoding;
13 import org.bouncycastle.asn1.ASN1Integer;
14 import org.bouncycastle.asn1.oiw.ElGamalParameter;
15 import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
16 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
17 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
18 import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
19 import org.bouncycastle.jce.interfaces.ElGamalPublicKey;
20 import org.bouncycastle.jce.spec.ElGamalParameterSpec;
21 import org.bouncycastle.jce.spec.ElGamalPublicKeySpec;
22 
23 public class BCElGamalPublicKey
24     implements ElGamalPublicKey, DHPublicKey
25 {
26     static final long serialVersionUID = 8712728417091216948L;
27 
28     private BigInteger              y;
29     private transient ElGamalParameterSpec    elSpec;
30 
BCElGamalPublicKey( ElGamalPublicKeySpec spec)31     BCElGamalPublicKey(
32         ElGamalPublicKeySpec spec)
33     {
34         this.y = spec.getY();
35         this.elSpec = new ElGamalParameterSpec(spec.getParams().getP(), spec.getParams().getG());
36     }
37 
BCElGamalPublicKey( DHPublicKeySpec spec)38     BCElGamalPublicKey(
39         DHPublicKeySpec spec)
40     {
41         this.y = spec.getY();
42         this.elSpec = new ElGamalParameterSpec(spec.getP(), spec.getG());
43     }
44 
BCElGamalPublicKey( ElGamalPublicKey key)45     BCElGamalPublicKey(
46         ElGamalPublicKey key)
47     {
48         this.y = key.getY();
49         this.elSpec = key.getParameters();
50     }
51 
BCElGamalPublicKey( DHPublicKey key)52     BCElGamalPublicKey(
53         DHPublicKey key)
54     {
55         this.y = key.getY();
56         this.elSpec = new ElGamalParameterSpec(key.getParams().getP(), key.getParams().getG());
57     }
58 
BCElGamalPublicKey( ElGamalPublicKeyParameters params)59     BCElGamalPublicKey(
60         ElGamalPublicKeyParameters params)
61     {
62         this.y = params.getY();
63         this.elSpec = new ElGamalParameterSpec(params.getParameters().getP(), params.getParameters().getG());
64     }
65 
BCElGamalPublicKey( BigInteger y, ElGamalParameterSpec elSpec)66     BCElGamalPublicKey(
67         BigInteger y,
68         ElGamalParameterSpec elSpec)
69     {
70         this.y = y;
71         this.elSpec = elSpec;
72     }
73 
BCElGamalPublicKey( SubjectPublicKeyInfo info)74     BCElGamalPublicKey(
75         SubjectPublicKeyInfo info)
76     {
77         ElGamalParameter        params = ElGamalParameter.getInstance(info.getAlgorithm().getParameters());
78         ASN1Integer              derY = null;
79 
80         try
81         {
82             derY = (ASN1Integer)info.parsePublicKey();
83         }
84         catch (IOException e)
85         {
86             throw new IllegalArgumentException("invalid info structure in DSA public key");
87         }
88 
89         this.y = derY.getValue();
90         this.elSpec = new ElGamalParameterSpec(params.getP(), params.getG());
91     }
92 
getAlgorithm()93     public String getAlgorithm()
94     {
95         return "ElGamal";
96     }
97 
getFormat()98     public String getFormat()
99     {
100         return "X.509";
101     }
102 
getEncoded()103     public byte[] getEncoded()
104     {
105         try
106         {
107             SubjectPublicKeyInfo    info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new ASN1Integer(y));
108 
109             return info.getEncoded(ASN1Encoding.DER);
110         }
111         catch (IOException e)
112         {
113             return null;
114         }
115     }
116 
getParameters()117     public ElGamalParameterSpec getParameters()
118     {
119         return elSpec;
120     }
121 
getParams()122     public DHParameterSpec getParams()
123     {
124         return new DHParameterSpec(elSpec.getP(), elSpec.getG());
125     }
126 
getY()127     public BigInteger getY()
128     {
129         return y;
130     }
131 
hashCode()132     public int hashCode()
133     {
134         return this.getY().hashCode() ^ this.getParams().getG().hashCode()
135                 ^ this.getParams().getP().hashCode() ^ this.getParams().getL();
136     }
137 
equals( Object o)138     public boolean equals(
139         Object o)
140     {
141         if (!(o instanceof DHPublicKey))
142         {
143             return false;
144         }
145 
146         DHPublicKey other = (DHPublicKey)o;
147 
148         return this.getY().equals(other.getY())
149             && this.getParams().getG().equals(other.getParams().getG())
150             && this.getParams().getP().equals(other.getParams().getP())
151             && this.getParams().getL() == other.getParams().getL();
152     }
153 
readObject( ObjectInputStream in)154     private void readObject(
155         ObjectInputStream   in)
156         throws IOException, ClassNotFoundException
157     {
158         in.defaultReadObject();
159 
160         this.elSpec = new ElGamalParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject());
161     }
162 
writeObject( ObjectOutputStream out)163     private void writeObject(
164         ObjectOutputStream  out)
165         throws IOException
166     {
167         out.defaultWriteObject();
168 
169         out.writeObject(elSpec.getP());
170         out.writeObject(elSpec.getG());
171     }
172 }
173