use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class CreateRouterInfoJob method getSigTypeConfig.
/**
* The configured SigType to expect on read-in
* @since 0.9.16
*/
public static SigType getSigTypeConfig(RouterContext ctx) {
SigType cstype = DEFAULT_SIGTYPE;
String sstype = ctx.getProperty(PROP_ROUTER_SIGTYPE);
if (sstype != null) {
SigType ntype = SigType.parseSigType(sstype);
if (ntype != null)
cstype = ntype;
}
// fallback?
if (cstype != SigType.DSA_SHA1 && !cstype.isAvailable())
cstype = SigType.DSA_SHA1;
return cstype;
}
use of net.i2p.crypto.SigType 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) {
}
}
}
use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class UDPTransport method bid.
public TransportBid bid(RouterInfo toAddress, long dataSize) {
if (dataSize > OutboundMessageState.MAX_MSG_SIZE) {
// NTCP max is lower, so msg will get dropped
return null;
}
Hash to = toAddress.getIdentity().calculateHash();
PeerState peer = getPeerState(to);
if (peer != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("bidding on a message to an established peer: " + peer);
if (preferUDP())
return _cachedBid[FAST_PREFERRED_BID];
else
return _cachedBid[FAST_BID];
} else {
// If we don't have a port, all is lost
if (_reachabilityStatus == Status.HOSED) {
markUnreachable(to);
return null;
}
// Validate his SSU address
RouterAddress addr = getTargetAddress(toAddress);
if (addr == null) {
markUnreachable(to);
return null;
}
// Check for supported sig type
SigType type = toAddress.getIdentity().getSigType();
if (type == null || !type.isAvailable()) {
markUnreachable(to);
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(to);
return null;
}
}
}
if (!allowConnection())
return _cachedBid[TRANSIENT_FAIL_BID];
if (_log.shouldLog(Log.DEBUG))
_log.debug("bidding on a message to an unestablished peer: " + to);
// Try to maintain at least 5 peers (30 for v6) so we can determine our IP address and
// we have a selection to run peer tests with.
// If we are firewalled, and we don't have enough peers that volunteered to
// also introduce us, also bid aggressively so we are preferred over NTCP.
// (Otherwise we only talk UDP to those that are firewalled, and we will
// never get any introducers)
int count = _peersByIdent.size();
if (alwaysPreferUDP()) {
return _cachedBid[SLOW_PREFERRED_BID];
} else if (count < _min_peers || (_haveIPv6Address && count < _min_v6_peers) || (introducersRequired() && _introManager.introducerCount() < MIN_INTRODUCER_POOL)) {
// TODO After some time, decide that UDP is blocked/broken and return TRANSIENT_FAIL_BID?
if (_context.random().nextInt(4) == 0)
return _cachedBid[SLOWEST_BID];
else
return _cachedBid[SLOW_PREFERRED_BID];
} else if (preferUDP()) {
return _cachedBid[SLOW_BID];
} else if (haveCapacity()) {
if (addr.getCost() > DEFAULT_COST)
return _cachedBid[SLOWEST_COST_BID];
else
return _cachedBid[SLOWEST_BID];
} else {
if (addr.getCost() > DEFAULT_COST)
return _cachedBid[NEAR_CAPACITY_COST_BID];
else
return _cachedBid[NEAR_CAPACITY_BID];
}
}
}
use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class FamilyKeyCrypto method verify.
/**
* Verify the family in a RouterInfo, name already retrieved
* @since 0.9.28
*/
private boolean verify(RouterInfo ri, String name) {
Hash h = ri.getHash();
String ssig = ri.getOption(OPT_SIG);
if (ssig == null) {
if (_log.shouldInfo())
_log.info("No sig for " + h + ' ' + name);
return false;
}
String nameAndSig = _verified.get(h);
String riNameAndSig = name + ssig;
if (nameAndSig != null) {
if (nameAndSig.equals(riNameAndSig))
return true;
// name or sig changed
_verified.remove(h);
}
SigningPublicKey spk;
if (name.equals(_fname)) {
// us
spk = _pubkey;
} else {
if (_negativeCache.contains(h))
return false;
spk = loadCert(name);
if (spk == null) {
// look for a b64 key in the RI
String skey = ri.getOption(OPT_KEY);
if (skey != null) {
int colon = skey.indexOf(':');
// switched from ';' to ':' during dev, remove this later
if (colon < 0)
colon = skey.indexOf(';');
if (colon > 0) {
try {
int code = Integer.parseInt(skey.substring(0, colon));
SigType type = SigType.getByCode(code);
if (type != null) {
byte[] bkey = Base64.decode(skey.substring(colon + 1));
if (bkey != null) {
spk = new SigningPublicKey(type, bkey);
}
}
} catch (NumberFormatException e) {
if (_log.shouldInfo())
_log.info("Bad b64 family key: " + ri, e);
} catch (IllegalArgumentException e) {
if (_log.shouldInfo())
_log.info("Bad b64 family key: " + ri, e);
} catch (ArrayIndexOutOfBoundsException e) {
if (_log.shouldInfo())
_log.info("Bad b64 family key: " + ri, e);
}
}
}
if (spk == null) {
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("No cert or valid key for " + h + ' ' + name);
return false;
}
}
}
if (!spk.getType().isAvailable()) {
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Unsupported crypto for sig for " + h);
return false;
}
byte[] bsig = Base64.decode(ssig);
if (bsig == null) {
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Bad sig for " + h + ' ' + name + ' ' + ssig);
return false;
}
Signature sig;
try {
sig = new Signature(spk.getType(), bsig);
} catch (IllegalArgumentException iae) {
// wrong size (type mismatch)
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Bad sig for " + ri, iae);
return false;
}
byte[] nb = DataHelper.getUTF8(name);
byte[] b = new byte[nb.length + Hash.HASH_LENGTH];
System.arraycopy(nb, 0, b, 0, nb.length);
System.arraycopy(ri.getHash().getData(), 0, b, nb.length, Hash.HASH_LENGTH);
boolean rv = _context.dsa().verifySignature(sig, b, spk);
if (rv)
_verified.put(h, riNameAndSig);
else
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Verified? " + rv + " for " + h + ' ' + name + ' ' + ssig);
return rv;
}
use of net.i2p.crypto.SigType in project i2p.i2p by i2p.
the class KademliaNetworkDatabaseFacade method processStoreFailure.
/**
* If the validate fails, call this
* to determine if it was because of unsupported crypto.
*
* If so, this will banlist-forever the router hash or permanently negative cache the dest hash,
* and then throw the exception. Otherwise it does nothing.
*
* @throws UnsupportedCryptoException if that's why it failed.
* @since 0.9.16
*/
private void processStoreFailure(Hash h, DatabaseEntry entry) throws UnsupportedCryptoException {
if (entry.getHash().equals(h)) {
if (entry.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
LeaseSet ls = (LeaseSet) entry;
Destination d = ls.getDestination();
Certificate c = d.getCertificate();
if (c.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
try {
KeyCertificate kc = c.toKeyCertificate();
SigType type = kc.getSigType();
if (type == null || !type.isAvailable() || type.getBaseAlgorithm() == SigAlgo.RSA) {
failPermanently(d);
String stype = (type != null) ? type.toString() : Integer.toString(kc.getSigTypeCode());
if (_log.shouldLog(Log.WARN))
_log.warn("Unsupported sig type " + stype + " for destination " + h);
throw new UnsupportedCryptoException("Sig type " + stype);
}
} catch (DataFormatException dfe) {
}
}
} else if (entry.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
RouterInfo ri = (RouterInfo) entry;
RouterIdentity id = ri.getIdentity();
Certificate c = id.getCertificate();
if (c.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
try {
KeyCertificate kc = c.toKeyCertificate();
SigType type = kc.getSigType();
if (type == null || !type.isAvailable()) {
String stype = (type != null) ? type.toString() : Integer.toString(kc.getSigTypeCode());
_context.banlist().banlistRouterForever(h, "Unsupported signature type " + stype);
if (_log.shouldLog(Log.WARN))
_log.warn("Unsupported sig type " + stype + " for router " + h);
throw new UnsupportedCryptoException("Sig type " + stype);
}
} catch (DataFormatException dfe) {
}
}
}
}
if (_log.shouldLog(Log.WARN))
_log.warn("Verify fail, cause unknown: " + entry);
}
Aggregations