コード例 #1
0
ファイル: DSAEngine.java プロジェクト: hfeeki/I2P
  /**
   * @param hash either a Hash or a SHA1Hash
   * @since 0.8.3
   */
  private Signature signIt(SimpleDataStructure hash, SigningPrivateKey signingKey) {
    if ((signingKey == null) || (hash == null)) return null;
    long start = _context.clock().now();

    Signature sig = new Signature();
    BigInteger k;

    boolean ok = false;
    do {
      k = new BigInteger(160, _context.random());
      ok = k.compareTo(CryptoConstants.dsaq) != 1;
      ok = ok && !k.equals(BigInteger.ZERO);
      // System.out.println("K picked (ok? " + ok + "): " + k.bitLength() + ": " + k.toString());
    } while (!ok);

    BigInteger r = CryptoConstants.dsag.modPow(k, CryptoConstants.dsap).mod(CryptoConstants.dsaq);
    BigInteger kinv = k.modInverse(CryptoConstants.dsaq);

    BigInteger M = new NativeBigInteger(1, hash.getData());
    BigInteger x = new NativeBigInteger(1, signingKey.getData());
    BigInteger s = (kinv.multiply(M.add(x.multiply(r)))).mod(CryptoConstants.dsaq);

    byte[] rbytes = r.toByteArray();
    byte[] sbytes = s.toByteArray();
    byte[] out = new byte[40];

    // (q^random)%p is computationally random
    _context.random().harvester().feedEntropy("DSA.sign", rbytes, 0, rbytes.length);

    if (rbytes.length == 20) {
      // System.arraycopy(rbytes, 0, out, 0, 20);
      for (int i = 0; i < 20; i++) {
        out[i] = rbytes[i];
      }
    } else if (rbytes.length == 21) {
      // System.arraycopy(rbytes, 1, out, 0, 20);
      for (int i = 0; i < 20; i++) {
        out[i] = rbytes[i + 1];
      }
    } else {
      if (_log.shouldLog(Log.DEBUG))
        _log.debug("Using short rbytes.length [" + rbytes.length + "]");
      // System.arraycopy(rbytes, 0, out, 20 - rbytes.length, rbytes.length);
      for (int i = 0; i < rbytes.length; i++) out[i + 20 - rbytes.length] = rbytes[i];
    }
    if (sbytes.length == 20) {
      // System.arraycopy(sbytes, 0, out, 20, 20);
      for (int i = 0; i < 20; i++) {
        out[i + 20] = sbytes[i];
      }
    } else if (sbytes.length == 21) {
      // System.arraycopy(sbytes, 1, out, 20, 20);
      for (int i = 0; i < 20; i++) {
        out[i + 20] = sbytes[i + 1];
      }
    } else {
      if (_log.shouldLog(Log.DEBUG))
        _log.debug("Using short sbytes.length [" + sbytes.length + "]");
      // System.arraycopy(sbytes, 0, out, 40 - sbytes.length, sbytes.length);
      for (int i = 0; i < sbytes.length; i++) out[i + 20 + 20 - sbytes.length] = sbytes[i];
    }
    sig.setData(out);

    long diff = _context.clock().now() - start;
    if (diff > 1000) {
      if (_log.shouldLog(Log.WARN)) _log.warn("Took too long to sign (" + diff + "ms)");
    }

    return sig;
  }