Search in sources :

Example 36 with SigType

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

the class Packet method verifySignature.

/**
 * Determine whether the signature on the data is valid.
 *
 * @param ctx Application context
 * @param from the Destination the data came from
 * @param buffer data to validate with signature
 * @return true if the signature exists and validates against the data,
 *         false otherwise.
 */
public boolean verifySignature(I2PAppContext ctx, Destination from, byte[] buffer) {
    if (!isFlagSet(FLAG_SIGNATURE_INCLUDED))
        return false;
    if (_optionSignature == null)
        return false;
    // prevent receiveNewSyn() ... !active ... sendReset() ... verifySignature ... NPE
    if (from == null)
        return false;
    int size = writtenSize();
    if (buffer == null)
        buffer = new byte[size];
    SigningPublicKey spk = from.getSigningPublicKey();
    SigType type = spk.getType();
    if (type == null) {
        Log l = ctx.logManager().getLog(Packet.class);
        if (l.shouldLog(Log.WARN))
            l.warn("Unknown sig type in " + from + " cannot verify " + toString());
        return false;
    }
    int written = writePacket(buffer, 0, type.getSigLen());
    if (written != size) {
        ctx.logManager().getLog(Packet.class).error("Written " + written + " size " + size + " for " + toString(), new Exception("moo"));
        return false;
    }
    // on a close or reset packet where we have a signature without a FROM
    if (type != _optionSignature.getType() && type.getSigLen() == _optionSignature.length())
        _optionSignature = new Signature(type, _optionSignature.getData());
    boolean ok = ctx.dsa().verifySignature(_optionSignature, buffer, 0, size, spk);
    if (!ok) {
        Log l = ctx.logManager().getLog(Packet.class);
        if (l.shouldLog(Log.WARN))
            l.warn("Signature failed on " + toString(), new Exception("moo"));
    // if (false) {
    // l.error(Base64.encode(buffer, 0, size));
    // l.error("Signature: " + Base64.encode(_optionSignature.getData()));
    // }
    }
    return ok;
}
Also used : SigningPublicKey(net.i2p.data.SigningPublicKey) Log(net.i2p.util.Log) Signature(net.i2p.data.Signature) SigType(net.i2p.crypto.SigType) DataFormatException(net.i2p.data.DataFormatException) IOException(java.io.IOException)

Example 37 with SigType

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

the class AddressBean method getSigType.

/**
 * Do this the easy way
 * @since 0.9.12
 */
public String getSigType() {
    // (4 / 3) * (pubkey length + signing key length)
    String cert = destination.substring(512);
    if (cert.equals("AAAA"))
        return _t("DSA 1024 bit");
    byte[] enc = Base64.decode(cert);
    if (enc == null)
        // shouldn't happen
        return "invalid";
    int type = enc[0] & 0xff;
    if (type != Certificate.CERTIFICATE_TYPE_KEY)
        return _t("DSA 1024 bit");
    int st = ((enc[3] & 0xff) << 8) | (enc[4] & 0xff);
    if (st == 0)
        return _t("DSA 1024 bit");
    SigType stype = SigType.getByCode(st);
    if (stype == null)
        return _t("Type {0}", st);
    return stype.toString();
}
Also used : SigType(net.i2p.crypto.SigType)

Example 38 with SigType

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

the class RouterInfo method readBytes.

/**
 *  If verifySig is true,
 *  this validates the signature while reading in,
 *  and throws a DataFormatException if the sig is invalid.
 *  This is faster than reserializing to validate later.
 *
 *  @throws IllegalStateException if RouterInfo was already read in
 *  @since 0.9
 */
