Interface to Diffie-Hellman algorithms

This commit is contained in:
Rhys Weatherley 2016-06-18 15:57:29 +10:00
parent a47b03674d
commit 5e10f7dda9
4 changed files with 366 additions and 0 deletions

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package com.southernstorm.noise.crypto;
/**
* Implementation of the Curve25519 elliptic-curve algorithm.
*/
public final class Curve25519 {
private Curve25519() {}
/**
* Evaluates the Curve25519 curve.
*
* @param result Buffer to place the result of the evaluation into.
* @param offset Offset into the result buffer.
* @param privateKey The private key to use in the evaluation.
* @param publicKey The public key to use in the evaluation, or null
* if the base point of the curve should be used.
*/
public static void eval(byte[] result, int offset, byte[] privateKey, byte[] publicKey)
{
// TODO
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package com.southernstorm.noise.protocol;
import java.util.Arrays;
import com.southernstorm.noise.crypto.Curve25519;
/**
* Implementation of the Curve25519 algorithm for the Noise protocol.
*/
class Curve25519DHState implements DHState {
private byte[] publicKey;
private byte[] privateKey;
private int mode;
/**
* Constructs a new Diffie-Hellman object for Curve25519.
*/
public Curve25519DHState()
{
publicKey = new byte [32];
privateKey = new byte [32];
mode = 0;
}
@Override
public void destroy() {
clearKey();
}
@Override
public String getDHName() {
return "25519";
}
@Override
public int getPublicKeyLength() {
return 32;
}
@Override
public int getPrivateKeyLength() {
return 32;
}
@Override
public int getSharedKeyLength() {
return 32;
}
@Override
public void generateKeyPair() {
Noise.random(privateKey);
Curve25519.eval(publicKey, 0, privateKey, null);
mode = 0x03;
}
@Override
public void getPublicKey(byte[] key, int offset) {
System.arraycopy(publicKey, 0, key, offset, 32);
}
@Override
public void setPublicKey(byte[] key, int offset) {
System.arraycopy(key, offset, publicKey, 0, 32);
Arrays.fill(privateKey, (byte)0);
mode = 0x01;
}
@Override
public void getPrivateKey(byte[] key, int offset) {
System.arraycopy(privateKey, 0, key, offset, 32);
}
@Override
public void setPrivateKey(byte[] key, int offset) {
System.arraycopy(key, offset, publicKey, 0, 32);
Curve25519.eval(publicKey, 0, privateKey, null);
mode = 0x03;
}
@Override
public void setToNullPublicKey() {
Arrays.fill(publicKey, (byte)0);
Arrays.fill(privateKey, (byte)0);
mode = 0x01;
}
@Override
public void clearKey() {
Noise.destroy(publicKey);
Noise.destroy(privateKey);
mode = 0;
}
@Override
public boolean hasPublicKey() {
return (mode & 0x01) != 0;
}
@Override
public boolean hasPrivateKey() {
return (mode & 0x02) != 0;
}
@Override
public boolean isNullPublicKey() {
if ((mode & 0x01) == 0)
return false;
int temp = 0;
for (int index = 0; index < 32; ++index)
temp |= publicKey[index];
return temp == 0;
}
@Override
public void calculate(byte[] sharedKey, int offset, DHState publicDH) {
if (!(publicDH instanceof Curve25519DHState))
throw new IllegalArgumentException("Incompatible DH algorithms");
Curve25519.eval(sharedKey, offset, privateKey, ((Curve25519DHState)publicDH).publicKey);
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package com.southernstorm.noise.protocol;
/**
* Interface to a Diffie-Hellman algorithm for the Noise protocol.
*/
public interface DHState extends Destroyable {
/**
* Gets the Noise protocol name for this Diffie-Hellman algorithm.
*
* @return The algorithm name.
*/
String getDHName();
/**
* Gets the length of public keys for this algorithm.
*
* @return The length of public keys in bytes.
*/
int getPublicKeyLength();
/**
* Gets the length of private keys for this algorithm.
*
* @return The length of private keys in bytes.
*/
int getPrivateKeyLength();
/**
* Gets the length of shared keys for this algorithm.
*
* @return The length of shared keys in bytes.
*/
int getSharedKeyLength();
/**
* Generates a new random keypair.
*/
void generateKeyPair();
/**
* Gets the public key associated with this object.
*
* @param key The buffer to copy the public key to.
* @param offset The first offset in the key buffer to copy to.
*/
void getPublicKey(byte[] key, int offset);
/**
* Sets the public key for this object.
*
* @param key The buffer containing the public key.
* @param offset The first offset in the buffer that contains the key.
*
* If this object previously held a key pair, then this function
* will change it into a public key only object.
*/
void setPublicKey(byte[] key, int offset);
/**
* Gets the private key associated with this object.
*
* @param key The buffer to copy the private key to.
* @param offset The first offset in the key buffer to copy to.
*/
void getPrivateKey(byte[] key, int offset);
/**
* Sets the private key for this object.
*
* @param key The buffer containing the [rivate key.
* @param offset The first offset in the buffer that contains the key.
*
* If this object previously held only a public key, then
* this function will change it into a key pair.
*/
void setPrivateKey(byte[] key, int offset);
/**
* Sets this object to the null public key and clears the private key.
*/
void setToNullPublicKey();
/**
* Clears the key pair.
*/
void clearKey();
/**
* Determine if this object contains a public key.
*
* @return Returns true if this object contains a public key,
* or false if the public key has not yet been set.
*/
boolean hasPublicKey();
/**
* Determine if this object contains a private key.
*
* @return Returns true if this object contains a private key,
* or false if the private key has not yet been set.
*/
boolean hasPrivateKey();
/**
* Determine if the public key in this object is the special null value.
*
* @return Returns true if the public key is the special null value,
* or false otherwise.
*/
boolean isNullPublicKey();
/**
* Performs a Diffie-Hellman calculation with this object as the private key.
*
* @param sharedKey Buffer to put the shared key into.
* @param offset Offset of the first byte for the shared key.
* @param publicDH Object that contains the public key for the calculation.
*
* @throws IllegalArgumentException The publicDH object is not the same
* type as this object, or one of the objects does not contain a valid key.
*/
void calculate(byte[] sharedKey, int offset, DHState publicDH);
}

View File

@ -24,6 +24,7 @@ package com.southernstorm.noise.protocol;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import com.southernstorm.noise.crypto.Blake2bMessageDigest;
@ -43,7 +44,37 @@ public final class Noise {
{
Arrays.fill(array, (byte)0);
}
private static SecureRandom random = new SecureRandom();
/**
* Generates random data using the system random number generator.
*
* @param data The data buffer to fill with random data.
*/
public static void random(byte[] data)
{
random.nextBytes(data);
}
/**
* Creates a Diffie-Hellman object from its Noise protocol name.
*
* @param name The name of the DH algorithm; e.g. "25519", "448", etc.
*
* @return The Diffie-Hellman object if the name is recognized.
*
* @throws NoSuchAlgorithmException The name is not recognized as a
* valid Noise protocol name, or there is no cryptography provider
* in the system that implements the algorithm.
*/
public static DHState createDH(String name) throws NoSuchAlgorithmException
{
if (name.equals("25519"))
return new Curve25519DHState();
throw new NoSuchAlgorithmException("Unknown Noise DH algorithm name: " + name);
}
/**
* Creates a cipher object from its Noise protocol name.
*