Search in sources :

Example 41 with SigType

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

the class SAMv3Handler method execSessionMessage.

/* Parse and execute a SESSION message */
@Override
protected boolean execSessionMessage(String opcode, Properties props) {
    String dest = "BUG!";
    boolean ok = false;
    String nick = (String) props.remove("ID");
    if (nick == null)
        return writeString(SESSION_ERROR, "ID not specified");
    String style = (String) props.remove("STYLE");
    if (style == null && !opcode.equals("REMOVE"))
        return writeString(SESSION_ERROR, "No SESSION STYLE specified");
    try {
        if (opcode.equals("CREATE")) {
            if ((this.getRawSession() != null) || (this.getDatagramSession() != null) || (this.getStreamSession() != null)) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Trying to create a session, but one still exists");
                return writeString(SESSION_ERROR, "Session already exists");
            }
            if (props.isEmpty()) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("No parameters specified in SESSION CREATE message");
                return writeString(SESSION_ERROR, "No parameters for SESSION CREATE");
            }
            dest = (String) props.remove("DESTINATION");
            if (dest == null) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("SESSION DESTINATION parameter not specified");
                return writeString(SESSION_ERROR, "DESTINATION not specified");
            }
            if (dest.equals("TRANSIENT")) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("TRANSIENT destination requested");
                String sigTypeStr = (String) props.remove("SIGNATURE_TYPE");
                SigType sigType;
                if (sigTypeStr != null) {
                    sigType = SigType.parseSigType(sigTypeStr);
                    if (sigType == null) {
                        return writeString(SESSION_ERROR, "SIGNATURE_TYPE " + sigTypeStr + " unsupported");
                    }
                } else {
                    sigType = SigType.DSA_SHA1;
                }
                ByteArrayOutputStream priv = new ByteArrayOutputStream(663);
                SAMUtils.genRandomKey(priv, null, sigType);
                dest = Base64.encode(priv.toByteArray());
            } else {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Custom destination specified [" + dest + "]");
                if (!SAMUtils.checkPrivateDestination(dest))
                    return writeString("SESSION STATUS RESULT=INVALID_KEY\n");
            }
            // Unconditionally override what the client may have set
            // (iMule sets BestEffort) as None is more efficient
            // and the client has no way to access delivery notifications
            i2cpProps.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
            i2cpProps.setProperty("i2cp.fastReceive", "true");
            // Record the session in the database sSessionsHash
            Properties allProps = new Properties();
            allProps.putAll(i2cpProps);
            allProps.putAll(props);
            if (style.equals("MASTER")) {
                // We must put these here, as SessionRecord.getProps() makes a copy,
                // and the socket manager is instantiated in the
                // SAMStreamSession constructor.
                allProps.setProperty("i2p.streaming.enforceProtocol", "true");
                allProps.setProperty("i2cp.dontPublishLeaseSet", "false");
            }
            try {
                sSessionsHash.put(nick, new SessionRecord(dest, allProps, this));
            } catch (SessionsDB.ExistingIdException e) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("SESSION ID parameter already in use");
                return writeString("SESSION STATUS RESULT=DUPLICATED_ID\n");
            } catch (SessionsDB.ExistingDestException e) {
                return writeString("SESSION STATUS RESULT=DUPLICATED_DEST\n");
            }
            if (style.equals("RAW")) {
                SAMv3DatagramServer dgs = bridge.getV3DatagramServer(props);
                SAMv3RawSession v3 = new SAMv3RawSession(nick, dgs);
                rawSession = v3;
                this.session = v3;
                v3.start();
            } else if (style.equals("DATAGRAM")) {
                SAMv3DatagramServer dgs = bridge.getV3DatagramServer(props);
                SAMv3DatagramSession v3 = new SAMv3DatagramSession(nick, dgs);
                datagramSession = v3;
                this.session = v3;
                v3.start();
            } else if (style.equals("STREAM")) {
                SAMv3StreamSession v3 = newSAMStreamSession(nick);
                streamSession = v3;
                this.session = v3;
                v3.start();
            } else if (style.equals("MASTER")) {
                SAMv3DatagramServer dgs = bridge.getV3DatagramServer(props);
                MasterSession v3 = new MasterSession(nick, dgs, this, allProps);
                streamSession = v3;
                datagramSession = v3;
                rawSession = v3;
                this.session = v3;
                v3.start();
            } else {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Unrecognized SESSION STYLE: \"" + style + "\"");
                return writeString(SESSION_ERROR, "Unrecognized SESSION STYLE");
            }
            ok = true;
            return writeString("SESSION STATUS RESULT=OK DESTINATION=" + dest + "\n");
        } else if (opcode.equals("ADD") || opcode.equals("REMOVE")) {
            // prevent trouble in finally block
            ok = true;
            if (streamSession == null || datagramSession == null || rawSession == null)
                return writeString(SESSION_ERROR, "Not a MASTER session");
            MasterSession msess = (MasterSession) session;
            String msg;
            if (opcode.equals("ADD")) {
                msg = msess.add(nick, style, props);
            } else {
                msg = msess.remove(nick, props);
            }
            if (msg == null)
                return writeString("SESSION STATUS RESULT=OK ID=\"" + nick + '"', opcode + ' ' + nick);
            else
                return writeString(SESSION_ERROR + " ID=\"" + nick + '"', msg);
        } else {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Unrecognized SESSION message opcode: \"" + opcode + "\"");
            return writeString(SESSION_ERROR, "Unrecognized opcode");
        }
    } catch (DataFormatException e) {
        _log.error("Invalid SAM destination specified", e);
        return writeString("SESSION STATUS RESULT=INVALID_KEY", e.getMessage());
    } catch (I2PSessionException e) {
        _log.error("Failed to start SAM session", e);
        return writeString(SESSION_ERROR, e.getMessage());
    } catch (SAMException e) {
        _log.error("Failed to start SAM session", e);
        return writeString(SESSION_ERROR, e.getMessage());
    } catch (IOException e) {
        _log.error("Failed to start SAM session", e);
        return writeString(SESSION_ERROR, e.getMessage());
    } finally {
        // unregister the session if it has not been created
        if (!ok && nick != null) {
            sSessionsHash.del(nick);
            session = null;
        }
    }
}
Also used : ByteArrayOutputStream(java.io.ByteArrayOutputStream) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) Properties(java.util.Properties) SigType(net.i2p.crypto.SigType) DataFormatException(net.i2p.data.DataFormatException) I2PSessionException(net.i2p.client.I2PSessionException)

