Search in sources :

Example 11 with SessionKeyManager

use of net.i2p.crypto.SessionKeyManager in project i2p.i2p by i2p.

the class OutboundClientMessageOneShotJob method send.

/**
 * Send the message to the specified tunnel by creating a new garlic message containing
 * the (already created) payload clove as well as a new delivery status message.  This garlic
 * message is sent out one of our tunnels, destined for the lease (tunnel+router) specified, and the delivery
 * status message is targetting one of our free inbound tunnels as well.  We use a new
 * reply selector to keep an eye out for that delivery status message's token
 */
private void send() {
    synchronized (this) {
        if (_finished != Result.NONE) {
            if (_log.shouldLog(Log.WARN))
                _log.warn(OutboundClientMessageOneShotJob.this.getJobId() + ": SEND-AFTER-" + _finished);
            return;
        }
    }
    long now = getContext().clock().now();
    if (now >= _overallExpiration) {
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED);
        return;
    }
    _outTunnel = selectOutboundTunnel(_to);
    if (_outTunnel == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn(getJobId() + ": Could not find any outbound tunnels to send the payload through... this might take a while");
        getContext().statManager().addRateData("client.dispatchNoTunnels", now - _start);
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_NO_TUNNELS);
        return;
    }
    // boolean wantACK = _wantACK || existingTags <= 30 || getContext().random().nextInt(100) < 5;
    // what's the point of 5% random? possible improvements or replacements:
    // DONE (getNextLease() is called before this): wantACK if we changed their inbound lease (getNextLease() sets _wantACK)
    // DONE (selectOutboundTunnel() moved above here): wantACK if we changed our outbound tunnel (selectOutboundTunnel() sets _wantACK)
    // DONE (added new cache): wantACK if we haven't in last 1m (requires a new static cache probably)
    Long lastReplyRequestSent = _cache.lastReplyRequestCache.get(_hashPair);
    boolean shouldRequestReply = lastReplyRequestSent == null || lastReplyRequestSent.longValue() < now - REPLY_REQUEST_INTERVAL;
    int sendFlags = _clientMessage.getFlags();
    // Per-message flag > 0 overrides per-session option
    int tagsRequired = SendMessageOptions.getTagThreshold(sendFlags);
    boolean wantACK = _wantACK || shouldRequestReply || GarlicMessageBuilder.needsTags(getContext(), _leaseSet.getEncryptionKey(), _from.calculateHash(), tagsRequired);
    LeaseSet replyLeaseSet;
    // Per-message flag == false overrides session option which is default true
    String allow = _clientMessage.getSenderConfig().getOptions().getProperty(BUNDLE_REPLY_LEASESET);
    boolean allowLeaseBundle = SendMessageOptions.getSendLeaseSet(sendFlags) && (allow == null || Boolean.parseBoolean(allow));
    if (allowLeaseBundle) {
        // If we want an ack, bundle a leaseSet...
        // replyLeaseSet = getReplyLeaseSet(wantACK);
        // Only when necessary. We don't need to force.
        // ACKs find their own way back, they don't need a leaseset.
        replyLeaseSet = getReplyLeaseSet(false);
        // ... and vice versa  (so we know he got it)
        if (replyLeaseSet != null)
            wantACK = true;
    } else {
        replyLeaseSet = null;
    }
    long token;
    if (wantACK) {
        _cache.lastReplyRequestCache.put(_hashPair, Long.valueOf(now));
        token = getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE);
        _inTunnel = selectInboundTunnel();
    } else {
        token = -1;
    }
    PayloadGarlicConfig clove = buildClove();
    if (clove == null) {
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION);
        return;
    }
    // if (_log.shouldLog(Log.DEBUG))
    // _log.debug(getJobId() + ": Clove built to " + _toString);
    PublicKey key = _leaseSet.getEncryptionKey();
    SessionKey sessKey = new SessionKey();
    Set<SessionTag> tags = new HashSet<SessionTag>();
    // Per-message flag > 0 overrides per-session option
    int tagsToSend = SendMessageOptions.getTagsToSend(sendFlags);
    GarlicMessage msg = OutboundClientMessageJobHelper.createGarlicMessage(getContext(), token, _overallExpiration, key, clove, _from.calculateHash(), _to, _inTunnel, tagsToSend, tagsRequired, sessKey, tags, wantACK, replyLeaseSet);
    if (msg == null) {
        // we dont receive the reply? hmm...)
        if (_log.shouldLog(Log.WARN))
            _log.warn(getJobId() + ": Unable to create the garlic message (no tunnels left or too lagged) to " + _toString);
        getContext().statManager().addRateData("client.dispatchNoTunnels", now - _start);
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_NO_TUNNELS);
        return;
    }
    // if (_log.shouldLog(Log.DEBUG))
    // _log.debug(getJobId() + ": send() - token expected " + token + " to " + _toString);
    SendSuccessJob onReply = null;
    SendTimeoutJob onFail = null;
    ReplySelector selector = null;
    if (wantACK) {
        TagSetHandle tsh = null;
        if (!tags.isEmpty()) {
            SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_from.calculateHash());
            if (skm != null)
                tsh = skm.tagsDelivered(_leaseSet.getEncryptionKey(), sessKey, tags);
        }
        onReply = new SendSuccessJob(getContext(), sessKey, tsh);
        onFail = new SendTimeoutJob(getContext(), sessKey, tsh);
        long expiration = Math.max(_overallExpiration, _start + REPLY_TIMEOUT_MS_MIN);
        selector = new ReplySelector(token, expiration);
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug(getJobId() + ": Sending msg out " + _outTunnel.getSendTunnelId(0) + " to " + _toString + " at " + _lease.getTunnelId() + " on " + _lease.getGateway());
    DispatchJob dispatchJob = new DispatchJob(getContext(), msg, selector, onReply, onFail);
    // if (false) // dispatch may take 100+ms, so toss it in its own job
    // getContext().jobQueue().addJob(dispatchJob);
    // else
    dispatchJob.runJob();
    getContext().statManager().addRateData("client.dispatchPrepareTime", now - _start);
    if (!wantACK)
        getContext().statManager().addRateData("client.dispatchNoACK", 1);
}
Also used : PublicKey(net.i2p.data.PublicKey) SessionKeyManager(net.i2p.crypto.SessionKeyManager) TagSetHandle(net.i2p.crypto.TagSetHandle) LeaseSet(net.i2p.data.LeaseSet) SessionKey(net.i2p.data.SessionKey) GarlicMessage(net.i2p.data.i2np.GarlicMessage) SessionTag(net.i2p.data.SessionTag) HashSet(java.util.HashSet)

