0
|
1 /**
|
|
2 *
|
|
3 */
|
|
4 package com.trilead.ssh2.crypto.dh;
|
|
5
|
|
6 import java.io.IOException;
|
|
7 import java.math.BigInteger;
|
|
8 import java.security.InvalidAlgorithmParameterException;
|
|
9 import java.security.InvalidKeyException;
|
|
10 import java.security.KeyFactory;
|
|
11 import java.security.KeyPair;
|
|
12 import java.security.KeyPairGenerator;
|
|
13 import java.security.NoSuchAlgorithmException;
|
|
14 import java.security.interfaces.ECPrivateKey;
|
|
15 import java.security.interfaces.ECPublicKey;
|
|
16 import java.security.spec.ECParameterSpec;
|
|
17 import java.security.spec.ECPoint;
|
|
18 import java.security.spec.ECPublicKeySpec;
|
|
19 import java.security.spec.InvalidKeySpecException;
|
|
20
|
|
21 import javax.crypto.KeyAgreement;
|
|
22
|
|
23 import com.trilead.ssh2.signature.ECDSASHA2Verify;
|
|
24
|
|
25 /**
|
|
26 * @author kenny
|
|
27 *
|
|
28 */
|
|
29 public class EcDhExchange extends GenericDhExchange {
|
|
30 private ECPrivateKey clientPrivate;
|
|
31 private ECPublicKey clientPublic;
|
|
32 private ECPublicKey serverPublic;
|
|
33
|
|
34 @Override
|
|
35 public void init(String name) throws IOException {
|
|
36 final ECParameterSpec spec;
|
|
37
|
|
38 if ("ecdh-sha2-nistp256".equals(name)) {
|
|
39 spec = ECDSASHA2Verify.EllipticCurves.nistp256;
|
|
40 }
|
|
41 else if ("ecdh-sha2-nistp384".equals(name)) {
|
|
42 spec = ECDSASHA2Verify.EllipticCurves.nistp384;
|
|
43 }
|
|
44 else if ("ecdh-sha2-nistp521".equals(name)) {
|
|
45 spec = ECDSASHA2Verify.EllipticCurves.nistp521;
|
|
46 }
|
|
47 else {
|
|
48 throw new IllegalArgumentException("Unknown EC curve " + name);
|
|
49 }
|
|
50
|
|
51 KeyPairGenerator kpg;
|
|
52
|
|
53 try {
|
|
54 kpg = KeyPairGenerator.getInstance("EC");
|
|
55 kpg.initialize(spec);
|
|
56 KeyPair pair = kpg.generateKeyPair();
|
|
57 clientPrivate = (ECPrivateKey) pair.getPrivate();
|
|
58 clientPublic = (ECPublicKey) pair.getPublic();
|
|
59 }
|
|
60 catch (NoSuchAlgorithmException e) {
|
|
61 throw(IOException) new IOException("No DH keypair generator").initCause(e);
|
|
62 }
|
|
63 catch (InvalidAlgorithmParameterException e) {
|
|
64 throw(IOException) new IOException("Invalid DH parameters").initCause(e);
|
|
65 }
|
|
66 }
|
|
67
|
|
68 @Override
|
|
69 public byte[] getE() {
|
|
70 return ECDSASHA2Verify.encodeECPoint(clientPublic.getW(), clientPublic.getParams()
|
|
71 .getCurve());
|
|
72 }
|
|
73
|
|
74 @Override
|
|
75 protected byte[] getServerE() {
|
|
76 return ECDSASHA2Verify.encodeECPoint(serverPublic.getW(), serverPublic.getParams()
|
|
77 .getCurve());
|
|
78 }
|
|
79
|
|
80 @Override
|
|
81 public void setF(byte[] f) throws IOException {
|
|
82 if (clientPublic == null)
|
|
83 throw new IllegalStateException("DhDsaExchange not initialized!");
|
|
84
|
|
85 final KeyAgreement ka;
|
|
86
|
|
87 try {
|
|
88 KeyFactory kf = KeyFactory.getInstance("EC");
|
|
89 ECParameterSpec params = clientPublic.getParams();
|
|
90 ECPoint serverPoint = ECDSASHA2Verify.decodeECPoint(f, params.getCurve());
|
|
91 this.serverPublic = (ECPublicKey) kf.generatePublic(new ECPublicKeySpec(serverPoint,
|
|
92 params));
|
|
93 ka = KeyAgreement.getInstance("ECDH");
|
|
94 ka.init(clientPrivate);
|
|
95 ka.doPhase(serverPublic, true);
|
|
96 }
|
|
97 catch (NoSuchAlgorithmException e) {
|
|
98 throw(IOException) new IOException("No ECDH key agreement method").initCause(e);
|
|
99 }
|
|
100 catch (InvalidKeyException e) {
|
|
101 throw(IOException) new IOException("Invalid ECDH key").initCause(e);
|
|
102 }
|
|
103 catch (InvalidKeySpecException e) {
|
|
104 throw(IOException) new IOException("Invalid ECDH key").initCause(e);
|
|
105 }
|
|
106
|
|
107 sharedSecret = new BigInteger(ka.generateSecret());
|
|
108 }
|
|
109
|
|
110 @Override
|
|
111 public String getHashAlgo() {
|
|
112 return ECDSASHA2Verify.getDigestAlgorithmForParams(clientPublic.getParams());
|
|
113 }
|
|
114 }
|