com.subgraph.orchid.crypto.TorCreateFastKeyAgreement Maven / Gradle / Ivy
package com.subgraph.orchid.crypto;
import java.nio.ByteBuffer;
import java.util.Arrays;
public class TorCreateFastKeyAgreement implements TorKeyAgreement {
private final byte[] xValue;
private byte[] yValue;
public TorCreateFastKeyAgreement() {
final TorRandom random = new TorRandom();
xValue = random.getBytes(TorMessageDigest.TOR_DIGEST_SIZE);
}
public byte[] getPublicValue() {
return Arrays.copyOf(xValue, xValue.length);
}
public void setOtherValue(byte[] yValue) {
if(yValue == null || yValue.length != TorMessageDigest.TOR_DIGEST_SIZE) {
throw new IllegalArgumentException();
}
this.yValue = Arrays.copyOf(yValue, yValue.length);
}
public byte[] getDerivedValue() {
if(yValue == null) {
throw new IllegalStateException("Must call setOtherValue() first");
}
final byte[] result = new byte[2 * TorMessageDigest.TOR_DIGEST_SIZE];
System.arraycopy(xValue, 0, result, 0, TorMessageDigest.TOR_DIGEST_SIZE);
System.arraycopy(yValue, 0, result, TorMessageDigest.TOR_DIGEST_SIZE, TorMessageDigest.TOR_DIGEST_SIZE);
return result;
}
public byte[] createOnionSkin() {
return getPublicValue();
}
public boolean deriveKeysFromHandshakeResponse(byte[] handshakeResponse,
byte[] keyMaterialOut, byte[] verifyHashOut) {
final ByteBuffer bb = ByteBuffer.wrap(handshakeResponse);
final byte[] peerValue = new byte[TorMessageDigest.TOR_DIGEST_SIZE];
final byte[] keyHash = new byte[TorMessageDigest.TOR_DIGEST_SIZE];
bb.get(peerValue);
bb.get(keyHash);
setOtherValue(peerValue);
final byte[] seed = getDerivedValue();
final TorKeyDerivation kdf = new TorKeyDerivation(seed);
kdf.deriveKeys(keyMaterialOut, verifyHashOut);
return Arrays.equals(verifyHashOut, keyHash);
}
}