Beispiel #1
0
  /** @return success */
  private static final boolean genKeysCLI(String publicKeyFile, String privateKeyFile) {
    FileOutputStream fileOutputStream = null;

    I2PAppContext context = I2PAppContext.getGlobalContext();
    try {
      Object signingKeypair[] = context.keyGenerator().generateSigningKeypair();
      SigningPublicKey signingPublicKey = (SigningPublicKey) signingKeypair[0];
      SigningPrivateKey signingPrivateKey = (SigningPrivateKey) signingKeypair[1];

      fileOutputStream = new FileOutputStream(publicKeyFile);
      signingPublicKey.writeBytes(fileOutputStream);
      fileOutputStream.close();
      fileOutputStream = null;

      fileOutputStream = new FileOutputStream(privateKeyFile);
      signingPrivateKey.writeBytes(fileOutputStream);

      System.out.println("\r\nPrivate key written to: " + privateKeyFile);
      System.out.println("Public key written to: " + publicKeyFile);
      System.out.println("\r\nPublic key: " + signingPublicKey.toBase64() + "\r\n");
    } catch (Exception e) {
      System.err.println("Error writing keys:");
      e.printStackTrace();
      return false;
    } finally {
      if (fileOutputStream != null)
        try {
          fileOutputStream.close();
        } catch (IOException ioe) {
        }
    }
    return true;
  }
Beispiel #2
0
  /**
   * Verifies the DSA signature of a signed update file.
   *
   * @param signedFile The signed update file to check.
   * @param publicKeyFile A file containing the public key to use for verification.
   * @return <code>true</code> if the file has a valid signature, otherwise <code>false</code>.
   */
  public boolean verify(String signedFile, String publicKeyFile) {
    SigningPublicKey signingPublicKey = new SigningPublicKey();
    FileInputStream fileInputStream = null;

    try {
      fileInputStream = new FileInputStream(signedFile);
      signingPublicKey.readBytes(fileInputStream);
    } catch (IOException ioe) {
      if (_log.shouldLog(Log.WARN)) _log.warn("Unable to load the signature", ioe);

      return false;
    } catch (DataFormatException dfe) {
      if (_log.shouldLog(Log.WARN)) _log.warn("Unable to load the signature", dfe);

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

    return verify(new File(signedFile), signingPublicKey);
  }
Beispiel #3
0
  /**
   * Fetches the trusted keys for the current instance. We could sort it but don't bother.
   *
   * @return A <code>String</code> containing the trusted keys, delimited by CR LF line breaks.
   */
  public String getTrustedKeysString() {
    StringBuilder buf = new StringBuilder(1024);
    for (SigningPublicKey spk : _trustedKeys.keySet()) {
      // If something already buffered, first add line break.
      if (buf.length() > 0) buf.append("\r\n");
      buf.append(spk.toBase64());
    }

    return buf.toString();
  }
Beispiel #4
0
 /**
  * Do we know about the following key?
  *
  * @since 0.7.12
  */
 public boolean haveKey(String key) {
   if (key.length() != KEYSIZE_B64_BYTES) return false;
   SigningPublicKey signingPublicKey = new SigningPublicKey();
   try {
     signingPublicKey.fromBase64(key);
   } catch (DataFormatException dfe) {
     return false;
   }
   return _trustedKeys.containsKey(signingPublicKey);
 }
Beispiel #5
0
 /** Verify with the "olddest" property's public key using the "oldsig" property */
 public boolean hasValidInnerSig() {
   if (props == null || name == null || dest == null) return false;
   boolean rv = false;
   // don't cache result
   if (true) {
     StringWriter buf = new StringWriter(1024);
     String sig = props.getProperty(PROP_OLDSIG);
     String olddest = props.getProperty(PROP_OLDDEST);
     if (sig == null || olddest == null) return false;
     buf.append(name);
     buf.append(KV_SEPARATOR);
     buf.append(dest);
     try {
       writeProps(buf, true, true);
     } catch (IOException ioe) {
       // won't happen
       return false;
     }
     byte[] sdata = Base64.decode(sig);
     if (sdata == null) return false;
     Destination d;
     try {
       d = new Destination(olddest);
     } catch (DataFormatException dfe) {
       return false;
     }
     SigningPublicKey spk = d.getSigningPublicKey();
     SigType type = spk.getType();
     if (type == null) return false;
     Signature s;
     try {
       s = new Signature(type, sdata);
     } catch (IllegalArgumentException iae) {
       return false;
     }
     rv = DSAEngine.getInstance().verifySignature(s, DataHelper.getUTF8(buf.toString()), spk);
   }
   return rv;
 }
Beispiel #6
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;
    }
  }
Beispiel #7
0
 /**
  * Duplicate keys or names rejected, except that duplicate empty names are allowed
  *
  * @param key 172 character base64 string
  * @param name non-null but "" ok
  * @since 0.7.12
  * @return true if successful
  */
 public boolean addKey(String key, String name) {
   if (_log.shouldLog(Log.DEBUG)) _log.debug("Adding " + name + ": " + key);
   SigningPublicKey signingPublicKey = new SigningPublicKey();
   try {
     // fromBase64() will throw a DFE if length is not right
     signingPublicKey.fromBase64(key);
   } catch (DataFormatException dfe) {
     _log.error("Invalid signing key for " + name + " : " + key, dfe);
     return false;
   }
   String oldName = _trustedKeys.get(signingPublicKey);
   // already there?
   if (name.equals(oldName)) return true;
   if (oldName != null && !oldName.equals("")) {
     _log.error("Key for " + name + " already stored for different name " + oldName + " : " + key);
     return false;
   }
   if ((!name.equals("")) && _trustedKeys.containsValue(name)) {
     _log.error("Key mismatch for " + name + ", spoof attempt? : " + key);
     return false;
   }
   _trustedKeys.put(signingPublicKey, name);
   return true;
 }
