SigUtil: Enhance ASN.1 parser/generator to support

signatures up to 64K, needed for ElG
Log and javadoc tweaks
This commit is contained in:
zzz
2016-01-24 19:02:13 +00:00
parent 649d7122a2
commit f38cfcc937

View File

@@ -141,7 +141,7 @@ public final class SigUtil {
throw new IllegalArgumentException("Unknown RSA type"); throw new IllegalArgumentException("Unknown RSA type");
return fromJavaKey(k, type); return fromJavaKey(k, type);
} }
throw new IllegalArgumentException("Unknown type"); throw new IllegalArgumentException("Unknown type: " + pk.getClass());
} }
/** /**
@@ -161,7 +161,7 @@ public final class SigUtil {
case RSA: case RSA:
return fromJavaKey((RSAPublicKey) pk, type); return fromJavaKey((RSAPublicKey) pk, type);
default: default:
throw new IllegalArgumentException(); throw new IllegalArgumentException("Unknown type: " + type);
} }
} }
@@ -209,7 +209,7 @@ public final class SigUtil {
throw new IllegalArgumentException("Unknown RSA type"); throw new IllegalArgumentException("Unknown RSA type");
return fromJavaKey(k, type); return fromJavaKey(k, type);
} }
throw new IllegalArgumentException("Unknown type"); throw new IllegalArgumentException("Unknown type: " + pk.getClass());
} }
/** /**
@@ -229,7 +229,7 @@ public final class SigUtil {
case RSA: case RSA:
return fromJavaKey((RSAPrivateKey) pk, type); return fromJavaKey((RSAPrivateKey) pk, type);
default: default:
throw new IllegalArgumentException(); throw new IllegalArgumentException("Unknown type: " + type);
} }
} }
@@ -661,7 +661,7 @@ public final class SigUtil {
* *
* r and s are always non-negative. * r and s are always non-negative.
* *
* Only supports sigs up to about 252 bytes. See code to fix BER encoding for this before you * Only supports sigs up to about 65530 bytes. See code to fix BER encoding for this before you
* add a SigType with bigger signatures. * add a SigType with bigger signatures.
* *
* @param sig length must be even * @param sig length must be even
@@ -669,42 +669,71 @@ public final class SigUtil {
* @since 0.9.25, split out from sigBytesToASN1(byte[]) * @since 0.9.25, split out from sigBytesToASN1(byte[])
*/ */
public static byte[] sigBytesToASN1(BigInteger r, BigInteger s) { public static byte[] sigBytesToASN1(BigInteger r, BigInteger s) {
int extra = 4;
byte[] rb = r.toByteArray(); byte[] rb = r.toByteArray();
if (rb.length > 127) if (rb.length > 127) {
throw new IllegalArgumentException("FIXME R length > 127"); extra++;
if (rb.length > 255)
extra++;
}
byte[] sb = s.toByteArray(); byte[] sb = s.toByteArray();
if (sb.length > 127) if (sb.length > 127) {
throw new IllegalArgumentException("FIXME S length > 127"); extra++;
int seqlen = rb.length + sb.length + 4; if (sb.length > 255)
if (seqlen > 255) extra++;
throw new IllegalArgumentException("FIXME seq length > 255"); }
int seqlen = rb.length + sb.length + extra;
int totlen = seqlen + 2; int totlen = seqlen + 2;
if (seqlen > 127) if (seqlen > 127) {
totlen++; totlen++;
if (seqlen > 255)
totlen++;
}
byte[] rv = new byte[totlen]; byte[] rv = new byte[totlen];
int idx = 0; int idx = 0;
rv[idx++] = 0x30; rv[idx++] = 0x30;
if (seqlen > 127) idx = intToASN1(rv, idx, seqlen);
rv[idx++] =(byte) 0x81;
rv[idx++] = (byte) seqlen;
rv[idx++] = 0x02; rv[idx++] = 0x02;
rv[idx++] = (byte) rb.length; idx = intToASN1(rv, idx, rb.length);
System.arraycopy(rb, 0, rv, idx, rb.length); System.arraycopy(rb, 0, rv, idx, rb.length);
idx += rb.length; idx += rb.length;
rv[idx++] = 0x02; rv[idx++] = 0x02;
rv[idx++] = (byte) sb.length; idx = intToASN1(rv, idx, sb.length);
System.arraycopy(sb, 0, rv, idx, sb.length); System.arraycopy(sb, 0, rv, idx, sb.length);
//System.out.println("post TO asn1\n" + net.i2p.util.HexDump.dump(rv)); //System.out.println("post TO asn1\n" + net.i2p.util.HexDump.dump(rv));
return rv; return rv;
} }
/**
* Output an length or integer value in ASN.1
* Does NOT output the tag e.g. 0x02 / 0x30
*
* @param val 0-65535
* @return the new index
* @since 0.9.25
*/
private static int intToASN1(byte[] d, int idx, int val) {
if (val < 0 || val > 65535)
throw new IllegalArgumentException("fixme length " + val);
if (val > 127) {
if (val > 255) {
d[idx++] = (byte) 0x82;
d[idx++] = (byte) (val >> 8);
} else {
d[idx++] = (byte) 0x81;
}
}
d[idx++] = (byte) val;
return idx;
}
/** /**
* See above. * See above.
* Only supports sigs up to about 252 bytes. See code to fix BER encoding for bigger than that. * Only supports sigs up to about 65530 bytes. See code to fix BER encoding for bigger than that.
* *
* @param len must be even, twice the nominal length of each BigInteger * @param len must be even, twice the nominal length of each BigInteger
* @return len bytes, call split() on the result to get two BigIntegers * @return len bytes, call split() on the result to get two BigIntegers
@@ -724,8 +753,17 @@ public final class SigUtil {
byte[] rv = new byte[len]; byte[] rv = new byte[len];
int sublen = len / 2; int sublen = len / 2;
int rlen = asn[++idx]; int rlen = asn[++idx];
if ((rlen & 0x80) != 0) if ((rlen & 0x80) != 0) {
throw new SignatureException("FIXME R length > 127"); if ((rlen & 0xff) == 0x81) {
rlen = asn[++idx] & 0xff;
} else if ((rlen & 0xff) == 0x82) {
rlen = asn[++idx] & 0xff;
rlen <<= 8;
rlen |= asn[++idx] & 0xff;
} else {
throw new SignatureException("FIXME R length > 65535");
}
}
if ((asn[++idx] & 0x80) != 0) if ((asn[++idx] & 0x80) != 0)
throw new SignatureException("R is negative"); throw new SignatureException("R is negative");
if (rlen > sublen + 1) if (rlen > sublen + 1)
@@ -735,27 +773,36 @@ public final class SigUtil {
else else
System.arraycopy(asn, idx, rv, sublen - rlen, rlen); System.arraycopy(asn, idx, rv, sublen - rlen, rlen);
idx += rlen; idx += rlen;
int slenloc = idx + 1;
if (asn[idx] != 0x02) if (asn[idx] != 0x02)
throw new SignatureException("asn[s] = " + (asn[idx] & 0xff)); throw new SignatureException("asn[s] = " + (asn[idx] & 0xff));
int slen = asn[slenloc]; int slen = asn[++idx];
if ((slen & 0x80) != 0) if ((slen & 0x80) != 0) {
throw new SignatureException("FIXME S length > 127"); if ((slen & 0xff) == 0x81) {
if ((asn[slenloc + 1] & 0x80) != 0) slen = asn[++idx] & 0xff;
} else if ((slen & 0xff) == 0x82) {
slen = asn[++idx] & 0xff;
slen <<= 8;
slen |= asn[++idx] & 0xff;
} else {
throw new SignatureException("FIXME S length > 65535");
}
}
if ((asn[++idx] & 0x80) != 0)
throw new SignatureException("S is negative"); throw new SignatureException("S is negative");
if (slen > sublen + 1) if (slen > sublen + 1)
throw new SignatureException("S too big " + slen); throw new SignatureException("S too big " + slen);
if (slen == sublen + 1) if (slen == sublen + 1)
System.arraycopy(asn, slenloc + 2, rv, sublen, sublen); System.arraycopy(asn, idx + 1, rv, sublen, sublen);
else else
System.arraycopy(asn, slenloc + 1, rv, len - slen, slen); System.arraycopy(asn, idx, rv, len - slen, slen);
//System.out.println("post from asn1\n" + net.i2p.util.HexDump.dump(rv)); //System.out.println("post from asn1\n" + net.i2p.util.HexDump.dump(rv));
return rv; return rv;
} }
/** /**
* See above. * See above.
* Only supports sigs up to about 252 bytes. See code to fix BER encoding for bigger than that. * Only supports sigs up to about 65530 bytes. See code to fix BER encoding for bigger than that.
* *
* @param len nominal length of each BigInteger * @param len nominal length of each BigInteger
* @return two BigIntegers * @return two BigIntegers