Search in sources :

Example 46 with DataFormatException

use of net.i2p.data.DataFormatException in project i2p.i2p by i2p.

the class CreateRouterInfoJob method createRouterInfo.

/**
 *  Writes 6 files: router.info (standard RI format),
 *  router.keys.dat, and 4 individual key files under keyBackup/
 *
 *  router.keys.dat file format: This is the
 *  same "eepPriv.dat" format used by the client code,
 *  as documented in PrivateKeyFile.
 *
 *  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();
        // set or overwrite old random keys
        Map<String, String> map = new HashMap<String, String>(2);
        byte[] rk = new byte[32];
        getContext().random().nextBytes(rk);
        map.put(Router.PROP_IB_RANDOM_KEY, Base64.encode(rk));
        getContext().random().nextBytes(rk);
        map.put(Router.PROP_OB_RANDOM_KEY, Base64.encode(rk));
        getContext().router().saveConfig(map, null);
        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;
}
Also used : PrivateKey(net.i2p.data.PrivateKey) SigningPrivateKey(net.i2p.data.SigningPrivateKey) HashMap(java.util.HashMap) RouterInfo(net.i2p.data.router.RouterInfo) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) BufferedOutputStream(java.io.BufferedOutputStream) OutputStream(java.io.OutputStream) Properties(java.util.Properties) SimpleDataStructure(net.i2p.data.SimpleDataStructure) BufferedOutputStream(java.io.BufferedOutputStream) SigningPublicKey(net.i2p.data.SigningPublicKey) SigningPublicKey(net.i2p.data.SigningPublicKey) PublicKey(net.i2p.data.PublicKey) RouterIdentity(net.i2p.data.router.RouterIdentity) GeneralSecurityException(java.security.GeneralSecurityException) PrivateKeyFile(net.i2p.data.PrivateKeyFile) IOException(java.io.IOException) SigType(net.i2p.crypto.SigType) SigningPrivateKey(net.i2p.data.SigningPrivateKey) DataFormatException(net.i2p.data.DataFormatException) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) PrivateKeyFile(net.i2p.data.PrivateKeyFile) File(java.io.File) Certificate(net.i2p.data.Certificate) KeyCertificate(net.i2p.data.KeyCertificate)

Example 47 with DataFormatException

use of net.i2p.data.DataFormatException in project i2p.i2p by i2p.

the class LoadRouterInfoJob method loadRouterInfo.

/**
 *  Loads router.info and either router.keys.dat or router.keys.
 *
 *  See CreateRouterInfoJob for file formats
 */
