diff --git a/CHANGES.md b/CHANGES.md
index 758ddf6f7..cfa0188e1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -14,6 +14,7 @@
* Valid values are supported for enum characteristics instead of min and max values
* Supported valid states for Thermostat, SecuritySystem, HeaterCooler and HumidifierDehumidifier [#108] [#120](https://github.com/hap-java/HAP-Java/pull/120)
* Support for FilterMaintenance. Can be used as a linked service for an Air Purifier [#124](https://github.com/hap-java/HAP-Java/pull/124)
+* Update crypto libs [#130](https://github.com/hap-java/HAP-Java/pull/130)
# HAP-Java 1.1.5
diff --git a/pom.xml b/pom.xml
index 5faf6eafc..d4f47b432 100644
--- a/pom.xml
+++ b/pom.xml
@@ -100,37 +100,31 @@
com.nimbusds
srp6a
- 1.5.2
+ 2.1.0
org.bouncycastle
bcprov-jdk15on
- 1.51
+ 1.67
net.vrallev.ecc
ecc-25519-java
- 1.0.1
-
-
-
- org.zeromq
- curve25519-java
- 0.1.0
+ 1.0.3
javax.json
javax.json-api
- 1.0
+ 1.1.4
org.glassfish
javax.json
- 1.0.4
+ 1.1.4
diff --git a/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java b/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java
index 9b5b2b8ee..20a697ff9 100644
--- a/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java
+++ b/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java
@@ -2,7 +2,6 @@
import com.nimbusds.srp6.SRP6Routines;
import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
import java.security.SecureRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -14,11 +13,12 @@ public class HomekitUtils {
private static volatile SecureRandom secureRandom;
public static BigInteger generateSalt() {
- return new BigInteger(SRP6Routines.generateRandomSalt(16));
+ return new BigInteger(new SRP6Routines().generateRandomSalt(16));
}
- public static byte[] generateKey() throws InvalidAlgorithmParameterException {
- EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
+ public static byte[] generateKey() {
+ EdDSAParameterSpec spec =
+ EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
byte[] seed = new byte[spec.getCurve().getField().getb() / 8];
getSecureRandom().nextBytes(seed);
return seed;
diff --git a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java
index 4c74a469d..d616d2e0f 100644
--- a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java
+++ b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java
@@ -5,8 +5,6 @@
import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.tls.AlertDescription;
-import org.bouncycastle.crypto.tls.TlsFatalAlert;
import org.bouncycastle.util.Arrays;
public class ChachaDecoder {
@@ -28,7 +26,7 @@ public byte[] decodeCiphertext(byte[] receivedMAC, byte[] additionalData, byte[]
byte[] calculatedMAC = PolyKeyCreator.create(macKey, additionalData, ciphertext);
if (!Arrays.constantTimeAreEqual(calculatedMAC, receivedMAC)) {
- throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ throw new IOException("received an incorrect MAC");
}
byte[] output = new byte[ciphertext.length];
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java b/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java
index 6516e2e29..e65beec3c 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java
@@ -22,7 +22,7 @@ public static byte[] joinBytes(byte[]... piece) {
return ret;
}
- public static byte[] toByteArray(BigInteger i) {
+ public static byte[] toUnsignedByteArray(BigInteger i) {
byte[] array = i.toByteArray();
if (array[0] == 0) {
array = Arrays.copyOfRange(array, 1, array.length);
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java b/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java
index 16c514707..87ddf3907 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java
@@ -8,9 +8,7 @@
class ClientEvidenceRoutineImpl implements ClientEvidenceRoutine {
- public ClientEvidenceRoutineImpl() {
- // TODO Auto-generated constructor stub
- }
+ public ClientEvidenceRoutineImpl() {}
/**
* Calculates M1 according to the following formula:
@@ -27,10 +25,10 @@ public BigInteger computeClientEvidence(
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Could not locate requested algorithm", e);
}
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.N));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(cryptoParams.N));
byte[] hN = digest.digest();
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.g));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(cryptoParams.g));
byte[] hg = digest.digest();
byte[] hNhg = xor(hN, hg);
@@ -38,14 +36,14 @@ public BigInteger computeClientEvidence(
digest.update(ctx.userID.getBytes(StandardCharsets.UTF_8));
byte[] hu = digest.digest();
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.S));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.S));
byte[] hS = digest.digest();
digest.update(hNhg);
digest.update(hu);
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.s));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.A));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.B));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.s));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.A));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.B));
digest.update(hS);
BigInteger ret = new BigInteger(1, digest.digest());
return ret;
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java b/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java
index 3841d9fb7..116fced13 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java
@@ -8,6 +8,7 @@
import com.nimbusds.srp6.SRP6Session;
import com.nimbusds.srp6.URoutineContext;
import java.math.BigInteger;
+import java.security.MessageDigest;
/**
* This is a slightly modified version of the SRP6ServerSession class included with nimbus. The only
@@ -74,6 +75,8 @@ public static enum State {
/** The current SRP-6a auth state. */
private State state;
+ private MessageDigest digest;
+
/**
* Creates a new server-side SRP-6a authentication session and sets its state to {@link
* State#INIT}.
@@ -92,7 +95,7 @@ public HomekitSRP6ServerSession(final SRP6CryptoParams config, final int timeout
this.config = config;
- digest = config.getMessageDigestInstance();
+ this.digest = config.getMessageDigestInstance();
if (digest == null)
throw new IllegalArgumentException("Unsupported hash algorithm 'H': " + config.H);
@@ -151,13 +154,13 @@ public BigInteger step1(final String userID, final BigInteger s, final BigIntege
throw new IllegalStateException("State violation: Session must be in INIT state");
// Generate server private and public values
- k = SRP6Routines.computeK(digest, config.N, config.g);
+ k = new SRP6Routines().computeK(digest, config.N, config.g);
digest.reset();
b = HomekitSRP6Routines.generatePrivateValue(config.N, random);
digest.reset();
- B = SRP6Routines.computePublicServerValue(config.N, config.g, k, v, b);
+ B = new SRP6Routines().computePublicServerValue(config.N, config.g, k, v, b);
state = State.STEP_1;
@@ -234,7 +237,7 @@ public BigInteger step2(final BigInteger A, final BigInteger M1) throws SRP6Exce
if (hasTimedOut()) throw new SRP6Exception("Session timeout", SRP6Exception.CauseType.TIMEOUT);
// Check A validity
- if (!SRP6Routines.isValidPublicValue(config.N, A))
+ if (!new SRP6Routines().isValidPublicValue(config.N, A))
throw new SRP6Exception(
"Bad client public value 'A'", SRP6Exception.CauseType.BAD_PUBLIC_VALUE);
@@ -246,11 +249,11 @@ public BigInteger step2(final BigInteger A, final BigInteger M1) throws SRP6Exce
URoutineContext hashedKeysContext = new URoutineContext(A, B);
u = hashedKeysRoutine.computeU(config, hashedKeysContext);
} else {
- u = SRP6Routines.computeU(digest, config.N, A, B);
+ u = new SRP6Routines().computeU(digest, config.N, A, B);
digest.reset();
}
- S = SRP6Routines.computeSessionKey(config.N, v, u, A, b);
+ S = new SRP6Routines().computeSessionKey(config.N, v, u, A, b);
// Compute the own client evidence message 'M1'
BigInteger computedM1;
@@ -262,7 +265,7 @@ public BigInteger step2(final BigInteger A, final BigInteger M1) throws SRP6Exce
computedM1 = clientEvidenceRoutine.computeClientEvidence(config, ctx);
} else {
// With default routine
- computedM1 = SRP6Routines.computeClientEvidence(digest, A, B, S);
+ computedM1 = new SRP6Routines().computeClientEvidence(digest, A, B, S);
digest.reset();
}
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java b/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java
index af6a6e01f..ee4b772f9 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java
@@ -29,7 +29,7 @@ public HttpResponse handle(HttpRequest httpRequest) throws Exception {
if (req.getStage() == Stage.ONE) {
logger.trace("Starting pair for " + registry.getLabel());
srpHandler = new SrpHandler(authInfo.getPin(), authInfo.getSalt());
- return srpHandler.handle(req);
+ return srpHandler.step1();
} else if (req.getStage() == Stage.TWO) {
logger.trace("Entering second stage of pair for " + registry.getLabel());
if (srpHandler == null) {
@@ -37,7 +37,7 @@ public HttpResponse handle(HttpRequest httpRequest) throws Exception {
return new UnauthorizedResponse();
} else {
try {
- return srpHandler.handle(req);
+ return srpHandler.step2((PairSetupRequest.Stage2Request) req);
} catch (Exception e) {
srpHandler = null; // You don't get to try again - need a new key
logger.warn("Exception encountered while processing pairing request", e);
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java b/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java
index 7cf7b3164..6c032ce59 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java
@@ -1,5 +1,6 @@
package io.github.hapjava.server.impl.pairing;
+import com.nimbusds.srp6.BigIntegerUtils;
import com.nimbusds.srp6.SRP6CryptoParams;
import com.nimbusds.srp6.SRP6ServerEvidenceContext;
import com.nimbusds.srp6.ServerEvidenceRoutine;
@@ -20,10 +21,10 @@ public BigInteger computeServerEvidence(
throw new RuntimeException("Could not locate requested algorithm", e);
}
- byte[] hS = digest.digest(SrpHandler.bigIntegerToUnsignedByteArray(ctx.S));
+ byte[] hS = digest.digest(BigIntegerUtils.bigIntegerToBytes(ctx.S));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.A));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.M1));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.A));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.M1));
digest.update(hS);
return new BigInteger(1, digest.digest());
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java b/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java
index e02ccdb90..92d2098fa 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java
@@ -6,20 +6,15 @@
import io.github.hapjava.server.impl.pairing.PairSetupRequest.Stage2Request;
import io.github.hapjava.server.impl.pairing.TypeLengthValueUtils.Encoder;
import io.github.hapjava.server.impl.responses.ConflictResponse;
-import io.github.hapjava.server.impl.responses.NotFoundResponse;
import java.math.BigInteger;
import java.security.MessageDigest;
-import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class SrpHandler {
- // Precomputed safe 3072 bit prime 'N'. Origin RFC 5054, appendix A.
- private static final BigInteger N_3072 =
- new BigInteger(
- "5809605995369958062791915965639201402176612226902900533702900882779736177890990861472094774477339581147373410185646378328043729800750470098210924487866935059164371588168047540943981644516632755067501626434556398193186628990071248660819361205119793693985433297036118232914410171876807536457391277857011849897410207519105333355801121109356897459426271845471397952675959440793493071628394122780510124618488232602464649876850458861245784240929258426287699705312584509625419513463605155428017165714465363094021609290561084025893662561222573202082865797821865270991145082200656978177192827024538990239969175546190770645685893438011714430426409338676314743571154537142031573004276428701433036381801705308659830751190352946025482059931306571004727362479688415574702596946457770284148435989129632853918392117997472632693078113129886487399347796982772784615865232621289656944284216824611318709764535152507354116344703769998514148343807");
- private static final BigInteger G = BigInteger.valueOf(5);
+ private static final int BIT_SIZE = 3072;
+ private static final String HASH_ALG_H = "SHA-512";
private static final String IDENTIFIER = "Pair-Setup";
private static final Logger logger = LoggerFactory.getLogger(SrpHandler.class);
@@ -30,7 +25,7 @@ class SrpHandler {
private final String pin;
public SrpHandler(String pin, BigInteger salt) {
- config = new SRP6CryptoParams(N_3072, G, "SHA-512");
+ config = SRP6CryptoParams.getInstance(BIT_SIZE, HASH_ALG_H);
session = new HomekitSRP6ServerSession(config);
session.setClientEvidenceRoutine(new ClientEvidenceRoutineImpl());
session.setServerEvidenceRoutine(new ServerEvidenceRoutineImpl());
@@ -38,20 +33,7 @@ public SrpHandler(String pin, BigInteger salt) {
this.salt = salt;
}
- public HttpResponse handle(PairSetupRequest request) throws Exception {
- switch (request.getStage()) {
- case ONE:
- return step1();
-
- case TWO:
- return step2((Stage2Request) request);
-
- default:
- return new NotFoundResponse();
- }
- }
-
- private HttpResponse step1() throws Exception {
+ HttpResponse step1() throws Exception {
if (session.getState() != State.INIT) {
logger.warn("Session is not in state INIT when receiving step1");
return new ConflictResponse();
@@ -68,7 +50,7 @@ private HttpResponse step1() throws Exception {
return new PairingResponse(encoder.toByteArray());
}
- private HttpResponse step2(Stage2Request request) throws Exception {
+ HttpResponse step2(Stage2Request request) throws Exception {
if (session.getState() != State.STEP_1) {
logger.warn("Session is not in state Stage 1 when receiving step2");
return new ConflictResponse();
@@ -80,18 +62,10 @@ private HttpResponse step2(Stage2Request request) throws Exception {
return new PairingResponse(encoder.toByteArray());
}
- public byte[] getK() {
+ byte[] getK() {
MessageDigest digest = session.getCryptoParams().getMessageDigestInstance();
- BigInteger S = session.getSessionKey(false);
- byte[] sBytes = bigIntegerToUnsignedByteArray(S);
+ BigInteger S = session.getSessionKey();
+ byte[] sBytes = BigIntegerUtils.bigIntegerToBytes(S);
return digest.digest(sBytes);
}
-
- public static byte[] bigIntegerToUnsignedByteArray(BigInteger i) {
- byte[] array = i.toByteArray();
- if (array[0] == 0) {
- array = Arrays.copyOfRange(array, 1, array.length);
- }
- return array;
- }
}
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java b/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java
index 396829d34..bf76f53fb 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java
@@ -1,5 +1,6 @@
package io.github.hapjava.server.impl.pairing;
+import com.nimbusds.srp6.BigIntegerUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -38,7 +39,7 @@ private Encoder() {
}
public void add(MessageType type, BigInteger i) throws IOException {
- add(type, ByteUtils.toByteArray(i));
+ add(type, BigIntegerUtils.bigIntegerToBytes(i));
}
public void add(MessageType type, short b) {