Exemple #1
0
  /**
   * Verifies the DSA signature of a signed update file.
   *
   * @param signedFile The signed update file to check.
   * @param signingPublicKey An instance of {@link net.i2p.data.SigningPublicKey} to use for
   *     verification.
   * @return <code>true</code> if the file has a valid signature, otherwise <code>false</code>.
   */
  public boolean verify(File signedFile, SigningPublicKey signingPublicKey) {
    FileInputStream fileInputStream = null;

    try {
      fileInputStream = new FileInputStream(signedFile);
      Signature signature = new Signature();

      signature.readBytes(fileInputStream);

      return _context.dsa().verifySignature(signature, fileInputStream, signingPublicKey);
    } catch (IOException ioe) {
      if (_log.shouldLog(Log.WARN)) _log.warn("Error reading " + signedFile + " to verify", ioe);

      return false;
    } catch (DataFormatException dfe) {
      if (_log.shouldLog(Log.ERROR)) _log.error("Error reading the signature", dfe);

      return false;
    } finally {
      if (fileInputStream != null)
        try {
          fileInputStream.close();
        } catch (IOException ioe) {
        }
    }
  }
Exemple #2
0
 /** @param sigprop The signature property to set */
 private void signIt(SigningPrivateKey spk, String sigprop) {
   if (props == null) throw new IllegalStateException();
   if (props.containsKey(sigprop)) throw new IllegalStateException();
   StringWriter buf = new StringWriter(1024);
   buf.append(name);
   buf.append(KV_SEPARATOR);
   buf.append(dest);
   try {
     writeProps(buf);
   } catch (IOException ioe) {
     throw new IllegalStateException(ioe);
   }
   Signature s = DSAEngine.getInstance().sign(DataHelper.getUTF8(buf.toString()), spk);
   if (s == null) throw new IllegalArgumentException("sig failed");
   props.setProperty(sigprop, s.toBase64());
 }
Exemple #3
0
 public void readBytes(InputStream rawConfig) throws DataFormatException, IOException {
   _destination = Destination.create(rawConfig);
   _options = DataHelper.readProperties(rawConfig);
   _creationDate = DataHelper.readDate(rawConfig);
   _signature = new Signature();
   _signature.readBytes(rawConfig);
 }
Exemple #4
0
 /**
  * Sign as a "remove" line #!dest=dest#name=name#k1=v1#sig=sig...] Must have been constructed with
  * non-null properties.
  */
 public void signRemove(SigningPrivateKey spk) {
   if (props == null) throw new IllegalStateException();
   if (props.containsKey(PROP_SIG)) throw new IllegalStateException();
   props.setProperty(PROP_NAME, name);
   props.setProperty(PROP_DEST, dest);
   StringWriter buf = new StringWriter(1024);
   try {
     writeProps(buf);
   } catch (IOException ioe) {
     throw new IllegalStateException(ioe);
   }
   props.remove(PROP_NAME);
   props.remove(PROP_DEST);
   Signature s = DSAEngine.getInstance().sign(DataHelper.getUTF8(buf.toString()), spk);
   if (s == null) throw new IllegalArgumentException("sig failed");
   props.setProperty(PROP_SIG, s.toBase64());
 }
Exemple #5
0
 public void writeBytes(OutputStream out) throws DataFormatException, IOException {
   if ((_destination == null)
       || (_options == null)
       || (_signature == null)
       || (_creationDate == null))
     throw new DataFormatException("Not enough data to create the session config");
   _destination.writeBytes(out);
   DataHelper.writeProperties(out, _options, true); // UTF-8
   DataHelper.writeDate(out, _creationDate);
   _signature.writeBytes(out);
 }
Exemple #6
0
 public String getProof() {
   StringBuilder buf = new StringBuilder(512);
   RouterInfo us = _context.router().getRouterInfo();
   buf.append("Hash: ").append(us.getIdentity().calculateHash().toBase64()).append('\n');
   // buf.append("Ident: ").append(us.getIdentity().toBase64()).append('\n');
   for (RouterAddress addr : us.getAddresses()) {
     buf.append(addr.getTransportStyle()).append(": ").append(addr.getHost()).append('\n');
   }
   buf.append("Caps: ").append(us.getCapabilities()).append('\n');
   buf.append("Date: ").append(new Date()); // no trailing newline
   String msg = buf.toString();
   byte[] data = DataHelper.getUTF8(msg);
   Signature sig = _context.dsa().sign(data, _context.keyManager().getSigningPrivateKey());
   buf.setLength(0);
   buf.append("---BEGIN I2P SIGNED MESSAGE---\n");
   buf.append(msg);
   buf.append("\n---BEGIN I2P SIGNATURE---\n");
   buf.append(sig.toBase64());
   buf.append("\n---END I2P SIGNATURE---");
   return buf.toString();
 }