private void loadRouterInfo() {
    RouterInfo info = null;
    File rif = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME);
    boolean infoExists = rif.exists();
    File rkf = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS_FILENAME);
    boolean keysExist = rkf.exists();
    File rkf2 = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME);
    boolean keys2Exist = rkf2.exists();
    InputStream fis1 = null;
    try {
        // so pretend the RI isn't there if there is no keyfile
        if (infoExists && (keys2Exist || keysExist)) {
            fis1 = new BufferedInputStream(new FileInputStream(rif));
            info = new RouterInfo();
            info.readBytes(fis1);
            // Catch this here before it all gets worse
            if (!info.isValid())
                throw new DataFormatException("Our RouterInfo has a bad signature");
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Reading in routerInfo from " + rif.getAbsolutePath() + " and it has " + info.getAddresses().size() + " addresses");
            // don't reuse if family name changed
            if (DataHelper.eq(info.getOption(FamilyKeyCrypto.OPT_NAME), getContext().getProperty(FamilyKeyCrypto.PROP_FAMILY_NAME))) {
                _us = info;
            } else {
                _log.logAlways(Log.WARN, "NetDb family name changed");
            }
        }
        if (keys2Exist || keysExist) {
            KeyData kd = readKeyData(rkf, rkf2);
            PublicKey pubkey = kd.routerIdentity.getPublicKey();
            SigningPublicKey signingPubKey = kd.routerIdentity.getSigningPublicKey();
            PrivateKey privkey = kd.privateKey;
            SigningPrivateKey signingPrivKey = kd.signingPrivateKey;
            SigType stype = signingPubKey.getType();
            // check if the sigtype config changed
            SigType cstype = CreateRouterInfoJob.getSigTypeConfig(getContext());
            boolean sigTypeChanged = stype != cstype;
            if (sigTypeChanged && getContext().getProperty(CreateRouterInfoJob.PROP_ROUTER_SIGTYPE) == null) {
                // TODO reduce to ~3 (i.e. increase probability) in future release
                if (getContext().random().nextInt(4) > 0) {
                    sigTypeChanged = false;
                    if (_log.shouldWarn())
                        _log.warn("Deferring RI rekey from " + stype + " to " + cstype);
                }
            }
            if (sigTypeChanged || shouldRebuild(privkey)) {
                if (_us != null) {
                    Hash h = _us.getIdentity().getHash();
                    _log.logAlways(Log.WARN, "Deleting old router identity " + h.toBase64());
                    // the netdb hasn't started yet, but we want to delete the RI
                    File f = PersistentDataStore.getRouterInfoFile(getContext(), h);
                    f.delete();
                    // the banlist can be called at any time
                    getContext().banlist().banlistRouterForever(h, "Our previous identity");
                    _us = null;
                }
                if (sigTypeChanged)
                    _log.logAlways(Log.WARN, "Rebuilding RouterInfo with new signature type " + cstype);
                // windows... close before deleting
                if (fis1 != null) {
                    try {
                        fis1.close();
                    } catch (IOException ioe) {
                    }
                    fis1 = null;
                }
                rif.delete();
                rkf.delete();
                rkf2.delete();
                return;
            }
            getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
        }
    } catch (IOException ioe) {
        _log.log(Log.CRIT, "Error reading the router info from " + rif.getAbsolutePath() + " and the keys from " + rkf.getAbsolutePath(), ioe);
        _us = null;
        // windows... close before deleting
        if (fis1 != null) {
            try {
                fis1.close();
            } catch (IOException ioe2) {
            }
            fis1 = null;
        }
        rif.delete();
        rkf.delete();
        rkf2.delete();
    } catch (DataFormatException dfe) {
        _log.log(Log.CRIT, "Corrupt router info or keys at " + rif.getAbsolutePath() + " / " + rkf.getAbsolutePath(), dfe);
        _us = null;
        // windows... close before deleting
        if (fis1 != null) {
            try {
                fis1.close();
            } catch (IOException ioe) {
            }
            fis1 = null;
        }
        rif.delete();
        rkf.delete();
        rkf2.delete();
    } finally {
        if (fis1 != null)
            try {
                fis1.close();
            } catch (IOException ioe) {
            }
    }
}
Also used : SigningPublicKey(net.i2p.data.SigningPublicKey) PrivateKey(net.i2p.data.PrivateKey) SigningPrivateKey(net.i2p.data.SigningPrivateKey) RouterInfo(net.i2p.data.router.RouterInfo) BufferedInputStream(java.io.BufferedInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) SigningPublicKey(net.i2p.data.SigningPublicKey) PublicKey(net.i2p.data.PublicKey) IOException(java.io.IOException) Hash(net.i2p.data.Hash) FileInputStream(java.io.FileInputStream) SigType(net.i2p.crypto.SigType) SigningPrivateKey(net.i2p.data.SigningPrivateKey) DataFormatException(net.i2p.data.DataFormatException) BufferedInputStream(java.io.BufferedInputStream) File(java.io.File) RouterPrivateKeyFile(net.i2p.data.router.RouterPrivateKeyFile)

Example 48 with DataFormatException

use of net.i2p.data.DataFormatException in project i2p.i2p by i2p.

the class TunnelPeerSelector method selectExplicit.

/**
 *  For debugging, also possibly for restricted routes?
 *  Needs analysis and testing
 *  @return should always be false
 */
