use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class NTCPTransport method bid.
public TransportBid bid(RouterInfo toAddress, long dataSize) {
if (!isAlive())
return null;
if (dataSize > NTCPConnection.MAX_MSG_SIZE) {
// let SSU deal with it
_context.statManager().addRateData("ntcp.noBidTooLargeI2NP", dataSize);
return null;
}
Hash peer = toAddress.getIdentity().calculateHash();
if (_context.banlist().isBanlisted(peer, STYLE)) {
// we aren't banlisted in general (since we are trying to get a bid), but we have
// recently banlisted the peer on the NTCP transport, so don't try it
_context.statManager().addRateData("ntcp.attemptBanlistedPeer", 1);
return null;
} else if (isUnreachable(peer)) {
_context.statManager().addRateData("ntcp.attemptUnreachablePeer", 1);
return null;
}
boolean established = isEstablished(toAddress.getIdentity());
if (established) {
// _log.debug("fast bid when trying to send to " + peer + " as its already established");
return _fastBid;
}
RouterAddress addr = getTargetAddress(toAddress);
if (addr == null) {
markUnreachable(peer);
return null;
}
// Check for supported sig type
SigType type = toAddress.getIdentity().getSigType();
if (type == null || !type.isAvailable()) {
markUnreachable(peer);
return null;
}
// Can we connect to them if we are not DSA?
RouterInfo us = _context.router().getRouterInfo();
if (us != null) {
RouterIdentity id = us.getIdentity();
if (id.getSigType() != SigType.DSA_SHA1) {
String v = toAddress.getVersion();
if (VersionComparator.comp(v, MIN_SIGTYPE_VERSION) < 0) {
markUnreachable(peer);
return null;
}
}
}
if (!allowConnection()) {
// _log.warn("no bid when trying to send to " + peer + ", max connection limit reached");
return _transientFail;
}
// _log.debug("slow bid when trying to send to " + peer);
if (haveCapacity()) {
if (addr.getCost() > DEFAULT_COST)
return _slowCostBid;
else
return _slowBid;
} else {
if (addr.getCost() > DEFAULT_COST)
return _nearCapacityCostBid;
else
return _nearCapacityBid;
}
}
use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class OutboundEstablishState method decryptSignature.
/**
* decrypt the signature (and subsequent pad bytes) with the
* additional layer of encryption using the negotiated key along side
* the packet's IV
*
* Caller must synch on this.
* Only call this once! Decrypts in-place.
*/
private void decryptSignature() {
if (_receivedEncryptedSignature == null)
throw new NullPointerException("encrypted signature is null! this=" + this.toString());
if (_sessionKey == null)
throw new NullPointerException("SessionKey is null!");
if (_receivedIV == null)
throw new NullPointerException("IV is null!");
_context.aes().decrypt(_receivedEncryptedSignature, 0, _receivedEncryptedSignature, 0, _sessionKey, _receivedIV, _receivedEncryptedSignature.length);
// handle variable signature size
SigType type = _remotePeer.getSigningPublicKey().getType();
// if type == null throws NPE
int sigLen = type.getSigLen();
int mod = sigLen % 16;
if (mod != 0) {
byte[] signatureBytes = new byte[sigLen];
System.arraycopy(_receivedEncryptedSignature, 0, signatureBytes, 0, sigLen);
_receivedSignature = new Signature(type, signatureBytes);
} else {
_receivedSignature = new Signature(type, _receivedEncryptedSignature);
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Decrypted received signature: " + Base64.encode(_receivedSignature.getData()));
}
use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class OutboundEstablishState method receiveSessionCreated.
public synchronized void receiveSessionCreated(UDPPacketReader.SessionCreatedReader reader) {
if (_currentState == OutboundState.OB_STATE_VALIDATION_FAILED) {
if (_log.shouldLog(Log.WARN))
_log.warn("Session created already failed");
return;
}
if (_receivedY != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Session created already received, ignoring");
// already received
return;
}
_receivedY = new byte[UDPPacketReader.SessionCreatedReader.Y_LENGTH];
reader.readY(_receivedY, 0);
if (_aliceIP == null)
_aliceIP = new byte[reader.readIPSize()];
reader.readIP(_aliceIP, 0);
_alicePort = reader.readPort();
_receivedRelayTag = reader.readRelayTag();
_receivedSignedOnTime = reader.readSignedOnTime();
// handle variable signature size
SigType type = _remotePeer.getSigningPublicKey().getType();
if (type == null) {
// shouldn't happen, we only connect to supported peers
fail();
packetReceived();
return;
}
int sigLen = type.getSigLen();
int mod = sigLen % 16;
int pad = (mod == 0) ? 0 : (16 - mod);
int esigLen = sigLen + pad;
_receivedEncryptedSignature = new byte[esigLen];
reader.readEncryptedSignature(_receivedEncryptedSignature, 0, esigLen);
_receivedIV = new byte[UDPPacket.IV_SIZE];
reader.readIV(_receivedIV, 0);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Receive session created:Sig: " + Base64.encode(_receivedEncryptedSignature) + "receivedIV: " + Base64.encode(_receivedIV) + "AliceIP: " + Addresses.toString(_aliceIP) + " RelayTag: " + _receivedRelayTag + " SignedOn: " + _receivedSignedOnTime + ' ' + this.toString());
if (_currentState == OutboundState.OB_STATE_UNKNOWN || _currentState == OutboundState.OB_STATE_REQUEST_SENT || _currentState == OutboundState.OB_STATE_INTRODUCED || _currentState == OutboundState.OB_STATE_PENDING_INTRO)
_currentState = OutboundState.OB_STATE_CREATED_RECEIVED;
packetReceived();
}
use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class ClientMessageEventListener method handleCreateSession.
/**
* Handle a CreateSessionMessage.
* On errors, we could perhaps send a SessionStatusMessage with STATUS_INVALID before
* sending the DisconnectMessage... but right now the client will send _us_ a
* DisconnectMessage in return, and not wait around for our DisconnectMessage.
* So keep it simple.
*
* Defaults in SessionConfig options are, in general, NOT honored.
* In-JVM client side must promote defaults to the primary map.
*/
private void handleCreateSession(CreateSessionMessage message) {
SessionConfig in = message.getSessionConfig();
Destination dest = in.getDestination();
if (in.verifySignature()) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Signature verified correctly on create session message");
} else {
// For now, we do NOT send a SessionStatusMessage - see javadoc above
int itype = dest.getCertificate().getCertificateType();
SigType stype = SigType.getByCode(itype);
if (stype == null || !stype.isAvailable()) {
_log.error("Client requested unsupported signature type " + itype);
_runner.disconnectClient("Unsupported signature type " + itype);
} else if (in.tooOld()) {
long skew = _context.clock().now() - in.getCreationDate().getTime();
String msg = "Create session message client clock skew? ";
if (skew >= 0)
msg += DataHelper.formatDuration(skew) + " in the past";
else
msg += DataHelper.formatDuration(0 - skew) + " in the future";
_log.error(msg);
_runner.disconnectClient(msg);
} else {
_log.error("Signature verification failed on a create session message");
_runner.disconnectClient("Invalid signature on CreateSessionMessage");
}
return;
}
// Auth, since 0.8.2
Properties inProps = in.getOptions();
if (!checkAuth(inProps))
return;
SessionId id = _runner.getSessionId(dest.calculateHash());
if (id != null) {
_runner.disconnectClient("Already have session " + id);
return;
}
// Copy over the whole config structure so we don't later corrupt it on
// the client side if we change settings or later get a
// ReconfigureSessionMessage
SessionConfig cfg = new SessionConfig(dest);
cfg.setSignature(in.getSignature());
Properties props = new Properties();
boolean isPrimary = _runner.getSessionIds().isEmpty();
if (!isPrimary) {
// all the primary options, then the overrides from the alias
SessionConfig pcfg = _runner.getPrimaryConfig();
if (pcfg != null) {
props.putAll(pcfg.getOptions());
} else {
_log.error("no primary config?");
}
}
props.putAll(inProps);
cfg.setOptions(props);
// this sets the session id
int status = _runner.sessionEstablished(cfg);
if (status != SessionStatusMessage.STATUS_CREATED) {
// For now, we do NOT send a SessionStatusMessage - see javadoc above
if (_log.shouldLog(Log.ERROR))
_log.error("Session establish failed: code = " + status);
String msg;
if (status == SessionStatusMessage.STATUS_INVALID)
msg = "duplicate destination";
else if (status == SessionStatusMessage.STATUS_REFUSED)
msg = "session limit exceeded";
else
msg = "unknown error";
_runner.disconnectClient(msg);
return;
}
// get the new session ID
id = _runner.getSessionId(dest.calculateHash());
if (_log.shouldLog(Log.INFO))
_log.info("Session " + id + " established for " + dest.calculateHash());
if (isPrimary) {
sendStatusMessage(id, status);
startCreateSessionJob(cfg);
} else {
SessionConfig pcfg = _runner.getPrimaryConfig();
if (pcfg != null) {
ClientTunnelSettings settings = new ClientTunnelSettings(dest.calculateHash());
settings.readFromProperties(props);
// addAlias() sends the create lease set msg, so we have to send the SMS first
sendStatusMessage(id, status);
boolean ok = _context.tunnelManager().addAlias(dest, settings, pcfg.getDestination());
if (!ok) {
_log.error("Add alias failed");
// FIXME cleanup
}
} else {
_log.error("no primary config?");
status = SessionStatusMessage.STATUS_INVALID;
sendStatusMessage(id, status);
// FIXME cleanup
}
}
}
use of net.i2p.crypto.SigType 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;
}
Aggregations