public void readBytes(InputStream in, boolean verifySig) throws DataFormatException, IOException {
    if (_signature != null)
        throw new IllegalStateException();
    _identity = new RouterIdentity();
    _identity.readBytes(in);
    // can't set the digest until we know the sig type
    InputStream din;
    MessageDigest digest;
    if (verifySig) {
        SigType type = _identity.getSigningPublicKey().getType();
        if (type != SigType.EdDSA_SHA512_Ed25519) {
            // This won't work for EdDSA
            digest = _identity.getSigningPublicKey().getType().getDigestInstance();
            // TODO any better way?
            digest.update(_identity.toByteArray());
            din = new DigestInputStream(in, digest);
        } else {
            digest = null;
            din = in;
        }
    } else {
        digest = null;
        din = in;
    }
    // avoid thrashing objects
    // Date when = DataHelper.readDate(in);
    // if (when == null)
    // _published = 0;
    // else
    // _published = when.getTime();
    _published = DataHelper.readLong(din, 8);
    int numAddresses = (int) DataHelper.readLong(din, 1);
    for (int i = 0; i < numAddresses; i++) {
        RouterAddress address = new RouterAddress();
        address.readBytes(din);
        _addresses.add(address);
    }
    int numPeers = (int) DataHelper.readLong(din, 1);
    if (numPeers == 0) {
        _peers = null;
    } else {
        _peers = new HashSet<Hash>(numPeers);
        for (int i = 0; i < numPeers; i++) {
            Hash peerIdentityHash = new Hash();
            peerIdentityHash.readBytes(din);
            _peers.add(peerIdentityHash);
        }
    }
    DataHelper.readProperties(din, _options);
    _signature = new Signature(_identity.getSigningPublicKey().getType());
    _signature.readBytes(in);
    if (verifySig) {
        SigType type = _identity.getSigningPublicKey().getType();
        if (type != SigType.EdDSA_SHA512_Ed25519) {
            // This won't work for EdDSA
            SimpleDataStructure hash = _identity.getSigningPublicKey().getType().getHashInstance();
            hash.setData(digest.digest());
            _isValid = DSAEngine.getInstance().verifySignature(_signature, hash, _identity.getSigningPublicKey());
            _validated = true;
        } else {
            doValidate();
        }
        if (!_isValid) {
            throw new DataFormatException("Bad sig");
        }
    }
// _log.debug("Read routerInfo: " + toString());
}
Also used : DigestInputStream(java.security.DigestInputStream) DigestInputStream(java.security.DigestInputStream) InputStream(java.io.InputStream) Hash(net.i2p.data.Hash) SHA1Hash(net.i2p.crypto.SHA1Hash) SigType(net.i2p.crypto.SigType) DataFormatException(net.i2p.data.DataFormatException) Signature(net.i2p.data.Signature) MessageDigest(java.security.MessageDigest) SimpleDataStructure(net.i2p.data.SimpleDataStructure)

Example 39 with SigType

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

the class EstablishState method verifyInbound.

/**
 * We are Bob. Verify message #3 from Alice, then send message #4 to Alice.
 *
 * _aliceIdentSize and _aliceIdent must be set.
 * _sz_aliceIdent_tsA_padding_aliceSig must contain at least
 *  (2 + _aliceIdentSize + 4 + padding + sig) bytes.
 *
 * Sets _aliceIdent so that we
 *
 * readAliceRouterIdentity() must have been called previously
 *
 * Make sure the signatures are correct, and if they are, update the
 * NIOConnection with the session key / peer ident / clock skew / iv.
 * The NIOConnection itself is responsible for registering with the
 * transport
 *
 *  State must be IB_GOT_RI.
 *  Caller must synch.
 */
