Diffie-Hellman

Iniciado por Adalher, Septiembre 01, 2019, 12:25:38 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

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:
Código: java

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 ==&gt;
*                      B = g^b mod p
*                   &lt;== 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:
Código: java

// 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());


Código: java

// 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
Este es el mayor reproche al pueblo hispanohablante:

Que a pesar de su inteligencia y a pesar de su valentía siempre adoran el poder.