Example 12 with SessionKeyManager

use of net.i2p.crypto.SessionKeyManager in project i2p.i2p by i2p.

the class MessageWrapper method wrap.

/**
 *  Garlic wrap a message from a client or this router, destined for a router,
 *  to hide the contents from the OBEP.
 *  Caller must call acked() or fail() on the returned object.
 *
 *  @param from must be a local client with a session key manager,
 *              or null to use the router's session key manager
 *  @return null on encrypt failure
 */
static WrappedMessage wrap(RouterContext ctx, I2NPMessage m, Hash from, RouterInfo to) {
    PayloadGarlicConfig payload = new PayloadGarlicConfig();
    payload.setCertificate(Certificate.NULL_CERT);
    payload.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
    payload.setPayload(m);
    payload.setRecipient(to);
    payload.setDeliveryInstructions(DeliveryInstructions.LOCAL);
    payload.setExpiration(m.getMessageExpiration());
    SessionKeyManager skm;
    if (from != null)
        skm = ctx.clientManager().getClientSessionKeyManager(from);
    else
        skm = ctx.sessionKeyManager();
    if (skm == null)
        return null;
    SessionKey sentKey = new SessionKey();
    Set<SessionTag> sentTags = new HashSet<SessionTag>();
    GarlicMessage msg = GarlicMessageBuilder.buildMessage(ctx, payload, sentKey, sentTags, NETDB_TAGS_TO_DELIVER, NETDB_LOW_THRESHOLD, skm);
    if (msg == null)
        return null;
    TagSetHandle tsh = null;
    PublicKey sentTo = to.getIdentity().getPublicKey();
    if (!sentTags.isEmpty())
        tsh = skm.tagsDelivered(sentTo, sentKey, sentTags);
    // _log.debug("Sent to: " + to.getIdentity().getHash() + " with key: " + sentKey + " and tags: " + sentTags.size());
    return new WrappedMessage(msg, skm, sentTo, sentKey, tsh);
}
Also used : PayloadGarlicConfig(net.i2p.router.message.PayloadGarlicConfig) SessionKey(net.i2p.data.SessionKey) PublicKey(net.i2p.data.PublicKey) SessionKeyManager(net.i2p.crypto.SessionKeyManager) GarlicMessage(net.i2p.data.i2np.GarlicMessage) SessionTag(net.i2p.data.SessionTag) HashSet(java.util.HashSet) TagSetHandle(net.i2p.crypto.TagSetHandle)

Example 13 with SessionKeyManager

use of net.i2p.crypto.SessionKeyManager in project i2p.i2p-bote by i2p.

the class Util method decrypt.

/**
 * Decrypts data with an I2P private key
 * @throws DataFormatException
 */
public static byte[] decrypt(byte[] data, PrivateKey key) throws DataFormatException {
    I2PAppContext appContext = I2PAppContext.getGlobalContext();
    SessionKeyManager sessionKeyMgr = new net.i2p.crypto.SessionKeyManager(appContext) {
    };
    return appContext.elGamalAESEngine().decrypt(data, key, sessionKeyMgr);
}
Also used : I2PAppContext(net.i2p.I2PAppContext) SessionKeyManager(net.i2p.crypto.SessionKeyManager)

Aggregations

SessionKeyManager (net.i2p.crypto.SessionKeyManager)13 SessionKey (net.i2p.data.SessionKey)10 PublicKey (net.i2p.data.PublicKey)7 PrivateKey (net.i2p.data.PrivateKey)6 SessionTag (net.i2p.data.SessionTag)6 TagSetHandle (net.i2p.crypto.TagSetHandle)5 HashSet (java.util.HashSet)4 GarlicMessage (net.i2p.data.i2np.GarlicMessage)4 I2PAppContext (net.i2p.I2PAppContext)2 PayloadGarlicConfig (net.i2p.router.message.PayloadGarlicConfig)2 LeaseSet (net.i2p.data.LeaseSet)1 GarlicClove (net.i2p.data.i2np.GarlicClove)1 LeaseSetKeys (net.i2p.router.LeaseSetKeys)1 RemovableSingletonSet (net.i2p.router.util.RemovableSingletonSet)1