forked from I2P_Developers/i2p.i2p
* 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:
@ -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
|
* Deprecated - only used by CLI
|
||||||
*
|
*
|
||||||
* Sets the event "genkeysResult" = "ok" or "error" after the generation is complete
|
* 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
|
* Deprecated - only used by CLI
|
||||||
*
|
*
|
||||||
* Sets the event "privateKey" = base64 of the privateKey stream and
|
* 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
|
* @param l logger to receive events and output
|
||||||
*/
|
*/
|
||||||
private static void runGenTextKeys(Logging l) {
|
private static void runGenTextKeys(Logging l) {
|
||||||
ByteArrayOutputStream privkey = new ByteArrayOutputStream(512);
|
ByteArrayOutputStream privkey = new ByteArrayOutputStream(1024);
|
||||||
ByteArrayOutputStream pubkey = new ByteArrayOutputStream(512);
|
ByteArrayOutputStream pubkey = new ByteArrayOutputStream(512);
|
||||||
makeKey(privkey, pubkey, l);
|
makeKey(privkey, pubkey, l);
|
||||||
l.log("Private key: " + Base64.encode(privkey.toByteArray()));
|
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
|
* 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
|
* 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 pubDest location to store the destination
|
||||||
* @param l logger to send messages to
|
* @param l logger to send messages to
|
||||||
*/
|
*/
|
||||||
|
@ -7,11 +7,13 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
import net.i2p.client.I2PClient;
|
import net.i2p.client.I2PClient;
|
||||||
import net.i2p.client.I2PClientFactory;
|
import net.i2p.client.I2PClientFactory;
|
||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
|
import net.i2p.crypto.SigType;
|
||||||
import net.i2p.data.Base32;
|
import net.i2p.data.Base32;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
|
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
|
* the prefix should be used (and, in turn, that prefix should be stripped off
|
||||||
* before being interpreted by this controller)
|
* before being interpreted by this controller)
|
||||||
*
|
*
|
||||||
* @param config original key=value mapping
|
* @param config original key=value mapping non-null
|
||||||
* @param prefix beginning of key values that are relevent to this tunnel
|
* @param prefix beginning of key values that are relevant to this tunnel
|
||||||
*/
|
*/
|
||||||
public TunnelController(Properties config, String prefix) {
|
public TunnelController(Properties config, String prefix) {
|
||||||
this(config, prefix, true);
|
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
|
* @param createKey for servers, whether we want to create a brand new destination
|
||||||
* with private keys at the location specified or not (does not
|
* with private keys at the location specified or not (does not
|
||||||
* overwrite existing ones)
|
* overwrite existing ones)
|
||||||
@ -99,7 +103,16 @@ public class TunnelController implements Logging {
|
|||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
try {
|
try {
|
||||||
fos = new SecureFileOutputStream(keyFile);
|
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();
|
String destStr = dest.toBase64();
|
||||||
log("Private key created and saved in " + keyFile.getAbsolutePath());
|
log("Private key created and saved in " + keyFile.getAbsolutePath());
|
||||||
log("You should backup this file in a secure place.");
|
log("You should backup this file in a secure place.");
|
||||||
|
@ -12,6 +12,7 @@ import net.i2p.client.I2PClient;
|
|||||||
import net.i2p.client.I2PClientFactory;
|
import net.i2p.client.I2PClientFactory;
|
||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
import net.i2p.client.I2PSessionException;
|
import net.i2p.client.I2PSessionException;
|
||||||
|
import net.i2p.crypto.SigType;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.i2ptunnel.I2PTunnel;
|
import net.i2p.i2ptunnel.I2PTunnel;
|
||||||
import net.i2p.i2ptunnel.I2PTunnelTask;
|
import net.i2p.i2ptunnel.I2PTunnelTask;
|
||||||
@ -78,8 +79,17 @@ import net.i2p.util.EventDispatcher;
|
|||||||
I2PClient client = I2PClientFactory.createClient();
|
I2PClient client = I2PClientFactory.createClient();
|
||||||
byte[] key;
|
byte[] key;
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(512);
|
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||||||
client.createDestination(out);
|
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();
|
key = out.toByteArray();
|
||||||
} catch(Exception exc) {
|
} catch(Exception exc) {
|
||||||
throw new RuntimeException("failed to create i2p-destination", exc);
|
throw new RuntimeException("failed to create i2p-destination", exc);
|
||||||
|
@ -14,6 +14,7 @@ import net.i2p.client.I2PClient;
|
|||||||
import net.i2p.client.I2PClientFactory;
|
import net.i2p.client.I2PClientFactory;
|
||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
import net.i2p.client.I2PSessionException;
|
import net.i2p.client.I2PSessionException;
|
||||||
|
import net.i2p.crypto.SigType;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,9 +80,9 @@ public class I2PSocketManagerFactory {
|
|||||||
*/
|
*/
|
||||||
public static I2PSocketManager createManager(String i2cpHost, int i2cpPort, Properties opts) {
|
public static I2PSocketManager createManager(String i2cpHost, int i2cpPort, Properties opts) {
|
||||||
I2PClient client = I2PClientFactory.createClient();
|
I2PClient client = I2PClientFactory.createClient();
|
||||||
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
|
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
|
||||||
try {
|
try {
|
||||||
client.createDestination(keyStream);
|
client.createDestination(keyStream, getSigType(opts));
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(keyStream.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(keyStream.toByteArray());
|
||||||
return createManager(in, i2cpHost, i2cpPort, opts);
|
return createManager(in, i2cpHost, i2cpPort, opts);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
@ -168,9 +169,9 @@ public class I2PSocketManagerFactory {
|
|||||||
int i2cpPort, Properties opts) throws I2PSessionException {
|
int i2cpPort, Properties opts) throws I2PSessionException {
|
||||||
if (myPrivateKeyStream == null) {
|
if (myPrivateKeyStream == null) {
|
||||||
I2PClient client = I2PClientFactory.createClient();
|
I2PClient client = I2PClientFactory.createClient();
|
||||||
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
|
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
|
||||||
try {
|
try {
|
||||||
client.createDestination(keyStream);
|
client.createDestination(keyStream, getSigType(opts));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new I2PSessionException("Error creating keys", e);
|
throw new I2PSessionException("Error creating keys", e);
|
||||||
}
|
}
|
||||||
@ -257,6 +258,23 @@ public class I2PSocketManagerFactory {
|
|||||||
return i2cpPort;
|
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 */
|
/** @since 0.9.7 */
|
||||||
private static Log getLog() {
|
private static Log getLog() {
|
||||||
return I2PAppContext.getGlobalContext().logManager().getLog(I2PSocketManagerFactory.class);
|
return I2PAppContext.getGlobalContext().logManager().getLog(I2PSocketManagerFactory.class);
|
||||||
|
@ -397,13 +397,14 @@ class Packet {
|
|||||||
* @throws IllegalStateException if there is data missing or otherwise b0rked
|
* @throws IllegalStateException if there is data missing or otherwise b0rked
|
||||||
*/
|
*/
|
||||||
public int writePacket(byte buffer[], int offset) throws IllegalStateException {
|
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
|
* @param fakeSigLen if 0, include the real signature in _optionSignature;
|
||||||
* in its place.
|
* 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;
|
int cur = offset;
|
||||||
DataHelper.toLong(buffer, cur, 4, (_sendStreamId >= 0 ? _sendStreamId : STREAM_ID_UNKNOWN));
|
DataHelper.toLong(buffer, cur, 4, (_sendStreamId >= 0 ? _sendStreamId : STREAM_ID_UNKNOWN));
|
||||||
cur += 4;
|
cur += 4;
|
||||||
@ -438,7 +439,12 @@ class Packet {
|
|||||||
if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED))
|
if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED))
|
||||||
optionSize += 2;
|
optionSize += 2;
|
||||||
if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
|
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);
|
DataHelper.toLong(buffer, cur, 2, optionSize);
|
||||||
@ -456,11 +462,14 @@ class Packet {
|
|||||||
cur += 2;
|
cur += 2;
|
||||||
}
|
}
|
||||||
if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
|
if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
|
||||||
if (includeSig)
|
if (fakeSigLen == 0) {
|
||||||
|
// we're signing (or validating)
|
||||||
System.arraycopy(_optionSignature.getData(), 0, buffer, cur, _optionSignature.length());
|
System.arraycopy(_optionSignature.getData(), 0, buffer, cur, _optionSignature.length());
|
||||||
else // we're signing (or validating)
|
cur += _optionSignature.length();
|
||||||
Arrays.fill(buffer, cur, cur + _optionSignature.length(), (byte)0x0);
|
} else {
|
||||||
cur += _optionSignature.length();
|
Arrays.fill(buffer, cur, cur + fakeSigLen, (byte)0x0);
|
||||||
|
cur += fakeSigLen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_payload != null) {
|
if (_payload != null) {
|
||||||
@ -661,7 +670,7 @@ class Packet {
|
|||||||
|
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
buffer = new byte[size];
|
buffer = new byte[size];
|
||||||
int written = writePacket(buffer, 0, false);
|
int written = writePacket(buffer, 0, from.getSigningPublicKey().getType().getSigLen());
|
||||||
if (written != size) {
|
if (written != size) {
|
||||||
ctx.logManager().getLog(Packet.class).error("Written " + written + " size " + size + " for " + toString(), new Exception("moo"));
|
ctx.logManager().getLog(Packet.class).error("Written " + written + " size " + size + " for " + toString(), new Exception("moo"));
|
||||||
return false;
|
return false;
|
||||||
@ -692,7 +701,7 @@ class Packet {
|
|||||||
*/
|
*/
|
||||||
public int writeSignedPacket(byte buffer[], int offset, I2PAppContext ctx, SigningPrivateKey key) throws IllegalStateException {
|
public int writeSignedPacket(byte buffer[], int offset, I2PAppContext ctx, SigningPrivateKey key) throws IllegalStateException {
|
||||||
setFlag(FLAG_SIGNATURE_INCLUDED);
|
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);
|
_optionSignature = ctx.dsa().sign(buffer, offset, size, key);
|
||||||
//if (false) {
|
//if (false) {
|
||||||
// Log l = ctx.logManager().getLog(Packet.class);
|
// Log l = ctx.logManager().getLog(Packet.class);
|
||||||
@ -760,7 +769,7 @@ class Packet {
|
|||||||
if (isFlagSet(FLAG_CLOSE)) buf.append(" CLOSE");
|
if (isFlagSet(FLAG_CLOSE)) buf.append(" CLOSE");
|
||||||
if (isFlagSet(FLAG_DELAY_REQUESTED)) buf.append(" DELAY ").append(_optionDelay);
|
if (isFlagSet(FLAG_DELAY_REQUESTED)) buf.append(" DELAY ").append(_optionDelay);
|
||||||
if (isFlagSet(FLAG_ECHO)) buf.append(" ECHO");
|
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_MAX_PACKET_SIZE_INCLUDED)) buf.append(" MS ").append(_optionMaxSize);
|
||||||
if (isFlagSet(FLAG_PROFILE_INTERACTIVE)) buf.append(" INTERACTIVE");
|
if (isFlagSet(FLAG_PROFILE_INTERACTIVE)) buf.append(" INTERACTIVE");
|
||||||
if (isFlagSet(FLAG_RESET)) buf.append(" RESET");
|
if (isFlagSet(FLAG_RESET)) buf.append(" RESET");
|
||||||
|
@ -41,6 +41,11 @@ public interface I2PClient {
|
|||||||
/** @since 0.8.1 */
|
/** @since 0.8.1 */
|
||||||
public final static String PROP_RELIABILITY_NONE = "none";
|
public final static String PROP_RELIABILITY_NONE = "none";
|
||||||
|
|
||||||
|
/** @since 0.9.11 */
|
||||||
|
public static final String PROP_SIGTYPE = "i2cp.destination.sigType";
|
||||||
|
/** @since 0.9.11 */
|
||||||
|
public static final SigType DEFAULT_SIGTYPE = SigType.DSA_SHA1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For router->client payloads.
|
* For router->client payloads.
|
||||||
*
|
*
|
||||||
|
@ -47,7 +47,7 @@ class I2PClientImpl implements I2PClient {
|
|||||||
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
|
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
|
||||||
*/
|
*/
|
||||||
public Destination createDestination(OutputStream destKeyStream) throws I2PException, IOException {
|
public Destination createDestination(OutputStream destKeyStream) throws I2PException, IOException {
|
||||||
return createDestination(destKeyStream, SigType.DSA_SHA1);
|
return createDestination(destKeyStream, DEFAULT_SIGTYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,13 +89,20 @@ public class DSAEngine {
|
|||||||
* Uses TheCrypto code for DSA-SHA1 unless configured to use the java.security libraries.
|
* Uses TheCrypto code for DSA-SHA1 unless configured to use the java.security libraries.
|
||||||
*/
|
*/
|
||||||
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
|
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
|
||||||
|
return verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify using any sig type as of 0.9.11 (DSA only prior to that)
|
||||||
|
*/
|
||||||
|
public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
|
||||||
boolean rv;
|
boolean rv;
|
||||||
SigType type = signature.getType();
|
SigType type = signature.getType();
|
||||||
if (type != verifyingKey.getType())
|
if (type != verifyingKey.getType())
|
||||||
throw new IllegalArgumentException("type mismatch sig=" + signature.getType() + " key=" + verifyingKey.getType());
|
throw new IllegalArgumentException("type mismatch sig=" + signature.getType() + " key=" + verifyingKey.getType());
|
||||||
if (type != SigType.DSA_SHA1) {
|
if (type != SigType.DSA_SHA1) {
|
||||||
try {
|
try {
|
||||||
rv = altVerifySig(signature, signedData, verifyingKey);
|
rv = altVerifySig(signature, signedData, offset, size, verifyingKey);
|
||||||
if ((!rv) && _log.shouldLog(Log.WARN))
|
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||||
_log.warn(type + " Sig Verify Fail");
|
_log.warn(type + " Sig Verify Fail");
|
||||||
return rv;
|
return rv;
|
||||||
@ -107,7 +114,7 @@ public class DSAEngine {
|
|||||||
}
|
}
|
||||||
if (_useJavaLibs) {
|
if (_useJavaLibs) {
|
||||||
try {
|
try {
|
||||||
rv = altVerifySigSHA1(signature, signedData, verifyingKey);
|
rv = altVerifySigSHA1(signature, signedData, offset, size, verifyingKey);
|
||||||
if ((!rv) && _log.shouldLog(Log.WARN))
|
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||||
_log.warn("Lib DSA Sig Verify Fail");
|
_log.warn("Lib DSA Sig Verify Fail");
|
||||||
return rv;
|
return rv;
|
||||||
@ -117,19 +124,12 @@ public class DSAEngine {
|
|||||||
// now try TheCrypto
|
// now try TheCrypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rv = verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
|
rv = verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
|
||||||
if ((!rv) && _log.shouldLog(Log.WARN))
|
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||||
_log.warn("TheCrypto DSA Sig Verify Fail");
|
_log.warn("TheCrypto DSA Sig Verify Fail");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify using DSA-SHA1 ONLY
|
|
||||||
*/
|
|
||||||
public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
|
|
||||||
return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify using DSA-SHA1 ONLY
|
* Verify using DSA-SHA1 ONLY
|
||||||
*/
|
*/
|
||||||
@ -256,16 +256,26 @@ public class DSAEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign using DSA-SHA1 or ECDSA.
|
* Sign using any key type.
|
||||||
* Uses TheCrypto code unless configured to use the java.security libraries.
|
* Uses TheCrypto code unless configured to use the java.security libraries.
|
||||||
*
|
*
|
||||||
* @return null on error
|
* @return null on error
|
||||||
*/
|
*/
|
||||||
public Signature sign(byte data[], SigningPrivateKey signingKey) {
|
public Signature sign(byte data[], SigningPrivateKey signingKey) {
|
||||||
|
return sign(data, 0, data.length, signingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign using any key type as of 0.9.11 (DSA-SHA1 only prior to that)
|
||||||
|
*
|
||||||
|
* @return null on error
|
||||||
|
*/
|
||||||
|
public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
|
||||||
|
if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
|
||||||
SigType type = signingKey.getType();
|
SigType type = signingKey.getType();
|
||||||
if (type != SigType.DSA_SHA1) {
|
if (type != SigType.DSA_SHA1) {
|
||||||
try {
|
try {
|
||||||
return altSign(data, signingKey);
|
return altSign(data, offset, length, signingKey);
|
||||||
} catch (GeneralSecurityException gse) {
|
} catch (GeneralSecurityException gse) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn(type + " Sign Fail", gse);
|
_log.warn(type + " Sign Fail", gse);
|
||||||
@ -274,23 +284,13 @@ public class DSAEngine {
|
|||||||
}
|
}
|
||||||
if (_useJavaLibs) {
|
if (_useJavaLibs) {
|
||||||
try {
|
try {
|
||||||
return altSignSHA1(data, signingKey);
|
return altSignSHA1(data, offset, length, signingKey);
|
||||||
} catch (GeneralSecurityException gse) {
|
} catch (GeneralSecurityException gse) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Lib Sign Fail, privkey = " + signingKey, gse);
|
_log.warn("Lib Sign Fail, privkey = " + signingKey, gse);
|
||||||
// now try TheCrypto
|
// now try TheCrypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sign(data, 0, data.length, signingKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sign using DSA-SHA1 ONLY
|
|
||||||
*
|
|
||||||
* @return null on error
|
|
||||||
*/
|
|
||||||
public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
|
|
||||||
if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
|
|
||||||
SHA1Hash h = calculateHash(data, offset, length);
|
SHA1Hash h = calculateHash(data, offset, length);
|
||||||
return sign(h, signingKey);
|
return sign(h, signingKey);
|
||||||
}
|
}
|
||||||
@ -495,20 +495,20 @@ public class DSAEngine {
|
|||||||
/**
|
/**
|
||||||
* Generic verify DSA_SHA1, ECDSA, or RSA
|
* Generic verify DSA_SHA1, ECDSA, or RSA
|
||||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
* @since 0.9.9
|
* @since 0.9.9 added off/len 0.9.11
|
||||||
*/
|
*/
|
||||||
private boolean altVerifySig(Signature signature, byte[] data, SigningPublicKey verifyingKey)
|
private boolean altVerifySig(Signature signature, byte[] data, int offset, int len, SigningPublicKey verifyingKey)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
SigType type = signature.getType();
|
SigType type = signature.getType();
|
||||||
if (type != verifyingKey.getType())
|
if (type != verifyingKey.getType())
|
||||||
throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
|
throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
|
||||||
if (type == SigType.DSA_SHA1)
|
if (type == SigType.DSA_SHA1)
|
||||||
return altVerifySigSHA1(signature, data, verifyingKey);
|
return altVerifySigSHA1(signature, data, offset, len, verifyingKey);
|
||||||
|
|
||||||
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||||
PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
|
PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
|
||||||
jsig.initVerify(pubKey);
|
jsig.initVerify(pubKey);
|
||||||
jsig.update(data);
|
jsig.update(data, offset, len);
|
||||||
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -555,13 +555,14 @@ public class DSAEngine {
|
|||||||
/**
|
/**
|
||||||
* Alternate to verifySignature() using java.security libraries.
|
* Alternate to verifySignature() using java.security libraries.
|
||||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
* @since 0.8.7
|
* @since 0.8.7 added off/len 0.9.11
|
||||||
*/
|
*/
|
||||||
private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException {
|
private boolean altVerifySigSHA1(Signature signature, byte[] data, int offset,
|
||||||
|
int len, SigningPublicKey verifyingKey) throws GeneralSecurityException {
|
||||||
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
||||||
PublicKey pubKey = SigUtil.toJavaDSAKey(verifyingKey);
|
PublicKey pubKey = SigUtil.toJavaDSAKey(verifyingKey);
|
||||||
jsig.initVerify(pubKey);
|
jsig.initVerify(pubKey);
|
||||||
jsig.update(data);
|
jsig.update(data, offset, len);
|
||||||
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
||||||
//if (!rv) {
|
//if (!rv) {
|
||||||
// System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData()));
|
// System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData()));
|
||||||
@ -573,17 +574,18 @@ public class DSAEngine {
|
|||||||
/**
|
/**
|
||||||
* Generic sign DSA_SHA1, ECDSA, or RSA
|
* Generic sign DSA_SHA1, ECDSA, or RSA
|
||||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
* @since 0.9.9
|
* @since 0.9.9 added off/len 0.9.11
|
||||||
*/
|
*/
|
||||||
private Signature altSign(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
|
private Signature altSign(byte[] data, int offset, int len,
|
||||||
|
SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||||
SigType type = privateKey.getType();
|
SigType type = privateKey.getType();
|
||||||
if (type == SigType.DSA_SHA1)
|
if (type == SigType.DSA_SHA1)
|
||||||
return altSignSHA1(data, privateKey);
|
return altSignSHA1(data, offset, len, privateKey);
|
||||||
|
|
||||||
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||||
PrivateKey privKey = SigUtil.toJavaKey(privateKey);
|
PrivateKey privKey = SigUtil.toJavaKey(privateKey);
|
||||||
jsig.initSign(privKey, _context.random());
|
jsig.initSign(privKey, _context.random());
|
||||||
jsig.update(data);
|
jsig.update(data, offset, len);
|
||||||
return SigUtil.fromJavaSig(jsig.sign(), type);
|
return SigUtil.fromJavaSig(jsig.sign(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -622,13 +624,14 @@ public class DSAEngine {
|
|||||||
/**
|
/**
|
||||||
* Alternate to sign() using java.security libraries.
|
* Alternate to sign() using java.security libraries.
|
||||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
* @since 0.8.7
|
* @since 0.8.7 added off/len args 0.9.11
|
||||||
*/
|
*/
|
||||||
private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
|
private Signature altSignSHA1(byte[] data, int offset, int len,
|
||||||
|
SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||||
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
||||||
PrivateKey privKey = SigUtil.toJavaDSAKey(privateKey);
|
PrivateKey privKey = SigUtil.toJavaDSAKey(privateKey);
|
||||||
jsig.initSign(privKey, _context.random());
|
jsig.initSign(privKey, _context.random());
|
||||||
jsig.update(data);
|
jsig.update(data, offset, len);
|
||||||
return SigUtil.fromJavaSig(jsig.sign(), SigType.DSA_SHA1);
|
return SigUtil.fromJavaSig(jsig.sign(), SigType.DSA_SHA1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,16 @@ public class Destination extends KeysAndCert {
|
|||||||
PublicKey pk = PublicKey.create(in);
|
PublicKey pk = PublicKey.create(in);
|
||||||
SigningPublicKey sk = SigningPublicKey.create(in);
|
SigningPublicKey sk = SigningPublicKey.create(in);
|
||||||
Certificate c = Certificate.create(in);
|
Certificate c = Certificate.create(in);
|
||||||
|
byte[] padding;
|
||||||
|
if (c.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
|
||||||
|
// convert SPK to new SPK and padding
|
||||||
|
KeyCertificate kcert = c.toKeyCertificate();
|
||||||
|
padding = sk.getPadding(kcert);
|
||||||
|
sk = sk.toTypedKey(kcert);
|
||||||
|
c = kcert;
|
||||||
|
} else {
|
||||||
|
padding = null;
|
||||||
|
}
|
||||||
Destination rv;
|
Destination rv;
|
||||||
synchronized(_cache) {
|
synchronized(_cache) {
|
||||||
rv = _cache.get(sk);
|
rv = _cache.get(sk);
|
||||||
@ -67,7 +77,7 @@ public class Destination extends KeysAndCert {
|
|||||||
}
|
}
|
||||||
//if (STATS)
|
//if (STATS)
|
||||||
// I2PAppContext.getGlobalContext().statManager().addRateData("DestCache", 0);
|
// I2PAppContext.getGlobalContext().statManager().addRateData("DestCache", 0);
|
||||||
rv = new Destination(pk, sk, c);
|
rv = new Destination(pk, sk, c, padding);
|
||||||
_cache.put(sk, rv);
|
_cache.put(sk, rv);
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
@ -86,10 +96,11 @@ public class Destination extends KeysAndCert {
|
|||||||
/**
|
/**
|
||||||
* @since 0.9.9
|
* @since 0.9.9
|
||||||
*/
|
*/
|
||||||
private Destination(PublicKey pk, SigningPublicKey sk, Certificate c) {
|
private Destination(PublicKey pk, SigningPublicKey sk, Certificate c, byte[] padding) {
|
||||||
_publicKey = pk;
|
_publicKey = pk;
|
||||||
_signingKey = sk;
|
_signingKey = sk;
|
||||||
_certificate = c;
|
_certificate = c;
|
||||||
|
_padding = padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,7 +149,16 @@ public class Destination extends KeysAndCert {
|
|||||||
****/
|
****/
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return PublicKey.KEYSIZE_BYTES + _signingKey.length() + _certificate.size();
|
int rv = PublicKey.KEYSIZE_BYTES + _signingKey.length();
|
||||||
|
if (_certificate.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
|
||||||
|
// cert data included in keys
|
||||||
|
rv += 7;
|
||||||
|
if (_padding != null)
|
||||||
|
rv += _padding.length;
|
||||||
|
} else {
|
||||||
|
rv += _certificate.size();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user