History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/DHCrypt.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/DHCrypt.java+188−0
@@ -0,0 +1,188 @@
1+/*
2+ * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+
27+package sun.security.ssl;
28+
29+import java.math.BigInteger;
30+import java.security.*;
31+
32+import javax.crypto.SecretKey;
33+import javax.crypto.KeyAgreement;
34+import javax.crypto.interfaces.DHPublicKey;
35+import javax.crypto.spec.*;
36+
37+/**
38+ * This class implements the Diffie-Hellman key exchange algorithm.
39+ * D-H means combining your private key with your partners public key to
40+ * generate a number. The peer does the same with its private key and our
41+ * public key. Through the magic of Diffie-Hellman we both come up with the
42+ * same number. This number is secret (discounting MITM attacks) and hence
43+ * called the shared secret. It has the same length as the modulus, e.g. 512
44+ * or 1024 bit. Man-in-the-middle attacks are typically countered by an
45+ * independent authentication step using certificates (RSA, DSA, etc.).
46+ *
47+ * The thing to note is that the shared secret is constant for two partners
48+ * with constant private keys. This is often not what we want, which is why
49+ * it is generally a good idea to create a new private key for each session.
50+ * Generating a private key involves one modular exponentiation assuming
51+ * suitable D-H parameters are available.
52+ *
53+ * General usage of this class (TLS DHE case):
54+ * . if we are server, call DHCrypt(keyLength,random). This generates
55+ * an ephemeral keypair of the request length.
56+ * . if we are client, call DHCrypt(modulus, base, random). This
57+ * generates an ephemeral keypair using the parameters specified by the server.
58+ * . send parameters and public value to remote peer
59+ * . receive peers ephemeral public key
60+ * . call getAgreedSecret() to calculate the shared secret
61+ *
62+ * In TLS the server chooses the parameter values itself, the client must use
63+ * those sent to it by the server.
64+ *
65+ * The use of ephemeral keys as described above also achieves what is called
66+ * "forward secrecy". This means that even if the authentication keys are
67+ * broken at a later date, the shared secret remains secure. The session is
68+ * compromised only if the authentication keys are already broken at the
69+ * time the key exchange takes place and an active MITM attack is used.
70+ * This is in contrast to straightforward encrypting RSA key exchanges.
71+ *
72+ * @author David Brownell
73+ */
74+final class DHCrypt {
75+
76+ // group parameters (prime modulus and generator)
77+ private BigInteger modulus; // P (aka N)
78+ private BigInteger base; // G (aka alpha)
79+
80+ // our private key (including private component x)
81+ private PrivateKey privateKey;
82+
83+ // public component of our key, X = (g ^ x) mod p
84+ private BigInteger publicValue; // X (aka y)
85+
86+ /**
87+ * Generate a Diffie-Hellman keypair of the specified size.
88+ */
89+ DHCrypt(int keyLength, SecureRandom random) {
90+ try {
91+ KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
92+ kpg.initialize(keyLength, random);
93+ KeyPair kp = kpg.generateKeyPair();
94+ privateKey = kp.getPrivate();
95+ DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
96+ publicValue = spec.getY();
97+ modulus = spec.getP();
98+ base = spec.getG();
99+ } catch (GeneralSecurityException e) {
100+ throw new RuntimeException("Could not generate DH keypair", e);
101+ }
102+ }
103+
104+
105+ /**
106+ * Generate a Diffie-Hellman keypair using the specified parameters.
107+ *
108+ * @param modulus the Diffie-Hellman modulus P
109+ * @param base the Diffie-Hellman base G
110+ */
111+ DHCrypt(BigInteger modulus, BigInteger base, SecureRandom random) {
112+ this.modulus = modulus;
113+ this.base = base;
114+ try {
115+ KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
116+ DHParameterSpec params = new DHParameterSpec(modulus, base);
117+ kpg.initialize(params, random);
118+ KeyPair kp = kpg.generateKeyPair();
119+ privateKey = kp.getPrivate();
120+ DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
121+ publicValue = spec.getY();
122+ } catch (GeneralSecurityException e) {
123+ throw new RuntimeException("Could not generate DH keypair", e);
124+ }
125+ }
126+
127+ static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) {
128+ if (key instanceof DHPublicKey) {
129+ DHPublicKey dhKey = (DHPublicKey)key;
130+ DHParameterSpec params = dhKey.getParams();
131+ return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG());
132+ }
133+ try {
134+ KeyFactory factory = JsseJce.getKeyFactory("DH");
135+ return factory.getKeySpec(key, DHPublicKeySpec.class);
136+ } catch (Exception e) {
137+ throw new RuntimeException(e);
138+ }
139+ }
140+
141+
142+ /** Returns the Diffie-Hellman modulus. */
143+ BigInteger getModulus() {
144+ return modulus;
145+ }
146+
147+ /** Returns the Diffie-Hellman base (generator). */
148+ BigInteger getBase() {
149+ return base;
150+ }
151+
152+ /**
153+ * Gets the public key of this end of the key exchange.
154+ */
155+ BigInteger getPublicKey() {
156+ return publicValue;
157+ }
158+
159+ /**
160+ * Get the secret data that has been agreed on through Diffie-Hellman
161+ * key agreement protocol. Note that in the two party protocol, if
162+ * the peer keys are already known, no other data needs to be sent in
163+ * order to agree on a secret. That is, a secured message may be
164+ * sent without any mandatory round-trip overheads.
165+ *
166+ * <P>It is illegal to call this member function if the private key
167+ * has not been set (or generated).
168+ *
169+ * @param peerPublicKey the peer's public key.
170+ * @returns the secret, which is an unsigned big-endian integer
171+ * the same size as the Diffie-Hellman modulus.
172+ */
173+ SecretKey getAgreedSecret(BigInteger peerPublicValue) {
174+ try {
175+ KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
176+ DHPublicKeySpec spec =
177+ new DHPublicKeySpec(peerPublicValue, modulus, base);
178+ PublicKey publicKey = kf.generatePublic(spec);
179+ KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
180+ ka.init(privateKey);
181+ ka.doPhase(publicKey, true);
182+ return ka.generateSecret("TlsPremasterSecret");
183+ } catch (GeneralSecurityException e) {
184+ throw new RuntimeException("Could not generate secret", e);
185+ }
186+ }
187+
188+}