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 @@
 		<dependency>
 			<groupId>com.nimbusds</groupId>
 			<artifactId>srp6a</artifactId>
-			<version>1.5.2</version>
+			<version>2.1.0</version>
 		</dependency>
 
 		<dependency>
 			<groupId>org.bouncycastle</groupId>
 			<artifactId>bcprov-jdk15on</artifactId>
-			<version>1.51</version>
+			<version>1.67</version>
 		</dependency>
 
 		<dependency>
 			<groupId>net.vrallev.ecc</groupId>
 			<artifactId>ecc-25519-java</artifactId>
-			<version>1.0.1</version>
-		</dependency>
-
-		<dependency>
-			<groupId>org.zeromq</groupId>
-			<artifactId>curve25519-java</artifactId>
-			<version>0.1.0</version>
+			<version>1.0.3</version>
 		</dependency>
 
 		<dependency>
 			<groupId>javax.json</groupId>
 			<artifactId>javax.json-api</artifactId>
-			<version>1.0</version>
+			<version>1.1.4</version>
 		</dependency>
 
 		<dependency>
 			<groupId>org.glassfish</groupId>
 			<artifactId>javax.json</artifactId>
-			<version>1.0.4</version>
+			<version>1.1.4</version>
 		</dependency>
 
 		<dependency>
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) {