protected List<Hash> selectExplicit(TunnelPoolSettings settings, int length) {
    String peers = null;
    Properties opts = settings.getUnknownOptions();
    if (opts != null)
        peers = opts.getProperty("explicitPeers");
    if (peers == null)
        peers = ctx.getProperty("explicitPeers");
    List<Hash> rv = new ArrayList<Hash>();
    StringTokenizer tok = new StringTokenizer(peers, ",");
    while (tok.hasMoreTokens()) {
        String peerStr = tok.nextToken();
        Hash peer = new Hash();
        try {
            peer.fromBase64(peerStr);
            if (ctx.profileOrganizer().isSelectable(peer)) {
                rv.add(peer);
            } else {
                if (log.shouldLog(Log.DEBUG))
                    log.debug("Explicit peer is not selectable: " + peerStr);
            }
        } catch (DataFormatException dfe) {
            if (log.shouldLog(Log.ERROR))
                log.error("Explicit peer is improperly formatted (" + peerStr + ")", dfe);
        }
    }
    int sz = rv.size();
    Collections.shuffle(rv, ctx.random());
    while (rv.size() > length) rv.remove(0);
    if (log.shouldLog(Log.INFO)) {
        StringBuilder buf = new StringBuilder();
        if (settings.getDestinationNickname() != null)
            buf.append("peers for ").append(settings.getDestinationNickname());
        else if (settings.getDestination() != null)
            buf.append("peers for ").append(settings.getDestination().toBase64());
        else
            buf.append("peers for exploratory ");
        if (settings.isInbound())
            buf.append(" inbound");
        else
            buf.append(" outbound");
        buf.append(" peers: ").append(rv);
        buf.append(", out of ").append(sz).append(" (not including self)");
        log.info(buf.toString());
    }
    if (settings.isInbound())
        rv.add(0, ctx.routerHash());
    else
        rv.add(ctx.routerHash());
    return rv;
}
Also used : StringTokenizer(java.util.StringTokenizer) DataFormatException(net.i2p.data.DataFormatException) ArrayList(java.util.ArrayList) Properties(java.util.Properties) Hash(net.i2p.data.Hash)

Example 49 with DataFormatException

use of net.i2p.data.DataFormatException in project i2p.i2p by i2p.

the class BuildMessageProcessor method decrypt.

/**
 * Decrypt the record targetting us, encrypting all of the other records with the included
 * reply key and IV.  The original, encrypted record targetting us is removed from the request
 * message (so that the reply can be placed in that position after going through the decrypted
 * request record).
 *
 * Note that this layer-decrypts the build records in-place.
 * Do not call this more than once for a given message.
 *
 * @return the current hop's decrypted record or null on failure
 */
