* Certificate: Use a single static null cert in place of
tens of thousands of them
This commit is contained in:
@ -26,8 +26,10 @@ import java.io.OutputStream;
|
||||
* @author jrandom
|
||||
*/
|
||||
public class Certificate extends DataStructureImpl {
|
||||
private int _type;
|
||||
private byte[] _payload;
|
||||
public final static Certificate NULL_CERT = new NullCert();
|
||||
|
||||
protected int _type;
|
||||
protected byte[] _payload;
|
||||
|
||||
/** Specifies a null certificate type with no payload */
|
||||
public final static int CERTIFICATE_TYPE_NULL = 0;
|
||||
@ -41,6 +43,25 @@ public class Certificate extends DataStructureImpl {
|
||||
/** Contains multiple certs */
|
||||
public final static int CERTIFICATE_TYPE_MULTIPLE = 4;
|
||||
|
||||
/**
|
||||
* If null cert, return immutable static instance, else create new
|
||||
* @since 0.8.3
|
||||
*/
|
||||
public static Certificate create(InputStream in) throws DataFormatException, IOException {
|
||||
int type = (int) DataHelper.readLong(in, 1);
|
||||
int length = (int) DataHelper.readLong(in, 2);
|
||||
if (type == 0 && length == 0)
|
||||
return NULL_CERT;
|
||||
// from here down roughly the same as readBytes() below
|
||||
if (length == 0)
|
||||
return new Certificate(type, null);
|
||||
byte[] payload = new byte[length];
|
||||
int read = DataHelper.read(in, payload);
|
||||
if (read != length)
|
||||
throw new DataFormatException("Not enough bytes for the payload (read: " + read + " length: " + length + ')');
|
||||
return new Certificate(type, payload);
|
||||
}
|
||||
|
||||
public Certificate() {
|
||||
}
|
||||
|
||||
@ -140,10 +161,12 @@ public class Certificate extends DataStructureImpl {
|
||||
Certificate cert = (Certificate) object;
|
||||
return _type == cert.getCertificateType() && DataHelper.eq(_payload, cert.getPayload());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return _type + DataHelper.hashCode(_payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(64);
|
||||
@ -177,4 +200,67 @@ public class Certificate extends DataStructureImpl {
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* An immutable null certificate.
|
||||
* @since 0.8.3
|
||||
*/
|
||||
private static final class NullCert extends Certificate {
|
||||
private static final int NULL_LENGTH = 1 + 2;
|
||||
private static final byte[] NULL_DATA = new byte[NULL_LENGTH];
|
||||
|
||||
public NullCert() {
|
||||
// zero already
|
||||
//_type = CERTIFICATE_TYPE_NULL;
|
||||
}
|
||||
|
||||
/** @throws RuntimeException always */
|
||||
@Override
|
||||
public void setCertificateType(int type) {
|
||||
throw new RuntimeException("Data already set");
|
||||
}
|
||||
|
||||
/** @throws RuntimeException always */
|
||||
@Override
|
||||
public void setPayload(byte[] payload) {
|
||||
throw new RuntimeException("Data already set");
|
||||
}
|
||||
|
||||
/** @throws RuntimeException always */
|
||||
@Override
|
||||
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
||||
throw new RuntimeException("Data already set");
|
||||
}
|
||||
|
||||
/** Overridden for efficiency */
|
||||
@Override
|
||||
public void writeBytes(OutputStream out) throws IOException {
|
||||
out.write(NULL_DATA);
|
||||
}
|
||||
|
||||
/** Overridden for efficiency */
|
||||
@Override
|
||||
public int writeBytes(byte target[], int offset) {
|
||||
System.arraycopy(NULL_DATA, 0, target, offset, NULL_LENGTH);
|
||||
return offset + NULL_LENGTH;
|
||||
}
|
||||
|
||||
/** @throws RuntimeException always */
|
||||
@Override
|
||||
public int readBytes(byte source[], int offset) throws DataFormatException {
|
||||
throw new RuntimeException("Data already set");
|
||||
}
|
||||
|
||||
/** Overridden for efficiency */
|
||||
@Override
|
||||
public int size() {
|
||||
return NULL_LENGTH;
|
||||
}
|
||||
|
||||
/** Overridden for efficiency */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 99999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +65,9 @@ public class KeysAndCert extends DataStructureImpl {
|
||||
_publicKey.readBytes(in);
|
||||
_signingKey = new SigningPublicKey();
|
||||
_signingKey.readBytes(in);
|
||||
_certificate = new Certificate();
|
||||
_certificate.readBytes(in);
|
||||
//_certificate = new Certificate();
|
||||
//_certificate.readBytes(in);
|
||||
_certificate = Certificate.create(in);
|
||||
__calculatedHash = null;
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,9 @@ public class GarlicClove extends DataStructureImpl {
|
||||
_expiration = DataHelper.readDate(in);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("CloveID read: " + _cloveId + " expiration read: " + _expiration);
|
||||
_certificate = new Certificate();
|
||||
_certificate.readBytes(in);
|
||||
//_certificate = new Certificate();
|
||||
//_certificate.readBytes(in);
|
||||
_certificate = Certificate.create(in);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Read cert: " + _certificate);
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ class OutboundClientMessageJobHelper {
|
||||
instructions.setRouter(null);
|
||||
instructions.setTunnelId(null);
|
||||
|
||||
config.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
|
||||
config.setCertificate(Certificate.NULL_CERT);
|
||||
config.setDeliveryInstructions(instructions);
|
||||
config.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
|
||||
config.setExpiration(expiration); // +2*Router.CLOCK_FUDGE_FACTOR);
|
||||
@ -165,7 +165,7 @@ class OutboundClientMessageJobHelper {
|
||||
if (log.shouldLog(Log.DEBUG))
|
||||
log.debug("Delivery status message key: " + replyToken + " arrival: " + msg.getArrival());
|
||||
|
||||
ackClove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
|
||||
ackClove.setCertificate(Certificate.NULL_CERT);
|
||||
ackClove.setDeliveryInstructions(ackInstructions);
|
||||
ackClove.setExpiration(expiration);
|
||||
ackClove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
|
||||
@ -196,7 +196,7 @@ class OutboundClientMessageJobHelper {
|
||||
instructions.setDelaySeconds(0);
|
||||
instructions.setEncrypted(false);
|
||||
|
||||
clove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
|
||||
clove.setCertificate(Certificate.NULL_CERT);
|
||||
clove.setDeliveryInstructions(instructions);
|
||||
clove.setExpiration(expiration);
|
||||
clove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
|
||||
@ -222,7 +222,7 @@ class OutboundClientMessageJobHelper {
|
||||
instructions.setDelaySeconds(0);
|
||||
instructions.setEncrypted(false);
|
||||
|
||||
clove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
|
||||
clove.setCertificate(Certificate.NULL_CERT);
|
||||
clove.setDeliveryInstructions(instructions);
|
||||
clove.setExpiration(expiration);
|
||||
clove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
|
||||
|
@ -872,7 +872,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
||||
instructions.setDelaySeconds(0);
|
||||
instructions.setEncrypted(false);
|
||||
|
||||
clove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
|
||||
clove.setCertificate(Certificate.NULL_CERT);
|
||||
clove.setDeliveryInstructions(instructions);
|
||||
clove.setExpiration(OVERALL_TIMEOUT_MS_DEFAULT+getContext().clock().now());
|
||||
clove.setId(getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE));
|
||||
|
@ -46,7 +46,7 @@ class MessageWrapper {
|
||||
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_LOCAL);
|
||||
|
||||
PayloadGarlicConfig payload = new PayloadGarlicConfig();
|
||||
payload.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
|
||||
payload.setCertificate(Certificate.NULL_CERT);
|
||||
payload.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
|
||||
payload.setPayload(m);
|
||||
payload.setRecipient(to);
|
||||
|
Reference in New Issue
Block a user