Data: Cache P256 and Ed255i9 key certificates

- Enable P256 caching
 - Create cached Ed25519 cert and enable
 - Fix cached P256 hashcode
This commit is contained in:
zzz
2015-08-31 13:25:58 +00:00
parent f577a94012
commit 7c703953be
4 changed files with 121 additions and 11 deletions

View File

@ -47,16 +47,17 @@ public class Certificate extends DataStructureImpl {
public final static int CERTIFICATE_TYPE_KEY = 5;
/**
* If null cert, return immutable static instance, else create new
* If null, P256 key, or Ed25519 key cert, return immutable static instance, else create new
* @throws DataFormatException if not enough bytes
* @since 0.8.3
*/
public static Certificate create(byte[] data, int off) throws DataFormatException {
int type;
byte[] payload;
int length;
try {
type = data[off] & 0xff;
int length = (int) DataHelper.fromLong(data, off + 1, 2);
length = (int) DataHelper.fromLong(data, off + 1, 2);
if (type == 0 && length == 0)
return NULL_CERT;
// from here down roughly the same as readBytes() below
@ -68,6 +69,12 @@ public class Certificate extends DataStructureImpl {
throw new DataFormatException("not enough bytes", aioobe);
}
if (type == CERTIFICATE_TYPE_KEY) {
if (length == 4) {
if (Arrays.equals(payload, KeyCertificate.Ed25519_PAYLOAD))
return KeyCertificate.ELG_Ed25519_CERT;
if (Arrays.equals(payload, KeyCertificate.ECDSA256_PAYLOAD))
return KeyCertificate.ELG_ECDSA256_CERT;
}
try {
return new KeyCertificate(payload);
} catch (DataFormatException dfe) {
@ -78,7 +85,7 @@ public class Certificate extends DataStructureImpl {
}
/**
* If null cert, return immutable static instance, else create new
* If null, P256 key, or Ed25519 key cert, return immutable static instance, else create new
* @since 0.8.3
*/
public static Certificate create(InputStream in) throws DataFormatException, IOException {
@ -93,8 +100,15 @@ public class Certificate extends DataStructureImpl {
int read = DataHelper.read(in, payload);
if (read != length)
throw new DataFormatException("Not enough bytes for the payload (read: " + read + " length: " + length + ')');
if (type == CERTIFICATE_TYPE_KEY)
if (type == CERTIFICATE_TYPE_KEY) {
if (length == 4) {
if (Arrays.equals(payload, KeyCertificate.Ed25519_PAYLOAD))
return KeyCertificate.ELG_Ed25519_CERT;
if (Arrays.equals(payload, KeyCertificate.ECDSA256_PAYLOAD))
return KeyCertificate.ELG_ECDSA256_CERT;
}
return new KeyCertificate(payload);
}
return new Certificate(type, payload);
}

View File

@ -17,15 +17,41 @@ public class KeyCertificate extends Certificate {
public static final int HEADER_LENGTH = 4;
/** @since 0.9.22 pkg private for Certificate.create() */
static final byte[] Ed25519_PAYLOAD = new byte[] {
0, (byte) (SigType.EdDSA_SHA512_Ed25519.getCode()), 0, 0
};
/** @since 0.9.22 pkg private for Certificate.create() */
static final byte[] ECDSA256_PAYLOAD = new byte[] {
0, (byte) (SigType.ECDSA_SHA256_P256.getCode()), 0, 0
};
/**
* An immutable ElG/ECDSA-P256 certificate.
*/
public static final KeyCertificate ELG_ECDSA256_CERT;
/**
* An immutable ElG/Ed25519 certificate.
* @since 0.9.22
*/
public static final KeyCertificate ELG_Ed25519_CERT;
static {
KeyCertificate kc;
try {
kc = new ECDSA256Cert();
} catch (DataFormatException dfe) {
kc = null; // won't happen
throw new RuntimeException(dfe); // won't happen
}
ELG_ECDSA256_CERT = kc;
try {
kc = new Ed25519Cert();
} catch (DataFormatException dfe) {
throw new RuntimeException(dfe); // won't happen
}
ELG_Ed25519_CERT = kc;
}
/**
@ -185,19 +211,17 @@ public class KeyCertificate extends Certificate {
/**
* An immutable ElG/ECDSA-256 certificate.
* @since 0.8.3
*/
private static final class ECDSA256Cert extends KeyCertificate {
private static final byte[] ECDSA256_DATA = new byte[] {
CERTIFICATE_TYPE_KEY, 0, HEADER_LENGTH, 0, (byte) (SigType.ECDSA_SHA256_P256.getCode()), 0, 0
};
private static final int ECDSA256_LENGTH = ECDSA256_DATA.length;
private static final byte[] ECDSA256_PAYLOAD = new byte[] {
0, (byte) (SigType.ECDSA_SHA256_P256.getCode()), 0, 0
};
private final int _hashcode;
public ECDSA256Cert() throws DataFormatException {
super(ECDSA256_PAYLOAD);
_hashcode = super.hashCode();
}
/** @throws RuntimeException always */
@ -246,7 +270,75 @@ public class KeyCertificate extends Certificate {
/** Overridden for efficiency */
@Override
public int hashCode() {
return 1234567;
return _hashcode;
}
}
/**
* An immutable ElG/Ed25519 certificate.
* @since 0.9.22
*/
private static final class Ed25519Cert extends KeyCertificate {
private static final byte[] ED_DATA = new byte[] { CERTIFICATE_TYPE_KEY,
0, HEADER_LENGTH,
0, (byte) SigType.EdDSA_SHA512_Ed25519.getCode(),
0, 0
};
private static final int ED_LENGTH = ED_DATA.length;
private final int _hashcode;
public Ed25519Cert() throws DataFormatException {
super(Ed25519_PAYLOAD);
_hashcode = super.hashCode();
}
/** @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(ED_DATA);
}
/** Overridden for efficiency */
@Override
public int writeBytes(byte target[], int offset) {
System.arraycopy(ED_DATA, 0, target, offset, ED_LENGTH);
return ED_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 ED_LENGTH;
}
/** Overridden for efficiency */
@Override
public int hashCode() {
return _hashcode;
}
}
}