forked from I2P_Developers/i2p.i2p
SU3File: Add support for XML and NEWS types
This commit is contained in:
@@ -49,6 +49,7 @@ public class SU3File {
|
|||||||
private int _versionLength;
|
private int _versionLength;
|
||||||
private String _signer;
|
private String _signer;
|
||||||
private int _signerLength;
|
private int _signerLength;
|
||||||
|
private int _fileType = -1;
|
||||||
private ContentType _contentType;
|
private ContentType _contentType;
|
||||||
private long _contentLength;
|
private long _contentLength;
|
||||||
private PublicKey _signerPubkey;
|
private PublicKey _signerPubkey;
|
||||||
@@ -60,18 +61,21 @@ public class SU3File {
|
|||||||
private static final int MIN_VERSION_BYTES = 16;
|
private static final int MIN_VERSION_BYTES = 16;
|
||||||
private static final int VERSION_OFFSET = 40; // Signature.SIGNATURE_BYTES; avoid early ctx init
|
private static final int VERSION_OFFSET = 40; // Signature.SIGNATURE_BYTES; avoid early ctx init
|
||||||
|
|
||||||
private static final int TYPE_ZIP = 0;
|
public static final int TYPE_ZIP = 0;
|
||||||
|
public static final int TYPE_XML = 1;
|
||||||
|
|
||||||
public static final int CONTENT_UNKNOWN = 0;
|
public static final int CONTENT_UNKNOWN = 0;
|
||||||
public static final int CONTENT_ROUTER = 1;
|
public static final int CONTENT_ROUTER = 1;
|
||||||
public static final int CONTENT_PLUGIN = 2;
|
public static final int CONTENT_PLUGIN = 2;
|
||||||
public static final int CONTENT_RESEED = 3;
|
public static final int CONTENT_RESEED = 3;
|
||||||
|
public static final int CONTENT_NEWS = 4;
|
||||||
|
|
||||||
private enum ContentType {
|
private enum ContentType {
|
||||||
UNKNOWN(CONTENT_UNKNOWN, "unknown"),
|
UNKNOWN(CONTENT_UNKNOWN, "unknown"),
|
||||||
ROUTER(CONTENT_ROUTER, "router"),
|
ROUTER(CONTENT_ROUTER, "router"),
|
||||||
PLUGIN(CONTENT_PLUGIN, "plugin"),
|
PLUGIN(CONTENT_PLUGIN, "plugin"),
|
||||||
RESEED(CONTENT_RESEED, "reseed")
|
RESEED(CONTENT_RESEED, "reseed"),
|
||||||
|
NEWS(CONTENT_NEWS, "news")
|
||||||
;
|
;
|
||||||
|
|
||||||
private final int code;
|
private final int code;
|
||||||
@@ -153,6 +157,15 @@ public class SU3File {
|
|||||||
return _contentType != null ? _contentType.getCode() : -1;
|
return _contentType != null ? _contentType.getCode() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return -1 if unknown
|
||||||
|
* @since 0.9.15
|
||||||
|
*/
|
||||||
|
public int getFileType() throws IOException {
|
||||||
|
verifyHeader();
|
||||||
|
return _fileType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws IOE if verify vails.
|
* Throws IOE if verify vails.
|
||||||
*/
|
*/
|
||||||
@@ -204,9 +217,9 @@ public class SU3File {
|
|||||||
if (_contentLength <= 0)
|
if (_contentLength <= 0)
|
||||||
throw new IOException("bad content length");
|
throw new IOException("bad content length");
|
||||||
skip(in, 1);
|
skip(in, 1);
|
||||||
foo = in.read();
|
_fileType = in.read();
|
||||||
if (foo != TYPE_ZIP)
|
if (_fileType != TYPE_ZIP && _fileType != TYPE_XML)
|
||||||
throw new IOException("bad type");
|
throw new IOException("bad file type");
|
||||||
skip(in, 1);
|
skip(in, 1);
|
||||||
int cType = in.read();
|
int cType = in.read();
|
||||||
_contentType = BY_CODE.get(Integer.valueOf(cType));
|
_contentType = BY_CODE.get(Integer.valueOf(cType));
|
||||||
@@ -352,11 +365,12 @@ public class SU3File {
|
|||||||
* Throws on all errors.
|
* Throws on all errors.
|
||||||
*
|
*
|
||||||
* @param content the input file, probably in zip format
|
* @param content the input file, probably in zip format
|
||||||
* @param contentType 0-255, 0 for zip
|
* @param fileType 0-255, 0 for zip
|
||||||
|
* @param contentType 0-255
|
||||||
* @param version 1-255 bytes when converted to UTF-8
|
* @param version 1-255 bytes when converted to UTF-8
|
||||||
* @param signer ID of the public key, 1-255 bytes when converted to UTF-8
|
* @param signer ID of the public key, 1-255 bytes when converted to UTF-8
|
||||||
*/
|
*/
|
||||||
public void write(File content, int contentType, String version,
|
public void write(File content, int fileType, int contentType, String version,
|
||||||
String signer, PrivateKey privkey, SigType sigType) throws IOException {
|
String signer, PrivateKey privkey, SigType sigType) throws IOException {
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
DigestOutputStream out = null;
|
DigestOutputStream out = null;
|
||||||
@@ -386,7 +400,9 @@ public class SU3File {
|
|||||||
throw new IllegalArgumentException("No content");
|
throw new IllegalArgumentException("No content");
|
||||||
DataHelper.writeLong(out, 8, contentLength);
|
DataHelper.writeLong(out, 8, contentLength);
|
||||||
out.write((byte) 0);
|
out.write((byte) 0);
|
||||||
out.write((byte) TYPE_ZIP);
|
if (fileType < 0 || fileType > 255)
|
||||||
|
throw new IllegalArgumentException("bad content type");
|
||||||
|
out.write((byte) fileType);
|
||||||
out.write((byte) 0);
|
out.write((byte) 0);
|
||||||
if (contentType < 0 || contentType > 255)
|
if (contentType < 0 || contentType > 255)
|
||||||
throw new IllegalArgumentException("bad content type");
|
throw new IllegalArgumentException("bad content type");
|
||||||
@@ -443,8 +459,9 @@ public class SU3File {
|
|||||||
// defaults
|
// defaults
|
||||||
String stype = null;
|
String stype = null;
|
||||||
String ctype = null;
|
String ctype = null;
|
||||||
|
String ftype = null;
|
||||||
boolean error = false;
|
boolean error = false;
|
||||||
Getopt g = new Getopt("SU3File", args, "t:c:");
|
Getopt g = new Getopt("SU3File", args, "t:c:f:");
|
||||||
int c;
|
int c;
|
||||||
while ((c = g.getopt()) != -1) {
|
while ((c = g.getopt()) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -456,6 +473,10 @@ public class SU3File {
|
|||||||
ctype = g.getOptarg();
|
ctype = g.getOptarg();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
ftype = g.getOptarg();
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
case ':':
|
case ':':
|
||||||
default:
|
default:
|
||||||
@@ -476,7 +497,7 @@ public class SU3File {
|
|||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.setProperty("prng.bufferSize", "16384");
|
props.setProperty("prng.bufferSize", "16384");
|
||||||
new I2PAppContext(props);
|
new I2PAppContext(props);
|
||||||
ok = signCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4), "");
|
ok = signCLI(stype, ctype, ftype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4), "");
|
||||||
} else if ("bulksign".equals(cmd)) {
|
} else if ("bulksign".equals(cmd)) {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.setProperty("prng.bufferSize", "16384");
|
props.setProperty("prng.bufferSize", "16384");
|
||||||
@@ -502,11 +523,11 @@ public class SU3File {
|
|||||||
|
|
||||||
private static final void showUsageCLI() {
|
private static final void showUsageCLI() {
|
||||||
System.err.println("Usage: SU3File keygen [-t type|code] publicKeyFile keystore.ks you@mail.i2p");
|
System.err.println("Usage: SU3File keygen [-t type|code] publicKeyFile keystore.ks you@mail.i2p");
|
||||||
System.err.println(" SU3File sign [-c type|code] [-t type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p");
|
System.err.println(" SU3File sign [-t type|code] [-c type|code] [-f type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p");
|
||||||
System.err.println(" SU3File bulksign [-c type|code] [-t type|code] directory keystore.ks version you@mail.i2p");
|
System.err.println(" SU3File bulksign [-t type|code] [-c type|code] directory keystore.ks version you@mail.i2p");
|
||||||
System.err.println(" SU3File showversion signedFile.su3");
|
System.err.println(" SU3File showversion signedFile.su3");
|
||||||
System.err.println(" SU3File verifysig signedFile.su3");
|
System.err.println(" SU3File verifysig signedFile.su3");
|
||||||
System.err.println(" SU3File extract signedFile.su3 outFile.zip");
|
System.err.println(" SU3File extract signedFile.su3 outFile");
|
||||||
System.err.println(dumpTypes());
|
System.err.println(dumpTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +550,9 @@ public class SU3File {
|
|||||||
buf.append(" DEFAULT");
|
buf.append(" DEFAULT");
|
||||||
buf.append('\n');
|
buf.append('\n');
|
||||||
}
|
}
|
||||||
|
buf.append("Available file types (-f):\n");
|
||||||
|
buf.append(" ZIP\t(code: 0) DEFAULT\n");
|
||||||
|
buf.append(" XML\t(code: 1)\n");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,6 +598,7 @@ public class SU3File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Zip only
|
||||||
* @return success
|
* @return success
|
||||||
* @since 0.9.9
|
* @since 0.9.9
|
||||||
*/
|
*/
|
||||||
@@ -608,7 +633,7 @@ public class SU3File {
|
|||||||
if (!inputFile.endsWith(".zip"))
|
if (!inputFile.endsWith(".zip"))
|
||||||
continue;
|
continue;
|
||||||
String signedFile = inputFile.substring(0, inputFile.length() - 4) + ".su3";
|
String signedFile = inputFile.substring(0, inputFile.length() - 4) + ".su3";
|
||||||
boolean rv = signCLI(stype, ctype, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
|
boolean rv = signCLI(stype, ctype, null, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
|
||||||
if (!rv)
|
if (!rv)
|
||||||
return false;
|
return false;
|
||||||
success++;
|
success++;
|
||||||
@@ -622,7 +647,7 @@ public class SU3File {
|
|||||||
* @return success
|
* @return success
|
||||||
* @since 0.9.9
|
* @since 0.9.9
|
||||||
*/
|
*/
|
||||||
private static final boolean signCLI(String stype, String ctype, String inputFile, String signedFile,
|
private static final boolean signCLI(String stype, String ctype, String ftype, String inputFile, String signedFile,
|
||||||
String privateKeyFile, String version, String signerName, String keypw) {
|
String privateKeyFile, String version, String signerName, String keypw) {
|
||||||
SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : SigType.parseSigType(stype);
|
SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : SigType.parseSigType(stype);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
@@ -634,14 +659,32 @@ public class SU3File {
|
|||||||
System.out.println("Content type " + ctype + " is not supported");
|
System.out.println("Content type " + ctype + " is not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return signCLI(type, ct, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
|
int ft = TYPE_ZIP;
|
||||||
|
if (ftype != null) {
|
||||||
|
if (ftype.equalsIgnoreCase("ZIP")) {
|
||||||
|
ft = TYPE_ZIP;
|
||||||
|
} else if (ftype.equalsIgnoreCase("XML")) {
|
||||||
|
ft = TYPE_XML;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
ft = Integer.parseInt(ftype);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
ft = -1;
|
||||||
|
}
|
||||||
|
if (ft != TYPE_ZIP && ft != TYPE_XML) {
|
||||||
|
System.out.println("File type " + ftype + " is not supported");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return signCLI(type, ct, ft, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return success
|
* @return success
|
||||||
* @since 0.9.9
|
* @since 0.9.9
|
||||||
*/
|
*/
|
||||||
private static final boolean signCLI(SigType type, ContentType ctype, String inputFile, String signedFile,
|
private static final boolean signCLI(SigType type, ContentType ctype, int ftype, String inputFile, String signedFile,
|
||||||
String privateKeyFile, String version, String signerName, String keypw) {
|
String privateKeyFile, String version, String signerName, String keypw) {
|
||||||
try {
|
try {
|
||||||
while (keypw.length() < 6) {
|
while (keypw.length() < 6) {
|
||||||
@@ -657,7 +700,7 @@ public class SU3File {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SU3File file = new SU3File(signedFile);
|
SU3File file = new SU3File(signedFile);
|
||||||
file.write(new File(inputFile), ctype.getCode(), version, signerName, pk, type);
|
file.write(new File(inputFile), ftype, ctype.getCode(), version, signerName, pk, type);
|
||||||
System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'");
|
System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'");
|
||||||
return true;
|
return true;
|
||||||
} catch (GeneralSecurityException gse) {
|
} catch (GeneralSecurityException gse) {
|
||||||
|
Reference in New Issue
Block a user