protected byte[] enginesign() throws signatureexception {
    byte[] hash = new byte[digest.getdigestsize()];

    digest.dofinal(hash, 0);

    try {
      byte[] sigbytes = new byte[64];
      biginteger[] sig = signer.generatesignature(hash);
      byte[] r = sig[0].tobytearray();
      byte[] s = sig[1].tobytearray();

      if (s[0] != 0) {
        system.arraycopy(s, 0, sigbytes, 32 - s.length, s.length);
      } else {
        system.arraycopy(s, 1, sigbytes, 32 - (s.length - 1), s.length - 1);
      }

      if (r[0] != 0) {
        system.arraycopy(r, 0, sigbytes, 64 - r.length, r.length);
      } else {
        system.arraycopy(r, 1, sigbytes, 64 - (r.length - 1), r.length - 1);
      }

      return sigbytes;
    } catch (exception e) {
      throw new signatureexception(e.tostring());
    }
  }
  // public constructors
  public digestrandomgenerator(digest digest) {
    this.digest = digest;

    this.seed = new byte[digest.getdigestsize()];
    this.seedcounter = 1;

    this.state = new byte[digest.getdigestsize()];
    this.statecounter = 1;
  }
  protected void engineinitverify(publickey publickey) throws invalidkeyexception {
    cipherparameters param;

    if (publickey instanceof ecpublickey) {
      param = ecutil.generatepublickeyparameter(publickey);
    } else if (publickey instanceof gost3410key) {
      param = gost3410util.generatepublickeyparameter(publickey);
    } else {
      try {
        byte[] bytes = publickey.getencoded();

        publickey = bouncycastleprovider.getpublickey(subjectpublickeyinfo.getinstance(bytes));

        if (publickey instanceof ecpublickey) {
          param = ecutil.generatepublickeyparameter(publickey);
        } else {
          throw new invalidkeyexception("can't recognise key type in dsa based signer");
        }
      } catch (exception e) {
        throw new invalidkeyexception("can't recognise key type in dsa based signer");
      }
    }

    digest.reset();
    signer.init(false, param);
  }
  protected boolean engineverify(byte[] sigbytes) throws signatureexception {
    byte[] hash = new byte[digest.getdigestsize()];

    digest.dofinal(hash, 0);

    biginteger[] sig;

    try {
      byte[] r = new byte[32];
      byte[] s = new byte[32];

      system.arraycopy(sigbytes, 0, s, 0, 32);

      system.arraycopy(sigbytes, 32, r, 0, 32);

      sig = new biginteger[2];
      sig[0] = new biginteger(1, r);
      sig[1] = new biginteger(1, s);
    } catch (exception e) {
      throw new signatureexception("error decoding signature bytes.");
    }

    return signer.verifysignature(hash, sig[0], sig[1]);
  }
  protected void engineinitsign(privatekey privatekey) throws invalidkeyexception {
    cipherparameters param;

    if (privatekey instanceof eckey) {
      param = ecutil.generateprivatekeyparameter(privatekey);
    } else {
      param = gost3410util.generateprivatekeyparameter(privatekey);
    }

    digest.reset();

    if (random != null) {
      signer.init(true, new parameterswithrandom(param, random));
    } else {
      signer.init(true, param);
    }
  }
 private void digestdofinal(byte[] result) {
   digest.dofinal(result, 0);
 }
 private void digestupdate(byte[] inseed) {
   digest.update(inseed, 0, inseed.length);
 }
 private void digestaddcounter(long seed) {
   for (int i = 0; i != 8; i++) {
     digest.update((byte) seed);
     seed >>>= 8;
   }
 }
 protected void engineupdate(byte[] b, int off, int len) throws signatureexception {
   digest.update(b, off, len);
 }
 protected void engineupdate(byte b) throws signatureexception {
   digest.update(b);
 }
 private static byte[] dofinal(digest d) {
   byte[] bs = new byte[d.getdigestsize()];
   d.dofinal(bs, 0);
   return bs;
 }