* Crypto: More implementation for key certs

- Support i2cp.destination.sigType option in TunnelController and
    I2PSocketManagerFactory
  - Fixup of Destination.create() and Destination.size()
  - Add generic off/len methods in DSAEngine, needed for streaming
  - Fixup of sign/verify in streaming Packet
  - Javadocs
This commit is contained in:
zzz
2014-01-03 00:22:44 +00:00
parent 5842e25205
commit e8e239616f
9 changed files with 149 additions and 68 deletions

View File

@@ -1223,7 +1223,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
}
/**
* Generate a new keypair
* Generate a new keypair.
* Does NOT support non-default sig types.
* Deprecated - only used by CLI
*
* Sets the event "genkeysResult" = "ok" or "error" after the generation is complete
@@ -1266,7 +1267,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
}
/**
* Generate a new keypair
* Generate a new keypair.
* Does NOT support non-default sig types.
* Deprecated - only used by CLI
*
* Sets the event "privateKey" = base64 of the privateKey stream and
@@ -1275,7 +1277,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
* @param l logger to receive events and output
*/
private static void runGenTextKeys(Logging l) {
ByteArrayOutputStream privkey = new ByteArrayOutputStream(512);
ByteArrayOutputStream privkey = new ByteArrayOutputStream(1024);
ByteArrayOutputStream pubkey = new ByteArrayOutputStream(512);
makeKey(privkey, pubkey, l);
l.log("Private key: " + Base64.encode(privkey.toByteArray()));
@@ -1527,10 +1529,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
/**
* Create a new destination, storing the destination and its private keys where
* instructed
* instructed.
* Does NOT support non-default sig types.
* Deprecated - only used by CLI
*
* @param writeTo location to store the private keys
* @param writeTo location to store the destination and private keys
* @param pubDest location to store the destination
* @param l logger to send messages to
*/

View File

@@ -7,11 +7,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.crypto.SigType;
import net.i2p.data.Base32;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
@@ -49,8 +51,8 @@ public class TunnelController implements Logging {
* the prefix should be used (and, in turn, that prefix should be stripped off
* before being interpreted by this controller)
*
* @param config original key=value mapping
* @param prefix beginning of key values that are relevent to this tunnel
* @param config original key=value mapping non-null
* @param prefix beginning of key values that are relevant to this tunnel
*/
public TunnelController(Properties config, String prefix) {
this(config, prefix, true);
@@ -58,6 +60,8 @@ public class TunnelController implements Logging {
/**
*
* @param config original key=value mapping non-null
* @param prefix beginning of key values that are relevant to this tunnel
* @param createKey for servers, whether we want to create a brand new destination
* with private keys at the location specified or not (does not
* overwrite existing ones)
@@ -99,7 +103,16 @@ public class TunnelController implements Logging {
FileOutputStream fos = null;
try {
fos = new SecureFileOutputStream(keyFile);
Destination dest = client.createDestination(fos);
SigType stype = I2PClient.DEFAULT_SIGTYPE;
String st = _config.getProperty("option." + I2PClient.PROP_SIGTYPE);
if (st != null) {
SigType type = SigType.parseSigType(st);
if (type != null)
stype = type;
else
log("Unsupported sig type " + st);
}
Destination dest = client.createDestination(fos, stype);
String destStr = dest.toBase64();
log("Private key created and saved in " + keyFile.getAbsolutePath());
log("You should backup this file in a secure place.");

View File

@@ -12,6 +12,7 @@ import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.crypto.SigType;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelTask;
@@ -78,8 +79,17 @@ import net.i2p.util.EventDispatcher;
I2PClient client = I2PClientFactory.createClient();
byte[] key;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream(512);
client.createDestination(out);
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
SigType stype = I2PClient.DEFAULT_SIGTYPE;
String st = tunnel.getClientOptions().getProperty(I2PClient.PROP_SIGTYPE);
if (st != null) {
SigType type = SigType.parseSigType(st);
if (type != null)
stype = type;
else
l.log("Unsupported sig type " + st);
}
client.createDestination(out, stype);
key = out.toByteArray();
} catch(Exception exc) {
throw new RuntimeException("failed to create i2p-destination", exc);

View File

@@ -14,6 +14,7 @@ import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.crypto.SigType;
import net.i2p.util.Log;
/**
@@ -26,7 +27,7 @@ public class I2PSocketManagerFactory {
public static final String PROP_MANAGER = "i2p.streaming.manager";
public static final String DEFAULT_MANAGER = "net.i2p.client.streaming.I2PSocketManagerFull";
/**
* Create a socket manager using a brand new destination connected to the
* I2CP router on the local machine on the default port (7654).
@@ -79,9 +80,9 @@ public class I2PSocketManagerFactory {
*/
public static I2PSocketManager createManager(String i2cpHost, int i2cpPort, Properties opts) {
I2PClient client = I2PClientFactory.createClient();
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
try {
client.createDestination(keyStream);
client.createDestination(keyStream, getSigType(opts));
ByteArrayInputStream in = new ByteArrayInputStream(keyStream.toByteArray());
return createManager(in, i2cpHost, i2cpPort, opts);
} catch (IOException ioe) {
@@ -168,9 +169,9 @@ public class I2PSocketManagerFactory {
int i2cpPort, Properties opts) throws I2PSessionException {
if (myPrivateKeyStream == null) {
I2PClient client = I2PClientFactory.createClient();
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
try {
client.createDestination(keyStream);
client.createDestination(keyStream, getSigType(opts));
} catch (Exception e) {
throw new I2PSessionException("Error creating keys", e);
}
@@ -257,6 +258,23 @@ public class I2PSocketManagerFactory {
return i2cpPort;
}
/**
* @param opts may be null
* @since 0.9.11
*/
private static SigType getSigType(Properties opts) {
if (opts != null) {
String st = opts.getProperty(I2PClient.PROP_SIGTYPE);
if (st != null) {
SigType rv = SigType.parseSigType(st);
if (rv != null)
return rv;
getLog().error("Unsupported sig type " + st);
}
}
return I2PClient.DEFAULT_SIGTYPE;
}
/** @since 0.9.7 */
private static Log getLog() {
return I2PAppContext.getGlobalContext().logManager().getLog(I2PSocketManagerFactory.class);

View File

@@ -397,13 +397,14 @@ class Packet {
* @throws IllegalStateException if there is data missing or otherwise b0rked
*/
public int writePacket(byte buffer[], int offset) throws IllegalStateException {
return writePacket(buffer, offset, true);
return writePacket(buffer, offset, 0);
}
/**
* @param includeSig if true, include the real signature, otherwise put zeroes
* in its place.
* @param fakeSigLen if 0, include the real signature in _optionSignature;
* if nonzero, leave space for that many bytes
*/
private int writePacket(byte buffer[], int offset, boolean includeSig) throws IllegalStateException {
private int writePacket(byte buffer[], int offset, int fakeSigLen) throws IllegalStateException {
int cur = offset;
DataHelper.toLong(buffer, cur, 4, (_sendStreamId >= 0 ? _sendStreamId : STREAM_ID_UNKNOWN));
cur += 4;
@@ -438,7 +439,12 @@ class Packet {
if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED))
optionSize += 2;
if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
optionSize += _optionSignature.length();
if (fakeSigLen > 0)
optionSize += fakeSigLen;
else if (_optionSignature != null)
optionSize += _optionSignature.length();
else
throw new IllegalStateException();
}
DataHelper.toLong(buffer, cur, 2, optionSize);
@@ -456,11 +462,14 @@ class Packet {
cur += 2;
}
if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
if (includeSig)
if (fakeSigLen == 0) {
// we're signing (or validating)
System.arraycopy(_optionSignature.getData(), 0, buffer, cur, _optionSignature.length());
else // we're signing (or validating)
Arrays.fill(buffer, cur, cur + _optionSignature.length(), (byte)0x0);
cur += _optionSignature.length();
cur += _optionSignature.length();
} else {
Arrays.fill(buffer, cur, cur + fakeSigLen, (byte)0x0);
cur += fakeSigLen;
}
}
if (_payload != null) {
@@ -661,7 +670,7 @@ class Packet {
if (buffer == null)
buffer = new byte[size];
int written = writePacket(buffer, 0, false);
int written = writePacket(buffer, 0, from.getSigningPublicKey().getType().getSigLen());
if (written != size) {
ctx.logManager().getLog(Packet.class).error("Written " + written + " size " + size + " for " + toString(), new Exception("moo"));
return false;
@@ -692,7 +701,7 @@ class Packet {
*/
public int writeSignedPacket(byte buffer[], int offset, I2PAppContext ctx, SigningPrivateKey key) throws IllegalStateException {
setFlag(FLAG_SIGNATURE_INCLUDED);
int size = writePacket(buffer, offset, false);
int size = writePacket(buffer, offset, key.getType().getSigLen());
_optionSignature = ctx.dsa().sign(buffer, offset, size, key);
//if (false) {
// Log l = ctx.logManager().getLog(Packet.class);
@@ -760,7 +769,7 @@ class Packet {
if (isFlagSet(FLAG_CLOSE)) buf.append(" CLOSE");
if (isFlagSet(FLAG_DELAY_REQUESTED)) buf.append(" DELAY ").append(_optionDelay);
if (isFlagSet(FLAG_ECHO)) buf.append(" ECHO");
if (isFlagSet(FLAG_FROM_INCLUDED)) buf.append(" FROM");
if (isFlagSet(FLAG_FROM_INCLUDED)) buf.append(" FROM ").append(_optionFrom.size());
if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED)) buf.append(" MS ").append(_optionMaxSize);
if (isFlagSet(FLAG_PROFILE_INTERACTIVE)) buf.append(" INTERACTIVE");
if (isFlagSet(FLAG_RESET)) buf.append(" RESET");