Hola gente,
aquí se escribió una clase para el Diffie-Hellman. El código de demostración más abajo, aquí el código fuente:
import java.math.BigInteger;
import java.security.SecureRandom;
/**
* Utilizes a Diffie-Hellman Key-Exchange<br>
* <br>
* <pre>
* Partner A Partner B
* g, p, a (randomly) b (randomly)
* A = g^a mod p
* g, p, A ==>
* B = g^b mod p
* <== B
* K = B^a mod p K = A^b mod p
* </pre>
* <br>
* Example Usage:<br>
* Partner A:<br>
* <code>
* DiffieHellman dh = new DiffieHellman(DiffieHellman.PARTNER_A);<br>
* dh.init(512);<br>
* sendToOtherSide(dh.getG());<br>
* sendToOtherSide(dh.getP());<br>
* sendToOtherSide(dh.getA());<br>
* byte[] key = dh.getKey(receiveFromOtherSide());<br>
* </code><br>
* <br>
* Partner B:<br>
* <code>
* DiffieHellman dh = new DiffieHellman(DiffieHellman.PARTNER_B);<br>
* dh.init(512);<br>
* BigInteger g = receiveFromOtherSide();<br>
* BigInteger p = receiveFromOtherSide();<br>
* BigInteger A = receiveFromOtherSide();<br>
* byte[] key = dh.getKey(g, p, A);<br>
* sendToOtherSide(dh.getB());<br>
* </code>
* @author Tobias Marstaller
*/
public class DiffieHellman
{
public static final int PARTNER_A = 0xF124A;
public static final int PARTNER_B = 0xC134B;
protected BigInteger g;
protected BigInteger p;
protected BigInteger a;
protected BigInteger b;
protected BigInteger A;
protected BigInteger B;
protected byte[] K;
protected int side;
protected boolean initDone = false;
protected SecureRandom rand;
/**
* Constructs a new Key-Exchange for the given side
*/
public DiffieHellman(int side)
{
if (side != PARTNER_A && side != PARTNER_B)
{
throw new IllegalArgumentException("side must be equal to PARTNER_A or PARTNER_B");
}
this.side = side;
}
/**
* Constructs a new Key-Exchange for the given side with the default bit
* length 1024 and <code>random</code> as a source of randomness.
* @param random A SPRNG for the parameter-generation
*/
public DiffieHellman(int side, SecureRandom random)
{
this(side);
this.rand = random;
}
/**
* Constructs a new Key-Exchange for side B (therefore <code>assert(side == PARTNER_B)</code>)
* with <code>b</code> as the private parameter.<br>
* If this constructor is used, the call to {@link #init()} is not required anymore.
* @param b The private parameter <code>b</code>
*/
public DiffieHellman(int side, BigInteger b)
{
if (side != PARTNER_B)
{
throw new IllegalArgumentException("Side must be PARTNER_B");
}
this.side = side;
this.b = b;
initDone = true;
}
/**
* Constructs a new Key-Exchange for side A (therefore <code>assert(side == PARTNER_A)</code>)
* with <code>g</code>, <code>p</code> and <code>a</code> as the private parameters.<br>
* If this constructor is used, the call to {@link #init()} is not required anymore.
* @param g The private parameter <code>g</code>
* @param p The private parameter <code>p</code>
* @param a The private parameter <code>a</code>
*/
public DiffieHellman(int side, BigInteger g, BigInteger p, BigInteger a)
{
if (side != PARTNER_A)
{
throw new IllegalArgumentException("Side must be PARTNER_A");
}
this.side = side;
this.g = g;
this.p = p;
this.a = a;
this.A = this.g.modPow(a, p);
initDone = true;
}
/**
* Initializes the instance with the default bit-length 1024
*/
public void init()
{
init(1024);
}
/**
* Initializes the instance with the given bitLength
*/
public void init(int bitLength)
{
if (rand == null)
{
rand = new SecureRandom();
}
if (this.side == PARTNER_A)
{
this.g = BigInteger.probablePrime(bitLength, rand);
this.p = BigInteger.probablePrime(bitLength, rand);
this.a = BigInteger.probablePrime(bitLength, rand);
this.A = this.g.modPow(a, p);
}
else if (this.side == PARTNER_B)
{
this.b = BigInteger.probablePrime(bitLength, rand);
}
initDone = true;
}
/**
* @return Returns the key, if already calculated
* @throws RuntimeException If the key hast not been calculated yet.
*/
public byte[] getKey()
{
if (this.K == null)
{
throw new RuntimeException("The key has not been calculated yet.");
}
return K;
}
/**
* Calculates the key for side B (therefore <code>assert(side == PARTNER_B)</code>).
* @param g Parameter <code>g</code>
* @param p Parameter <code>p</code>
* @param A Parameter <code>A</code>
* @return Returns the calculated key
* @throws UnsupportedOperaionException If this instance has been inizialied as PARTNER_A
* @throws RuntimeException If the parameters are not initialized
*/
public byte[] getKey(BigInteger g, BigInteger p, BigInteger A)
{
if (this.side != PARTNER_B)
{
throw new UnsupportedOperationException("This method only works for PARTNER_B instances.");
}
if (!this.initDone)
{
throw new RuntimeException("The object has to be initialized.");
}
this.B = g.modPow(b, p);
this.K = A.modPow(b, p).toByteArray();
return K;
}
/**
* Calculates the key for side A (therefore <code>assert(side == PARTNER_A)</code>).
* @param g Parameter <code>g</code>
* @param p Parameter <code>p</code>
* @param A Parameter <code>A</code>
* @return Returns the calculated key
* @throws UnsupportedOperaionException If this instance has been inizialied as PARTNER_B
*/
public byte[] getKey(BigInteger B)
{
if (this.side != PARTNER_A)
{
throw new UnsupportedOperationException("This method only works for PARTNER_A instances.");
}
if (!this.initDone)
{
throw new RuntimeException("The object has to be initialized.");
}
this.K = B.modPow(a, p).toByteArray();
return K;
}
public BigInteger getG()
{
return g;
}
public BigInteger getP()
{
return p;
}
public BigInteger getA()
{
return A;
}
public BigInteger getB()
{
return B;
}
}
Código de demostración:
// Partner A
DiffieHellman dh = new DiffieHellman(DiffieHellman.PARTNER_A);
dh.init(512);
sendToOtherSide(dh.getG());
sendToOtherSide(dh.getP());
sendToOtherSide(dh.getA());
byte[] key = dh.getKey(receiveFromOtherSide());
// Partner B
DiffieHellman dh = new DiffieHellman(DiffieHellman.PARTNER_B);
dh.init(512);
BigInteger g = receiveFromOtherSide();
BigInteger p = receiveFromOtherSide();
BigInteger A = receiveFromOtherSide();
byte[] key = dh.getKey(g, p, A);
sendToOtherSide(dh.getB());
Autor: Tobias Marstaller
Saludos