private void verifyInbound() {
    byte[] b = _sz_aliceIdent_tsA_padding_aliceSig.toByteArray();
    try {
        int sz = _aliceIdentSize;
        // her timestamp from message #3
        long tsA = DataHelper.fromLong(b, 2 + sz, 4);
        // _tsB is when we sent message #2
        // Adjust backward by RTT/2
        long now = _context.clock().now();
        // rtt from sending #2 to receiving #3
        long rtt = now - _con.getCreated();
        _peerSkew = (now - (tsA * 1000) - (rtt / 2) + 500) / 1000;
        ByteArrayOutputStream baos = new ByteArrayOutputStream(768);
        baos.write(_X);
        baos.write(_Y);
        baos.write(_context.routerHash().getData());
        baos.write(DataHelper.toLong(4, tsA));
        baos.write(DataHelper.toLong(4, _tsB));
        // baos.write(b, 2+sz+4, b.length-2-sz-4-Signature.SIGNATURE_BYTES);
        byte[] toVerify = baos.toByteArray();
        // if (_log.shouldLog(Log.DEBUG)) {
        // _log.debug(prefix()+"checking " + Base64.encode(toVerify, 0, AES_SIZE));
        // //_log.debug(prefix()+"check pad " + Base64.encode(b, 2+sz+4, 12));
        // }
        // handle variable signature size
        SigType type = _aliceIdent.getSigningPublicKey().getType();
        if (type == null) {
            fail("unsupported sig type");
            return;
        }
        byte[] s = new byte[type.getSigLen()];
        System.arraycopy(b, b.length - s.length, s, 0, s.length);
        Signature sig = new Signature(type, s);
        boolean ok = _context.dsa().verifySignature(sig, toVerify, _aliceIdent.getSigningPublicKey());
        if (ok) {
            // get inet-addr
            InetAddress addr = this._con.getChannel().socket().getInetAddress();
            byte[] ip = (addr == null) ? null : addr.getAddress();
            if (_context.banlist().isBanlistedForever(_aliceIdent.calculateHash())) {
                if (_log.shouldLog(Log.WARN))
                    _log.warn("Dropping inbound connection from permanently banlisted peer: " + _aliceIdent.calculateHash());
                // rather than doing the whole handshake
                if (ip != null)
                    _context.blocklist().add(ip);
                fail("Peer is banlisted forever: " + _aliceIdent.calculateHash());
                return;
            }
            if (ip != null)
                _transport.setIP(_aliceIdent.calculateHash(), ip);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "verification successful for " + _con);
            long diff = 1000 * Math.abs(_peerSkew);
            if (!_context.clock().getUpdatedSuccessfully()) {
                // Adjust the clock one time in desperation
                // This isn't very likely, outbound will do it first
                // We are Bob, she is Alice, adjust to match Alice
                _context.clock().setOffset(1000 * (0 - _peerSkew), true);
                _peerSkew = 0;
                if (diff != 0)
                    _log.logAlways(Log.WARN, "NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
            } else if (diff >= Router.CLOCK_FUDGE_FACTOR) {
                _context.statManager().addRateData("ntcp.invalidInboundSkew", diff);
                _transport.markReachable(_aliceIdent.calculateHash(), true);
                // Only banlist if we know what time it is
                _context.banlist().banlistRouter(DataHelper.formatDuration(diff), _aliceIdent.calculateHash(), _x("Excessive clock skew: {0}"));
                _transport.setLastBadSkew(_peerSkew);
                fail("Clocks too skewed (" + diff + " ms)", null, true);
                return;
            } else if (_log.shouldLog(Log.DEBUG)) {
                _log.debug(prefix() + "Clock skew: " + diff + " ms");
            }
            _con.setRemotePeer(_aliceIdent);
            sendInboundConfirm(_aliceIdent, tsA);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "e_bobSig is " + _e_bobSig.length + " bytes long");
            // reuse buf
            byte[] iv = _curEncrypted;
            System.arraycopy(_e_bobSig, _e_bobSig.length - AES_SIZE, iv, 0, AES_SIZE);
            // this does not copy the IV, do not release to cache
            // We are Bob, she is Alice, clock skew is Alice-Bob
            // skew in seconds
            _con.finishInboundEstablishment(_dh.getSessionKey(), _peerSkew, iv, _prevEncrypted);
            releaseBufs(true);
            if (_log.shouldLog(Log.INFO))
                _log.info(prefix() + "Verified remote peer as " + _aliceIdent.calculateHash());
            changeState(State.VERIFIED);
        } else {
            _context.statManager().addRateData("ntcp.invalidInboundSignature", 1);
            fail("Peer verification failed - spoof of " + _aliceIdent.calculateHash() + "?");
        }
    } catch (IOException ioe) {
        _context.statManager().addRateData("ntcp.invalidInboundIOE", 1);
        fail("Error verifying peer", ioe);
    }
}
Also used : Signature(net.i2p.data.Signature) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) InetAddress(java.net.InetAddress) SigType(net.i2p.crypto.SigType)

Example 40 with SigType

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

the class SAMv1Handler method execDestMessage.

/* Parse and execute a DEST message*/
protected boolean execDestMessage(String opcode, Properties props) {
    if (opcode.equals("GENERATE")) {
        String sigTypeStr = props.getProperty("SIGNATURE_TYPE");
        SigType sigType;
        if (sigTypeStr != null) {
            sigType = SigType.parseSigType(sigTypeStr);
            if (sigType == null) {
                writeString("DEST REPLY RESULT=I2P_ERROR MESSAGE=\"SIGNATURE_TYPE " + sigTypeStr + " unsupported\"\n");
                return false;
            }
        } else {
            sigType = SigType.DSA_SHA1;
        }
        ByteArrayOutputStream priv = new ByteArrayOutputStream(663);
        ByteArrayOutputStream pub = new ByteArrayOutputStream(387);
        SAMUtils.genRandomKey(priv, pub, sigType);
        return writeString("DEST REPLY" + " PUB=" + Base64.encode(pub.toByteArray()) + " PRIV=" + Base64.encode(priv.toByteArray()) + "\n");
    } else {
        writeString("DEST REPLY RESULT=I2P_ERROR MESSAGE=\"DEST GENERATE required\"");
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Unrecognized DEST message opcode: \"" + opcode + "\"");
        return false;
    }
}
Also used : ByteArrayOutputStream(java.io.ByteArrayOutputStream) SigType(net.i2p.crypto.SigType)

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