Beispiel #8
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;
 }
  /**
   * Writes 6 files: router.info (standard RI format), router.keys.dat, and 4 individual key files
   * under keyBackup/
   *
   * <p>router.keys.dat file format: This is the same "eepPriv.dat" format used by the client code,
   * as documented in PrivateKeyFile.
   *
   * <p>Old router.keys file format: Note that this is NOT the same "eepPriv.dat" format used by the
   * client code.
   *
   * <pre>
   *   - Private key (256 bytes)
   *   - Signing Private key (20 bytes)
   *   - Public key (256 bytes)
   *   - Signing Public key (128 bytes)
   *  Total 660 bytes
   * </pre>
   *
   * Caller must hold Router.routerInfoFileLock.
   */
  RouterInfo createRouterInfo() {
    SigType type = getSigTypeConfig(getContext());
    RouterInfo info = new RouterInfo();
    OutputStream fos1 = null;
    try {
      info.setAddresses(getContext().commSystem().createAddresses());
      // not necessary, in constructor
      // info.setPeers(new HashSet());
      info.setPublished(getCurrentPublishDate(getContext()));
      Object keypair[] = getContext().keyGenerator().generatePKIKeypair();
      PublicKey pubkey = (PublicKey) keypair[0];
      PrivateKey privkey = (PrivateKey) keypair[1];
      SimpleDataStructure signingKeypair[] = getContext().keyGenerator().generateSigningKeys(type);
      SigningPublicKey signingPubKey = (SigningPublicKey) signingKeypair[0];
      SigningPrivateKey signingPrivKey = (SigningPrivateKey) signingKeypair[1];
      RouterIdentity ident = new RouterIdentity();
      Certificate cert = createCertificate(getContext(), signingPubKey);
      ident.setCertificate(cert);
      ident.setPublicKey(pubkey);
      ident.setSigningPublicKey(signingPubKey);
      byte[] padding;
      int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
      if (padLen > 0) {
        padding = new byte[padLen];
        getContext().random().nextBytes(padding);
        ident.setPadding(padding);
      } else {
        padding = null;
      }
      info.setIdentity(ident);
      Properties stats = getContext().statPublisher().publishStatistics(ident.getHash());
      info.setOptions(stats);

      info.sign(signingPrivKey);

      if (!info.isValid())
        throw new DataFormatException("RouterInfo we just built is invalid: " + info);

      // remove router.keys
      (new File(getContext().getRouterDir(), KEYS_FILENAME)).delete();

      // write router.info
      File ifile = new File(getContext().getRouterDir(), INFO_FILENAME);
      fos1 = new BufferedOutputStream(new SecureFileOutputStream(ifile));
      info.writeBytes(fos1);

      // write router.keys.dat
      File kfile = new File(getContext().getRouterDir(), KEYS2_FILENAME);
      PrivateKeyFile pkf =
          new PrivateKeyFile(kfile, pubkey, signingPubKey, cert, privkey, signingPrivKey, padding);
      pkf.write();

      getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);

      if (_log.shouldLog(Log.INFO))
        _log.info(
            "Router info created and stored at "
                + ifile.getAbsolutePath()
                + " with private keys stored at "
                + kfile.getAbsolutePath()
                + " ["
                + info
                + "]");
      getContext().router().eventLog().addEvent(EventLog.REKEYED, ident.calculateHash().toBase64());
    } catch (GeneralSecurityException gse) {
      _log.log(Log.CRIT, "Error building the new router information", gse);
    } catch (DataFormatException dfe) {
      _log.log(Log.CRIT, "Error building the new router information", dfe);
    } catch (IOException ioe) {
      _log.log(Log.CRIT, "Error writing out the new router information", ioe);
    } finally {
      if (fos1 != null)
        try {
          fos1.close();
        } catch (IOException ioe) {
        }
    }
    return info;
  }
 /**
  * Only called at startup via LoadRouterInfoJob and RebuildRouterInfoJob. Not called by periodic
  * RepublishLocalRouterInfoJob. We don't want to change the cert on the fly as it changes the
  * router hash. RouterInfo.isHidden() checks the capability, but RouterIdentity.isHidden() checks
  * the cert. There's no reason to ever add a hidden cert?
  *
  * @return the certificate for a new RouterInfo - probably a null cert.
  * @since 0.9.16 moved from Router
  */
 static Certificate createCertificate(RouterContext ctx, SigningPublicKey spk) {
   if (spk.getType() != SigType.DSA_SHA1) return new KeyCertificate(spk);
   if (ctx.getBooleanProperty(Router.PROP_HIDDEN))
     return new Certificate(Certificate.CERTIFICATE_TYPE_HIDDEN, null);
   return Certificate.NULL_CERT;
 }