public BuildRequestRecord decrypt(TunnelBuildMessage msg, Hash ourHash, PrivateKey privKey) {
    BuildRequestRecord rv = null;
    int ourHop = -1;
    long beforeActualDecrypt = 0;
    long afterActualDecrypt = 0;
    byte[] ourHashData = ourHash.getData();
    long beforeLoop = System.currentTimeMillis();
    for (int i = 0; i < msg.getRecordCount(); i++) {
        EncryptedBuildRecord rec = msg.getRecord(i);
        int len = BuildRequestRecord.PEER_SIZE;
        boolean eq = DataHelper.eq(ourHashData, 0, rec.getData(), 0, len);
        if (eq) {
            beforeActualDecrypt = System.currentTimeMillis();
            try {
                rv = new BuildRequestRecord(ctx, privKey, rec);
                afterActualDecrypt = System.currentTimeMillis();
                // i2pd bug
                boolean isBad = SessionKey.INVALID_KEY.equals(rv.readReplyKey());
                if (isBad) {
                    if (log.shouldLog(Log.WARN))
                        log.warn(msg.getUniqueId() + ": Bad reply key: " + rv);
                    ctx.statManager().addRateData("tunnel.buildRequestBadReplyKey", 1);
                    return null;
                }
                // The spec says to feed the 32-byte AES-256 reply key into the Bloom filter.
                // But we were using the first 32 bytes of the encrypted reply.
                // Fixed in 0.9.24
                boolean isDup = _filter.add(rv.getData(), BuildRequestRecord.OFF_REPLY_KEY, 32);
                if (isDup) {
                    if (log.shouldLog(Log.WARN))
                        log.warn(msg.getUniqueId() + ": Dup record: " + rv);
                    ctx.statManager().addRateData("tunnel.buildRequestDup", 1);
                    return null;
                }
                if (log.shouldLog(Log.DEBUG))
                    log.debug(msg.getUniqueId() + ": Matching record: " + rv);
                ourHop = i;
                // TODO should we keep looking for a second match and fail if found?
                break;
            } catch (DataFormatException dfe) {
                if (log.shouldLog(Log.WARN))
                    log.warn(msg.getUniqueId() + ": Matching record decrypt failure", dfe);
                // out there with the same first 16 bytes, go around again
                continue;
            }
        }
    }
    if (rv == null) {
        // none of the records matched, b0rk
        if (log.shouldLog(Log.WARN))
            log.warn(msg.getUniqueId() + ": No matching record");
        return null;
    }
    long beforeEncrypt = System.currentTimeMillis();
    SessionKey replyKey = rv.readReplyKey();
    byte[] iv = rv.readReplyIV();
    for (int i = 0; i < msg.getRecordCount(); i++) {
        if (i != ourHop) {
            EncryptedBuildRecord data = msg.getRecord(i);
            // if (log.shouldLog(Log.DEBUG))
            // log.debug("Encrypting record " + i + "/? with replyKey " + replyKey.toBase64() + "/" + Base64.encode(iv));
            // encrypt in-place, corrupts SDS
            byte[] bytes = data.getData();
            ctx.aes().encrypt(bytes, 0, bytes, 0, replyKey, iv, 0, EncryptedBuildRecord.LENGTH);
        }
    }
    long afterEncrypt = System.currentTimeMillis();
    msg.setRecord(ourHop, null);
    if (afterEncrypt - beforeLoop > 1000) {
        if (log.shouldLog(Log.WARN))
            log.warn("Slow decryption, total=" + (afterEncrypt - beforeLoop) + " looping=" + (beforeEncrypt - beforeLoop) + " decrypt=" + (afterActualDecrypt - beforeActualDecrypt) + " encrypt=" + (afterEncrypt - beforeEncrypt));
    }
    return rv;
}
Also used : EncryptedBuildRecord(net.i2p.data.i2np.EncryptedBuildRecord) DataFormatException(net.i2p.data.DataFormatException) SessionKey(net.i2p.data.SessionKey) BuildRequestRecord(net.i2p.data.i2np.BuildRequestRecord)

Example 50 with DataFormatException

use of net.i2p.data.DataFormatException in project i2p.i2p by i2p.

the class SSUDemo method storeMyInfo.

private static void storeMyInfo(RouterInfo info) {
    File infoDir = getInfoDir();
    if (!infoDir.exists())
        infoDir.mkdirs();
    FileOutputStream fos = null;
    File infoFile = new File(infoDir, info.getIdentity().calculateHash().toBase64());
    infoFile.deleteOnExit();
    try {
        fos = new FileOutputStream(infoFile);
        info.writeBytes(fos);
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } catch (DataFormatException dfe) {
        dfe.printStackTrace();
    } finally {
        if (fos != null)
            try {
                fos.close();
            } catch (IOException ioe) {
            }
    }
    System.out.println("Our info stored at: " + infoFile.getAbsolutePath());
}
Also used : DataFormatException(net.i2p.data.DataFormatException) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) File(java.io.File)

Aggregations

DataFormatException (net.i2p.data.DataFormatException)112 IOException (java.io.IOException)53 Destination (net.i2p.data.Destination)32 Properties (java.util.Properties)19 ByteArrayOutputStream (java.io.ByteArrayOutputStream)17 FileInputStream (java.io.FileInputStream)16 Hash (net.i2p.data.Hash)14 File (java.io.File)13 SigType (net.i2p.crypto.SigType)13 I2PSessionException (net.i2p.client.I2PSessionException)12 InputStream (java.io.InputStream)11 PrivateKey (net.i2p.data.PrivateKey)11 SigningPrivateKey (net.i2p.data.SigningPrivateKey)11 SigningPublicKey (net.i2p.data.SigningPublicKey)11 RouterInfo (net.i2p.data.router.RouterInfo)11 Signature (net.i2p.data.Signature)10 FileOutputStream (java.io.FileOutputStream)8 InterruptedIOException (java.io.InterruptedIOException)8 HashMap (java.util.HashMap)8 PublicKey (net.i2p.data.PublicKey)8