/** * @param hash either a Hash or a SHA1Hash * @since 0.8.3 */ private boolean verifySig( Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) { long start = _context.clock().now(); try { byte[] sigbytes = signature.getData(); byte rbytes[] = new byte[20]; byte sbytes[] = new byte[20]; // System.arraycopy(sigbytes, 0, rbytes, 0, 20); // System.arraycopy(sigbytes, 20, sbytes, 0, 20); for (int x = 0; x < 40; x++) { if (x < 20) { rbytes[x] = sigbytes[x]; } else { sbytes[x - 20] = sigbytes[x]; } } BigInteger s = new NativeBigInteger(1, sbytes); BigInteger r = new NativeBigInteger(1, rbytes); BigInteger y = new NativeBigInteger(1, verifyingKey.getData()); BigInteger w = null; try { w = s.modInverse(CryptoConstants.dsaq); } catch (ArithmeticException ae) { _log.warn("modInverse() error", ae); return false; } byte data[] = hash.getData(); NativeBigInteger bi = new NativeBigInteger(1, data); BigInteger u1 = bi.multiply(w).mod(CryptoConstants.dsaq); BigInteger u2 = r.multiply(w).mod(CryptoConstants.dsaq); BigInteger modval = CryptoConstants.dsag.modPow(u1, CryptoConstants.dsap); BigInteger modmulval = modval.multiply(y.modPow(u2, CryptoConstants.dsap)); BigInteger v = (modmulval).mod(CryptoConstants.dsap).mod(CryptoConstants.dsaq); boolean ok = v.compareTo(r) == 0; long diff = _context.clock().now() - start; if (diff > 1000) { if (_log.shouldLog(Log.WARN)) _log.warn("Took too long to verify the signature (" + diff + "ms)"); } return ok; } catch (Exception e) { _log.log(Log.CRIT, "Error verifying the signature", e); return false; } }
/** * @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; }