Exemple #7
0
  /**
   * @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;
    }
  }
  /**
   * Verify: Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's new relay tag + Bob's
   * signed on time Caller must synch on this.
   */
  private boolean verifySessionCreated() {
    byte signed[] =
        new byte
            [256
                + 256 // X + Y
                + _aliceIP.length
                + 2
                + _bobIP.length
                + 2
                + 4 // sent relay tag
                + 4 // signed on time
            ];

    int off = 0;
    System.arraycopy(_sentX, 0, signed, off, _sentX.length);
    off += _sentX.length;
    System.arraycopy(_receivedY, 0, signed, off, _receivedY.length);
    off += _receivedY.length;
    System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length);
    off += _aliceIP.length;
    DataHelper.toLong(signed, off, 2, _alicePort);
    off += 2;
    System.arraycopy(_bobIP, 0, signed, off, _bobIP.length);
    off += _bobIP.length;
    DataHelper.toLong(signed, off, 2, _bobPort);
    off += 2;
    DataHelper.toLong(signed, off, 4, _receivedRelayTag);
    off += 4;
    DataHelper.toLong(signed, off, 4, _receivedSignedOnTime);
    boolean valid =
        _context
            .dsa()
            .verifySignature(_receivedSignature, signed, _remotePeer.getSigningPublicKey());
    if (_log.shouldLog(Log.DEBUG) || (_log.shouldLog(Log.WARN) && !valid)) {
      StringBuilder buf = new StringBuilder(128);
      buf.append("Signed sessionCreated:");
      buf.append(" Alice: ").append(Addresses.toString(_aliceIP, _alicePort));
      buf.append(" Bob: ").append(Addresses.toString(_bobIP, _bobPort));
      buf.append(" RelayTag: ").append(_receivedRelayTag);
      buf.append(" SignedOn: ").append(_receivedSignedOnTime);
      buf.append(" signature: ").append(Base64.encode(_receivedSignature.getData()));
      if (valid) _log.debug(buf.toString());
      else if (_log.shouldLog(Log.WARN)) _log.warn("INVALID: " + buf.toString());
    }
    return valid;
  }
Exemple #9
0
 /**
  * Alternate to verifySignature() using java.security libraries.
  *
  * @throws GeneralSecurityException if algorithm unvailable or on other errors
  * @since 0.8.7
  */
 private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey)
     throws GeneralSecurityException {
   java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
   KeyFactory keyFact = KeyFactory.getInstance("DSA");
   // y p q g
   KeySpec spec =
       new DSAPublicKeySpec(
           new NativeBigInteger(1, verifyingKey.getData()),
           CryptoConstants.dsap,
           CryptoConstants.dsaq,
           CryptoConstants.dsag);
   PublicKey pubKey = keyFact.generatePublic(spec);
   jsig.initVerify(pubKey);
   jsig.update(data);
   boolean rv = jsig.verify(sigBytesToASN1(signature.getData()));
   // if (!rv) {
   //    System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData()));
   //    System.out.println("BAD SIG\n" +
   // net.i2p.util.HexDump.dump(sigBytesToASN1(signature.getData())));
   // }
   return rv;
 }
Exemple #10
0
  /**
   * @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;
  }
Exemple #11
0
  /**
   * Uses the given {@link net.i2p.data.SigningPrivateKey} to sign the given input file along with
   * its version string using DSA. The output will be a signed update file where the first 40 bytes
   * are the resulting DSA signature, the next 16 bytes are the input file's version string encoded
   * in UTF-8 (padded with trailing <code>0h</code> characters if necessary), and the remaining
   * bytes are the raw bytes of the input file.
   *
   * @param inputFile The file to be signed.
   * @param signedFile The signed update file to write.
   * @param signingPrivateKey An instance of <code>SigningPrivateKey</code> to sign <code>inputFile
   *     </code> with.
   * @param version The version string of the input file. If this is longer than 16 characters it
   *     will be truncated.
   * @return An instance of {@link net.i2p.data.Signature}, or <code>null</code> if there was an
   *     error.
   */
  public Signature sign(
      String inputFile, String signedFile, SigningPrivateKey signingPrivateKey, String version) {
    byte[] versionHeader = {
      0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00
    };
    byte[] versionRawBytes = null;

    if (version.length() > VERSION_BYTES) version = version.substring(0, VERSION_BYTES);

    try {
      versionRawBytes = version.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException("wtf, your JVM doesnt support utf-8? " + e.getMessage());
    }

    System.arraycopy(versionRawBytes, 0, versionHeader, 0, versionRawBytes.length);

    FileInputStream fileInputStream = null;
    Signature signature = null;
    SequenceInputStream bytesToSignInputStream = null;
    ByteArrayInputStream versionHeaderInputStream = null;

    try {
      fileInputStream = new FileInputStream(inputFile);
      versionHeaderInputStream = new ByteArrayInputStream(versionHeader);
      bytesToSignInputStream = new SequenceInputStream(versionHeaderInputStream, fileInputStream);
      signature = _context.dsa().sign(bytesToSignInputStream, signingPrivateKey);

    } catch (Exception e) {
      if (_log.shouldLog(Log.ERROR)) _log.error("Error signing", e);

      return null;
    } finally {
      if (bytesToSignInputStream != null)
        try {
          bytesToSignInputStream.close();
        } catch (IOException ioe) {
        }

      fileInputStream = null;
    }

    FileOutputStream fileOutputStream = null;

    try {
      fileOutputStream = new FileOutputStream(signedFile);
      fileOutputStream.write(signature.getData());
      fileOutputStream.write(versionHeader);
      fileInputStream = new FileInputStream(inputFile);
      byte[] buffer = new byte[1024];
      int bytesRead = 0;
      while ((bytesRead = fileInputStream.read(buffer)) != -1)
        fileOutputStream.write(buffer, 0, bytesRead);
      fileOutputStream.close();
    } catch (IOException ioe) {
      if (_log.shouldLog(Log.WARN))
        _log.log(Log.WARN, "Error writing signed file " + signedFile, ioe);

      return null;
    } finally {
      if (fileInputStream != null)
        try {
          fileInputStream.close();
        } catch (IOException ioe) {
        }

      if (fileOutputStream != null)
        try {
          fileOutputStream.close();
        } catch (IOException ioe) {
        }
    }

    return signature;
  }