docs: public BigInteger step1(final String userID, final BigInteger s, final BigInteger v) {
  
      // Check arguments
  
      if (userID == null || userID.trim().isEmpty())
        throw new IllegalArgumentException("The user identity 'I' must not be null or empty");
  
      this.userID = userID;
  
      if (s == null) throw new IllegalArgumentException("The salt 's' must not be null");
  
      this.s = s;
  
      if (v == null) throw new IllegalArgumentException("The verifier 'v' must not be null");
  
      this.v = v;
  
      // Check current state
      if (state != State.INIT)
        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);
      digest.reset();
  
      b = HomekitSRP6Routines.generatePrivateValue(config.N, random);
      digest.reset();
  
      B = SRP6Routines.computePublicServerValue(config.N, config.g, k, v, b);
  
      state = State.STEP_1;
  
      updateLastActivityTime();
  
      return B;
    }