Example 42 with SigType

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

the class HostTxtEntry method hasValidSig.

/**
 * Verify with the dest public key using the "sig" property
 */
public boolean hasValidSig() {
    if (props == null || name == null || dest == null)
        return false;
    if (!isValidated) {
        isValidated = true;
        StringWriter buf = new StringWriter(1024);
        String sig = props.getProperty(PROP_SIG);
        if (sig == null)
            return false;
        buf.append(name);
        buf.append(KV_SEPARATOR);
        buf.append(dest);
        try {
            writeProps(buf, true, false);
        } catch (IOException ioe) {
            // won't happen
            return false;
        }
        byte[] sdata = Base64.decode(sig);
        if (sdata == null)
            return false;
        Destination d;
        try {
            d = new Destination(dest);
        } 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;
        }
        isValid = DSAEngine.getInstance().verifySignature(s, DataHelper.getUTF8(buf.toString()), spk);
    }
    return isValid;
}
Also used : Destination(net.i2p.data.Destination) SigningPublicKey(net.i2p.data.SigningPublicKey) DataFormatException(net.i2p.data.DataFormatException) StringWriter(java.io.StringWriter) Signature(net.i2p.data.Signature) IOException(java.io.IOException) SigType(net.i2p.crypto.SigType)

Example 43 with SigType

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

the class HostTxtEntry method hasValidInnerSig.

/**
 * 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;
}
Also used : Destination(net.i2p.data.Destination) SigningPublicKey(net.i2p.data.SigningPublicKey) DataFormatException(net.i2p.data.DataFormatException) StringWriter(java.io.StringWriter) Signature(net.i2p.data.Signature) IOException(java.io.IOException) SigType(net.i2p.crypto.SigType)

Example 44 with SigType

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

the class RequestLeaseSetMessageHandler method signLeaseSet.

/**
 *  Finish creating and signing the new LeaseSet
 *  @since 0.9.7
 */
