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;
}
}
}
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;
}
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;
}
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);
}
}
}
Aggregations