Blinding:

- Blinding only throws IAE
- Remove context arg from encode()
- Hook in new form args on /configkeyring
- Show b33 on /configkeyring
- Remove support for appended secret in b33
- Persist cache immediately when storing secret or privkey
- Fix i2ptunnel for std. ls2
- Add auth/secret required flags to BlindData
more to do
This commit is contained in:
zzz
2019-05-28 15:12:20 +00:00
parent 0c7c19451c
commit 973aab8f53
9 changed files with 274 additions and 116 deletions

View File

@ -1,8 +1,16 @@
package net.i2p.router.web.helpers;
import net.i2p.crypto.Blinding;
import net.i2p.crypto.EncType;
import net.i2p.crypto.SigType;
import net.i2p.data.Base64;
import net.i2p.data.BlindData;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.PrivateKey;
import net.i2p.data.SessionKey;
import net.i2p.data.SigningPublicKey;
import net.i2p.router.web.FormHandler;
import net.i2p.util.ConvertToHash;
@ -12,33 +20,151 @@ import net.i2p.util.ConvertToHash;
public class ConfigKeyringHandler extends FormHandler {
private String _peer;
private String _key;
private String _secret;
private int _mode;
@Override
protected void processForm() {
boolean adding = _action.equals(_t("Add key"));
if (adding || _action.equals(_t("Delete key"))) {
if (_peer == null)
if (_peer == null) {
addFormError(_t("You must enter a destination"));
if (_key == null && adding)
addFormError(_t("You must enter a key"));
if (_peer == null || (_key == null && adding))
return;
Hash h = ConvertToHash.getHash(_peer);
}
Hash h = null;
if (!_peer.endsWith(".b32.i2p") || _peer.length() <= 60) {
// don't wait for several seconds for b33 lookup
h = ConvertToHash.getHash(_peer);
}
if (adding) {
SessionKey sk = new SessionKey();
try {
sk.fromBase64(_key);
} catch (DataFormatException dfe) {}
if (h == null || h.getData() == null) {
addFormError(_t("Invalid destination"));
} else if (_context.clientManager().isLocal(h)) {
// don't bother translating
addFormError("Cannot add key for local destination. Enable encryption in the Hidden Services Manager.");
} else if (sk.getData() == null) {
addFormError(_t("Invalid key"));
byte[] b = null;
if (_mode == 1 || _mode == 4 || _mode == 5) {
if (_key == null) {
addFormError(_t("You must enter a key"));
return;
}
b = Base64.decode(_key);
if (b == null || b.length != 32) {
addFormError(_t("Invalid key"));
return;
}
}
if (_mode == 1) {
// LS1
if (h == null || h.getData() == null) {
addFormError(_t("Invalid destination"));
} else if (_context.clientManager().isLocal(h)) {
// don't bother translating
addFormError("Cannot add key for local destination. Enable encryption in the Hidden Services Manager.");
} else {
SessionKey sk = new SessionKey(b);
_context.keyRing().put(h, sk);
addFormNotice(_t("Key for {0} added to keyring", h.toBase32()));
}
} else {
_context.keyRing().put(h, sk);
addFormNotice(_t("Key for {0} added to keyring", h.toBase32()));
if ((_mode == 3 || _mode == 5 || _mode == 7) && _secret == null) {
addFormError(_t("Lookup password required"));
return;
}
// b33 if supplied as hostname
BlindData bdin = null;
try {
bdin = Blinding.decode(_context, _peer);
} catch (IllegalArgumentException iae) {}
// we need the dest or the spk, not just the desthash
SigningPublicKey spk = null;
Destination d = null;
// don't cause LS fetch
if (!_peer.endsWith(".b32.i2p"))
d = _context.namingService().lookup(_peer);
if (d != null) {
spk = d.getSigningPublicKey();
} else if (bdin != null) {
spk = bdin.getUnblindedPubKey();
}
if (spk == null) {
addFormError(_t("Requires hostname, destination, or blinded base32"));
return;
}
// from BlindCache
BlindData bdold = _context.netDb().getBlindData(spk);
if (bdold != null && d == null)
d = bdold.getDestination();
if (d != null && _context.clientManager().isLocal(d)) {
// don't bother translating
addFormError("Cannot add key for local destination. Enable encryption in the Hidden Services Manager.");
return;
}
SigType blindType;
if (bdin != null) {
blindType = bdin.getBlindedSigType();
} else if (bdold != null) {
blindType = bdold.getBlindedSigType();
} else {
blindType = Blinding.getDefaultBlindedType(spk.getType());
}
int atype;
PrivateKey pk;
if (_mode == 4 || _mode == 5) {
atype = BlindData.AUTH_PSK;
// use supplied pk
pk = new PrivateKey(EncType.ECIES_X25519, b);
} else if (_mode == 6 || _mode == 7) {
atype = BlindData.AUTH_DH;
// create new pk
b = new byte[32];
_context.random().nextBytes(b);
pk = new PrivateKey(EncType.ECIES_X25519, b);
} else {
// modes 2 and 3
atype = BlindData.AUTH_NONE;
pk = null;
}
if (_mode == 2 || _mode == 4 || _mode == 6)
_secret = null;
if (bdin != null) {
// more checks based on supplied b33
if (bdin.getSecretRequired() && _secret == null) {
addFormError(_t("Destination requires lookup password"));
return;
}
if (!bdin.getSecretRequired() && _secret != null) {
addFormError(_t("Destination does not require lookup password"));
return;
}
if (bdin.getAuthRequired() && pk == null) {
addFormError(_t("Destination requires encryption key"));
return;
}
if (!bdin.getAuthRequired() && pk != null) {
addFormError(_t("Destination does not require encryption key"));
return;
}
}
// to BlindCache
BlindData bdout;
if (d != null) {
bdout = new BlindData(_context, d, blindType, _secret, atype, pk);
} else {
bdout = new BlindData(_context, spk, blindType, _secret, atype, pk);
}
if (bdold != null) {
// debug
addFormNotice("already cached: " + bdold);
}
try {
_context.netDb().setBlindData(bdout);
addFormNotice(_t("Key for {0} added to keyring", bdout.toBase32()));
if (_mode == 6 || _mode == 7) {
addFormNotice(_t("Send your new key to the server opererator") + ": " + pk.toPublic().toBase64());
}
} catch (IllegalArgumentException iae) {
addFormError(_t("Invalid destination") + ": " + iae.getMessage());
}
}
} else { // Delete
if (h != null && h.getData() != null) {
@ -61,4 +187,20 @@ public class ConfigKeyringHandler extends FormHandler {
public void setPeer(String peer) { if (peer != null) _peer = peer.trim(); }
public void setKey(String key) { if (key != null) _key = key.trim(); }
/** @since 0.9.41 */
public void setNofilter_blindedPassword(String pw) {
if (pw != null) {
pw = pw.trim();
if (pw.length() > 0)
_secret = pw;
}
}
/** @since 0.9.41 */
public void setEncryptMode(String m) {
try {
_mode = Integer.parseInt(m);
} catch (NumberFormatException nfe) {}
}
}

View File

@ -85,15 +85,15 @@ public class ConfigKeyringHelper extends HelperBase {
List<BlindData> bdata = _context.netDb().getBlindData();
// TODO sort by hostname
for (BlindData bd : bdata) {
Hash h = bd.getDestHash();
if (h == null)
continue;
buf.append("\n<tr><td>");
buf.append(h.toBase32());
buf.append(bd.toBase32());
buf.append("</td><td>");
String host = _context.namingService().reverseLookup(h);
if (host != null)
buf.append(host);
Hash h = bd.getDestHash();
if (h != null) {
String host = _context.namingService().reverseLookup(h);
if (host != null)
buf.append(host);
}
buf.append("</td><td>");
int type = bd.getAuthType();
PrivateKey pk = bd.getAuthPrivKey();