From c6559631a23a92c60b75f9ee07e9b9f06dc2dcd3 Mon Sep 17 00:00:00 2001 From: Gert-Jan van der Heiden Date: Wed, 23 Dec 2020 18:09:17 +0100 Subject: [PATCH 1/3] [#130](https://github.com/hap-java/HAP-Java/pull/130) --- CHANGES.md | 1 + pom.xml | 14 ++++---------- .../hapjava/server/impl/HomekitUtils.java | 2 +- .../server/impl/crypto/ChachaDecoder.java | 8 ++------ .../server/impl/crypto/ChachaEncoder.java | 4 +--- .../hapjava/server/impl/pairing/ByteUtils.java | 2 +- .../impl/pairing/ClientEvidenceRoutineImpl.java | 4 +--- .../impl/pairing/HomekitSRP6ServerSession.java | 17 ++++++++++------- .../hapjava/server/impl/pairing/SrpHandler.java | 4 ++-- .../impl/pairing/TypeLengthValueUtils.java | 2 +- 10 files changed, 24 insertions(+), 34 deletions(-) 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..5ffbd9609 100644 --- a/pom.xml +++ b/pom.xml @@ -100,13 +100,13 @@ com.nimbusds srp6a - 1.5.2 + 2.1.0 org.bouncycastle bcprov-jdk15on - 1.51 + 1.67 @@ -115,22 +115,16 @@ 1.0.1 - - org.zeromq - curve25519-java - 0.1.0 - - 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..9facbeb0b 100644 --- a/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java +++ b/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java @@ -14,7 +14,7 @@ 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 { 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..9b9c2cc5d 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]; @@ -45,9 +43,7 @@ private KeyParameter initRecordMAC(ChaChaEngine cipher) { byte[] firstBlock = new byte[64]; cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0); - // NOTE: The BC implementation puts 'r' after 'k' - System.arraycopy(firstBlock, 0, firstBlock, 32, 16); - KeyParameter macKey = new KeyParameter(firstBlock, 16, 32); + KeyParameter macKey = new KeyParameter(firstBlock, 0, 32); Poly1305KeyGenerator.clamp(macKey.getKey()); return macKey; } diff --git a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java index 3304e7d9a..3649844eb 100644 --- a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java +++ b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java @@ -39,9 +39,7 @@ private KeyParameter initRecordMAC(ChaChaEngine cipher) { byte[] firstBlock = new byte[64]; cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0); - // NOTE: The BC implementation puts 'r' after 'k' - System.arraycopy(firstBlock, 0, firstBlock, 32, 16); - KeyParameter macKey = new KeyParameter(firstBlock, 16, 32); + KeyParameter macKey = new KeyParameter(firstBlock, 0, 32); Poly1305KeyGenerator.clamp(macKey.getKey()); return macKey; } 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..0d55985f9 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: 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/SrpHandler.java b/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java index e02ccdb90..8d26d62dc 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 @@ -82,8 +82,8 @@ private HttpResponse step2(Stage2Request request) throws Exception { public byte[] getK() { MessageDigest digest = session.getCryptoParams().getMessageDigestInstance(); - BigInteger S = session.getSessionKey(false); - byte[] sBytes = bigIntegerToUnsignedByteArray(S); + BigInteger S = session.getSessionKey(); + byte[] sBytes = toUnsignedByteArray(S); return digest.digest(sBytes); } 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..03665d94d 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 @@ -38,7 +38,7 @@ private Encoder() { } public void add(MessageType type, BigInteger i) throws IOException { - add(type, ByteUtils.toByteArray(i)); + add(type, ByteUtils.toUnsignedByteArray(i)); } public void add(MessageType type, short b) { From 1061cbe7dc4514d35a343f3e7b7f4efecda5cbc0 Mon Sep 17 00:00:00 2001 From: Gert-Jan van der Heiden Date: Wed, 23 Dec 2020 18:16:34 +0100 Subject: [PATCH 2/3] #130(https://github.com/hap-java/HAP-Java/pull/130) --- pom.xml | 2 +- .../hapjava/server/impl/HomekitUtils.java | 6 +-- .../pairing/ClientEvidenceRoutineImpl.java | 14 ++++--- .../server/impl/pairing/PairingManager.java | 4 +- .../pairing/ServerEvidenceRoutineImpl.java | 8 ++-- .../server/impl/pairing/SrpHandler.java | 40 ++++--------------- 6 files changed, 27 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index 5ffbd9609..d4f47b432 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ net.vrallev.ecc ecc-25519-java - 1.0.1 + 1.0.3 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 9facbeb0b..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; @@ -17,8 +16,9 @@ public static BigInteger generateSalt() { 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/pairing/ClientEvidenceRoutineImpl.java b/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java index 0d55985f9..7e139296c 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 @@ -1,5 +1,7 @@ package io.github.hapjava.server.impl.pairing; +import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray; + import com.nimbusds.srp6.*; import java.math.BigInteger; import java.nio.charset.StandardCharsets; @@ -25,10 +27,10 @@ public BigInteger computeClientEvidence( } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Could not locate requested algorithm", e); } - digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.N)); + digest.update(toUnsignedByteArray(cryptoParams.N)); byte[] hN = digest.digest(); - digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.g)); + digest.update(toUnsignedByteArray(cryptoParams.g)); byte[] hg = digest.digest(); byte[] hNhg = xor(hN, hg); @@ -36,14 +38,14 @@ public BigInteger computeClientEvidence( digest.update(ctx.userID.getBytes(StandardCharsets.UTF_8)); byte[] hu = digest.digest(); - digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.S)); + digest.update(toUnsignedByteArray(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(toUnsignedByteArray(ctx.s)); + digest.update(toUnsignedByteArray(ctx.A)); + digest.update(toUnsignedByteArray(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/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..77739e9b2 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,7 @@ package io.github.hapjava.server.impl.pairing; +import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray; + import com.nimbusds.srp6.SRP6CryptoParams; import com.nimbusds.srp6.SRP6ServerEvidenceContext; import com.nimbusds.srp6.ServerEvidenceRoutine; @@ -20,10 +22,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(toUnsignedByteArray(ctx.S)); - digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.A)); - digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.M1)); + digest.update(toUnsignedByteArray(ctx.A)); + digest.update(toUnsignedByteArray(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 8d26d62dc..ec4b34c97 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 @@ -1,25 +1,22 @@ package io.github.hapjava.server.impl.pairing; +import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray; + import com.nimbusds.srp6.*; import io.github.hapjava.server.impl.http.HttpResponse; import io.github.hapjava.server.impl.pairing.HomekitSRP6ServerSession.State; 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 +27,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 +35,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 +52,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 +64,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(); byte[] sBytes = toUnsignedByteArray(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; - } } From 2a5629b3c92e48cdc83fa4eadb66fc8e307c33de Mon Sep 17 00:00:00 2001 From: Ben Swanson Date: Fri, 5 Feb 2021 08:55:30 +0000 Subject: [PATCH 3/3] Fix for Chacha and change to BigIntegerUtils.bigIntegerToBytes --- .../hapjava/server/impl/crypto/ChachaDecoder.java | 4 +++- .../hapjava/server/impl/crypto/ChachaEncoder.java | 4 +++- .../impl/pairing/ClientEvidenceRoutineImpl.java | 14 ++++++-------- .../impl/pairing/ServerEvidenceRoutineImpl.java | 9 ++++----- .../hapjava/server/impl/pairing/SrpHandler.java | 4 +--- .../server/impl/pairing/TypeLengthValueUtils.java | 3 ++- 6 files changed, 19 insertions(+), 19 deletions(-) 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 9b9c2cc5d..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 @@ -43,7 +43,9 @@ private KeyParameter initRecordMAC(ChaChaEngine cipher) { byte[] firstBlock = new byte[64]; cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0); - KeyParameter macKey = new KeyParameter(firstBlock, 0, 32); + // NOTE: The BC implementation puts 'r' after 'k' + System.arraycopy(firstBlock, 0, firstBlock, 32, 16); + KeyParameter macKey = new KeyParameter(firstBlock, 16, 32); Poly1305KeyGenerator.clamp(macKey.getKey()); return macKey; } diff --git a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java index 3649844eb..3304e7d9a 100644 --- a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java +++ b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java @@ -39,7 +39,9 @@ private KeyParameter initRecordMAC(ChaChaEngine cipher) { byte[] firstBlock = new byte[64]; cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0); - KeyParameter macKey = new KeyParameter(firstBlock, 0, 32); + // NOTE: The BC implementation puts 'r' after 'k' + System.arraycopy(firstBlock, 0, firstBlock, 32, 16); + KeyParameter macKey = new KeyParameter(firstBlock, 16, 32); Poly1305KeyGenerator.clamp(macKey.getKey()); return macKey; } 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 7e139296c..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 @@ -1,7 +1,5 @@ package io.github.hapjava.server.impl.pairing; -import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray; - import com.nimbusds.srp6.*; import java.math.BigInteger; import java.nio.charset.StandardCharsets; @@ -27,10 +25,10 @@ public BigInteger computeClientEvidence( } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Could not locate requested algorithm", e); } - digest.update(toUnsignedByteArray(cryptoParams.N)); + digest.update(BigIntegerUtils.bigIntegerToBytes(cryptoParams.N)); byte[] hN = digest.digest(); - digest.update(toUnsignedByteArray(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(toUnsignedByteArray(ctx.S)); + digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.S)); byte[] hS = digest.digest(); digest.update(hNhg); digest.update(hu); - digest.update(toUnsignedByteArray(ctx.s)); - digest.update(toUnsignedByteArray(ctx.A)); - digest.update(toUnsignedByteArray(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/ServerEvidenceRoutineImpl.java b/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java index 77739e9b2..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,7 +1,6 @@ package io.github.hapjava.server.impl.pairing; -import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray; - +import com.nimbusds.srp6.BigIntegerUtils; import com.nimbusds.srp6.SRP6CryptoParams; import com.nimbusds.srp6.SRP6ServerEvidenceContext; import com.nimbusds.srp6.ServerEvidenceRoutine; @@ -22,10 +21,10 @@ public BigInteger computeServerEvidence( throw new RuntimeException("Could not locate requested algorithm", e); } - byte[] hS = digest.digest(toUnsignedByteArray(ctx.S)); + byte[] hS = digest.digest(BigIntegerUtils.bigIntegerToBytes(ctx.S)); - digest.update(toUnsignedByteArray(ctx.A)); - digest.update(toUnsignedByteArray(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 ec4b34c97..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 @@ -1,7 +1,5 @@ package io.github.hapjava.server.impl.pairing; -import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray; - import com.nimbusds.srp6.*; import io.github.hapjava.server.impl.http.HttpResponse; import io.github.hapjava.server.impl.pairing.HomekitSRP6ServerSession.State; @@ -67,7 +65,7 @@ HttpResponse step2(Stage2Request request) throws Exception { byte[] getK() { MessageDigest digest = session.getCryptoParams().getMessageDigestInstance(); BigInteger S = session.getSessionKey(); - byte[] sBytes = toUnsignedByteArray(S); + byte[] sBytes = BigIntegerUtils.bigIntegerToBytes(S); return digest.digest(sBytes); } } 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 03665d94d..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.toUnsignedByteArray(i)); + add(type, BigIntegerUtils.bigIntegerToBytes(i)); } public void add(MessageType type, short b) {