protected synchronized void signLeaseSet(LeaseSet leaseSet, I2PSessionImpl session) {
    Destination dest = session.getMyDestination();
    // also, if this session is connected to multiple routers, include other leases here
    leaseSet.setDestination(dest);
    // reuse the old keys for the client
    LeaseInfo li = _existingLeaseSets.get(dest);
    if (li == null) {
        // [enctype:]b64 of private key
        String spk = session.getOptions().getProperty("i2cp.leaseSetPrivateKey");
        // [sigtype:]b64 of private key
        String sspk = session.getOptions().getProperty("i2cp.leaseSetSigningPrivateKey");
        PrivateKey privKey = null;
        SigningPrivateKey signingPrivKey = null;
        if (spk != null && sspk != null) {
            boolean useOldKeys = true;
            int colon = sspk.indexOf(':');
            SigType type = dest.getSigType();
            if (colon > 0) {
                String stype = sspk.substring(0, colon);
                SigType t = SigType.parseSigType(stype);
                if (t == type)
                    sspk = sspk.substring(colon + 1);
                else
                    useOldKeys = false;
            }
            colon = spk.indexOf(':');
            // just ignore for now, no other types supported
            if (colon >= 0)
                spk = spk.substring(colon + 1);
            if (useOldKeys) {
                try {
                    signingPrivKey = new SigningPrivateKey(type);
                    signingPrivKey.fromBase64(sspk);
                } catch (DataFormatException iae) {
                    useOldKeys = false;
                    signingPrivKey = null;
                }
            }
            if (useOldKeys) {
                try {
                    privKey = new PrivateKey();
                    privKey.fromBase64(spk);
                } catch (DataFormatException iae) {
                    privKey = null;
                }
            }
        }
        if (privKey == null && !_existingLeaseSets.isEmpty()) {
            // look for keypair from another dest using same pubkey
            PublicKey pk = dest.getPublicKey();
            for (Map.Entry<Destination, LeaseInfo> e : _existingLeaseSets.entrySet()) {
                if (pk.equals(e.getKey().getPublicKey())) {
                    privKey = e.getValue().getPrivateKey();
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Creating new leaseInfo keys for " + dest + " with private key from " + e.getKey());
                    break;
                }
            }
        }
        if (privKey != null) {
            if (signingPrivKey != null) {
                li = new LeaseInfo(privKey, signingPrivKey);
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Creating new leaseInfo keys for " + dest + " WITH configured private keys");
            } else {
                li = new LeaseInfo(privKey, dest);
            }
        } else {
            li = new LeaseInfo(dest);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Creating new leaseInfo keys for " + dest + " without configured private keys");
        }
        _existingLeaseSets.put(dest, li);
    } else {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Caching the old leaseInfo keys for " + dest);
    }
    leaseSet.setEncryptionKey(li.getPublicKey());
    leaseSet.setSigningKey(li.getSigningPublicKey());
    // SubSession options aren't updated via the gui, so use the primary options
    Properties opts;
    if (session instanceof SubSession)
        opts = ((SubSession) session).getPrimaryOptions();
    else
        opts = session.getOptions();
    boolean encrypt = Boolean.parseBoolean(opts.getProperty("i2cp.encryptLeaseSet"));
    String sk = opts.getProperty("i2cp.leaseSetKey");
    Hash h = dest.calculateHash();
    if (encrypt && sk != null) {
        SessionKey key = new SessionKey();
        try {
            key.fromBase64(sk);
            leaseSet.encrypt(key);
            _context.keyRing().put(h, key);
        } catch (DataFormatException dfe) {
            _log.error("Bad leaseset key: " + sk);
            _context.keyRing().remove(h);
        }
    } else {
        _context.keyRing().remove(h);
    }
    try {
        leaseSet.sign(session.getPrivateKey());
        // Workaround for unparsable serialized signing private key for revocation
        // Send him a dummy DSA_SHA1 private key since it's unused anyway
        // See CreateLeaseSetMessage.doReadMessage()
        SigningPrivateKey spk = li.getSigningPrivateKey();
        if (!_context.isRouterContext() && spk.getType() != SigType.DSA_SHA1) {
            byte[] dummy = new byte[SigningPrivateKey.KEYSIZE_BYTES];
            _context.random().nextBytes(dummy);
            spk = new SigningPrivateKey(dummy);
        }
        session.getProducer().createLeaseSet(session, leaseSet, spk, li.getPrivateKey());
        session.setLeaseSet(leaseSet);
    } catch (DataFormatException dfe) {
        session.propogateError("Error signing the leaseSet", dfe);
    } catch (I2PSessionException ise) {
        if (session.isClosed()) {
            // race, closed while signing leaseset
            // EOFExceptions are logged at WARN level (see I2PSessionImpl.propogateError())
            // so the user won't see this
            EOFException eof = new EOFException("Session closed while signing leaseset");
            eof.initCause(ise);
            session.propogateError("Session closed while signing leaseset", eof);
        } else {
            session.propogateError("Error sending the signed leaseSet", ise);
        }
    }
}
Also used : Destination(net.i2p.data.Destination) PrivateKey(net.i2p.data.PrivateKey) SigningPrivateKey(net.i2p.data.SigningPrivateKey) SigningPublicKey(net.i2p.data.SigningPublicKey) PublicKey(net.i2p.data.PublicKey) Properties(java.util.Properties) Hash(net.i2p.data.Hash) SigType(net.i2p.crypto.SigType) SigningPrivateKey(net.i2p.data.SigningPrivateKey) DataFormatException(net.i2p.data.DataFormatException) SessionKey(net.i2p.data.SessionKey) EOFException(java.io.EOFException) I2PSessionException(net.i2p.client.I2PSessionException) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Map(java.util.Map)

Aggregations

SigType (net.i2p.crypto.SigType)44 IOException (java.io.IOException)18 DataFormatException (net.i2p.data.DataFormatException)15 Signature (net.i2p.data.Signature)14 Destination (net.i2p.data.Destination)12 SigningPublicKey (net.i2p.data.SigningPublicKey)11 File (java.io.File)6 GeneralSecurityException (java.security.GeneralSecurityException)6 Properties (java.util.Properties)6 Hash (net.i2p.data.Hash)6 PrivateKey (net.i2p.data.PrivateKey)6 SigningPrivateKey (net.i2p.data.SigningPrivateKey)6 PublicKey (net.i2p.data.PublicKey)5 SimpleDataStructure (net.i2p.data.SimpleDataStructure)5 RouterInfo (net.i2p.data.router.RouterInfo)5 ByteArrayOutputStream (java.io.ByteArrayOutputStream)4 I2PException (net.i2p.I2PException)4 RouterIdentity (net.i2p.data.router.RouterIdentity)4 Log (net.i2p.util.Log)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3