• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.jce.provider;
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.ASN1Sequence;
13 import org.bouncycastle.asn1.DERInteger;
14 import org.bouncycastle.asn1.DERObjectIdentifier;
15 import org.bouncycastle.asn1.pkcs.DHParameter;
16 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
17 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
18 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
19 import org.bouncycastle.asn1.x9.DHDomainParameters;
20 import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
21 import org.bouncycastle.crypto.params.DHPublicKeyParameters;
22 
23 public class JCEDHPublicKey
24     implements DHPublicKey
25 {
26     static final long serialVersionUID = -216691575254424324L;
27 
28     private BigInteger              y;
29     private DHParameterSpec         dhSpec;
30     private SubjectPublicKeyInfo    info;
31 
JCEDHPublicKey( DHPublicKeySpec spec)32     JCEDHPublicKey(
33         DHPublicKeySpec    spec)
34     {
35         this.y = spec.getY();
36         this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG());
37     }
38 
JCEDHPublicKey( DHPublicKey key)39     JCEDHPublicKey(
40         DHPublicKey    key)
41     {
42         this.y = key.getY();
43         this.dhSpec = key.getParams();
44     }
45 
JCEDHPublicKey( DHPublicKeyParameters params)46     JCEDHPublicKey(
47         DHPublicKeyParameters  params)
48     {
49         this.y = params.getY();
50         this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL());
51     }
52 
JCEDHPublicKey( BigInteger y, DHParameterSpec dhSpec)53     JCEDHPublicKey(
54         BigInteger        y,
55         DHParameterSpec   dhSpec)
56     {
57         this.y = y;
58         this.dhSpec = dhSpec;
59     }
60 
JCEDHPublicKey( SubjectPublicKeyInfo info)61     JCEDHPublicKey(
62         SubjectPublicKeyInfo    info)
63     {
64         this.info = info;
65 
66         DERInteger              derY;
67         try
68         {
69             derY = (DERInteger)info.getPublicKey();
70         }
71         catch (IOException e)
72         {
73             throw new IllegalArgumentException("invalid info structure in DH public key");
74         }
75 
76         this.y = derY.getValue();
77 
78         ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters());
79         DERObjectIdentifier id = info.getAlgorithmId().getObjectId();
80 
81         // we need the PKCS check to handle older keys marked with the X9 oid.
82         if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement) || isPKCSParam(seq))
83         {
84             DHParameter             params = new DHParameter(seq);
85 
86             if (params.getL() != null)
87             {
88                 this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue());
89             }
90             else
91             {
92                 this.dhSpec = new DHParameterSpec(params.getP(), params.getG());
93             }
94         }
95         else if (id.equals(X9ObjectIdentifiers.dhpublicnumber))
96         {
97             DHDomainParameters params = DHDomainParameters.getInstance(seq);
98 
99             this.dhSpec = new DHParameterSpec(params.getP().getValue(), params.getG().getValue());
100         }
101         else
102         {
103             throw new IllegalArgumentException("unknown algorithm type: " + id);
104         }
105     }
106 
getAlgorithm()107     public String getAlgorithm()
108     {
109         return "DH";
110     }
111 
getFormat()112     public String getFormat()
113     {
114         return "X.509";
115     }
116 
getEncoded()117     public byte[] getEncoded()
118     {
119         if (info != null)
120         {
121             return info.getDEREncoded();
122         }
123 
124         SubjectPublicKeyInfo    info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).getDERObject()), new DERInteger(y));
125 
126         return info.getDEREncoded();
127     }
128 
getParams()129     public DHParameterSpec getParams()
130     {
131         return dhSpec;
132     }
133 
getY()134     public BigInteger getY()
135     {
136         return y;
137     }
138 
isPKCSParam(ASN1Sequence seq)139     private boolean isPKCSParam(ASN1Sequence seq)
140     {
141         if (seq.size() == 2)
142         {
143             return true;
144         }
145 
146         if (seq.size() > 3)
147         {
148             return false;
149         }
150 
151         DERInteger l = DERInteger.getInstance(seq.getObjectAt(2));
152         DERInteger p = DERInteger.getInstance(seq.getObjectAt(0));
153 
154         if (l.getValue().compareTo(BigInteger.valueOf(p.getValue().bitLength())) > 0)
155         {
156             return false;
157         }
158 
159         return true;
160     }
161 
readObject( ObjectInputStream in)162     private void readObject(
163         ObjectInputStream   in)
164         throws IOException, ClassNotFoundException
165     {
166         this.y = (BigInteger)in.readObject();
167         this.dhSpec = new DHParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), in.readInt());
168     }
169 
writeObject( ObjectOutputStream out)170     private void writeObject(
171         ObjectOutputStream  out)
172         throws IOException
173     {
174         out.writeObject(this.getY());
175         out.writeObject(dhSpec.getP());
176         out.writeObject(dhSpec.getG());
177         out.writeInt(dhSpec.getL());
178     }
179 }
180