forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.test2' (head c182b371bc28158dd47262b89e5bd0cdda29e07b)
to branch 'i2p.i2p' (head 4fc776f7b76b028bb890affccfdcfbefbb932c58)
This commit is contained in:
@ -22,7 +22,6 @@ import net.i2p.crypto.HMACGenerator;
|
||||
import net.i2p.crypto.KeyGenerator;
|
||||
import net.i2p.crypto.SHA256Generator;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.crypto.TransientSessionKeyManager;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.RoutingKeyGenerator;
|
||||
import net.i2p.internal.InternalClientManager;
|
||||
@ -76,7 +75,7 @@ public class I2PAppContext {
|
||||
protected final I2PProperties _overrideProps;
|
||||
|
||||
private StatManager _statManager;
|
||||
private SessionKeyManager _sessionKeyManager;
|
||||
protected SessionKeyManager _sessionKeyManager;
|
||||
private NamingService _namingService;
|
||||
private ElGamalEngine _elGamalEngine;
|
||||
private ElGamalAESEngine _elGamalAESEngine;
|
||||
@ -96,7 +95,7 @@ public class I2PAppContext {
|
||||
private SimpleTimer2 _simpleTimer2;
|
||||
private final PortMapper _portMapper;
|
||||
private volatile boolean _statManagerInitialized;
|
||||
private volatile boolean _sessionKeyManagerInitialized;
|
||||
protected volatile boolean _sessionKeyManagerInitialized;
|
||||
private volatile boolean _namingServiceInitialized;
|
||||
private volatile boolean _elGamalEngineInitialized;
|
||||
private volatile boolean _elGamalAESEngineInitialized;
|
||||
@ -599,6 +598,9 @@ public class I2PAppContext {
|
||||
* For client crypto within the router,
|
||||
* use RouterContext.clientManager.getClientSessionKeyManager(dest)
|
||||
*
|
||||
* As of 0.9.15, this returns a dummy SessionKeyManager in I2PAppContext.
|
||||
* The dummy SKM does NOT handle session tags.
|
||||
* Overridden in RouterContext to return the full TransientSessionKeyManager.
|
||||
*/
|
||||
public SessionKeyManager sessionKeyManager() {
|
||||
if (!_sessionKeyManagerInitialized)
|
||||
@ -606,11 +608,11 @@ public class I2PAppContext {
|
||||
return _sessionKeyManager;
|
||||
}
|
||||
|
||||
private void initializeSessionKeyManager() {
|
||||
protected void initializeSessionKeyManager() {
|
||||
synchronized (_lock3) {
|
||||
if (_sessionKeyManager == null)
|
||||
//_sessionKeyManager = new PersistentSessionKeyManager(this);
|
||||
_sessionKeyManager = new TransientSessionKeyManager(this);
|
||||
_sessionKeyManager = new SessionKeyManager(this);
|
||||
_sessionKeyManagerInitialized = true;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
@ -49,29 +51,36 @@ public class SU3File {
|
||||
private int _versionLength;
|
||||
private String _signer;
|
||||
private int _signerLength;
|
||||
private int _fileType = -1;
|
||||
private ContentType _contentType;
|
||||
private long _contentLength;
|
||||
private PublicKey _signerPubkey;
|
||||
private boolean _headerVerified;
|
||||
private SigType _sigType;
|
||||
private boolean _verifySignature = true;
|
||||
private File _certFile;
|
||||
|
||||
private static final byte[] MAGIC = DataHelper.getUTF8("I2Psu3");
|
||||
public static final String MAGIC = "I2Psu3";
|
||||
private static final byte[] MAGIC_BYTES = DataHelper.getASCII(MAGIC);
|
||||
private static final int FILE_VERSION = 0;
|
||||
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 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_ROUTER = 1;
|
||||
public static final int CONTENT_PLUGIN = 2;
|
||||
public static final int CONTENT_RESEED = 3;
|
||||
public static final int CONTENT_NEWS = 4;
|
||||
|
||||
private enum ContentType {
|
||||
UNKNOWN(CONTENT_UNKNOWN, "unknown"),
|
||||
ROUTER(CONTENT_ROUTER, "router"),
|
||||
PLUGIN(CONTENT_PLUGIN, "plugin"),
|
||||
RESEED(CONTENT_RESEED, "reseed")
|
||||
RESEED(CONTENT_RESEED, "reseed"),
|
||||
NEWS(CONTENT_NEWS, "news")
|
||||
;
|
||||
|
||||
private final int code;
|
||||
@ -125,17 +134,44 @@ public class SU3File {
|
||||
_file = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the signature be verified? Default true
|
||||
* @since 0.9.15
|
||||
*/
|
||||
public void setVerifySignature(boolean shouldVerify) {
|
||||
_verifySignature = shouldVerify;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this X.509 cert file for verification instead of $I2P/certificates/content_type/foo_at_mail.i2p
|
||||
* @since 0.9.15
|
||||
*/
|
||||
private void setPublicKeyCertificate(File certFile) {
|
||||
_certFile = certFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* This does not check the signature, but it will fail if the signer is unknown,
|
||||
* unless setVerifySignature(false) has been called.
|
||||
*/
|
||||
public String getVersionString() throws IOException {
|
||||
verifyHeader();
|
||||
return _version;
|
||||
}
|
||||
|
||||
/**
|
||||
* This does not check the signature, but it will fail if the signer is unknown,
|
||||
* unless setVerifySignature(false) has been called.
|
||||
*/
|
||||
public String getSignerString() throws IOException {
|
||||
verifyHeader();
|
||||
return _signer;
|
||||
}
|
||||
|
||||
/**
|
||||
* This does not check the signature, but it will fail if the signer is unknown,
|
||||
* unless setVerifySignature(false) has been called.
|
||||
*
|
||||
* @return null if unknown
|
||||
* @since 0.9.9
|
||||
*/
|
||||
@ -145,6 +181,9 @@ public class SU3File {
|
||||
}
|
||||
|
||||
/**
|
||||
* This does not check the signature, but it will fail if the signer is unknown,
|
||||
* unless setVerifySignature(false) has been called.
|
||||
*
|
||||
* @return -1 if unknown
|
||||
* @since 0.9.9
|
||||
*/
|
||||
@ -154,6 +193,21 @@ public class SU3File {
|
||||
}
|
||||
|
||||
/**
|
||||
* This does not check the signature, but it will fail if the signer is unknown,
|
||||
* unless setVerifySignature(false) has been called.
|
||||
*
|
||||
* @return -1 if unknown
|
||||
* @since 0.9.15
|
||||
*/
|
||||
public int getFileType() throws IOException {
|
||||
verifyHeader();
|
||||
return _fileType;
|
||||
}
|
||||
|
||||
/**
|
||||
* This does not check the signature, but it will fail if the signer is unknown,
|
||||
* unless setVerifySignature(false) has been called.
|
||||
*
|
||||
* Throws IOE if verify vails.
|
||||
*/
|
||||
public void verifyHeader() throws IOException {
|
||||
@ -176,9 +230,9 @@ public class SU3File {
|
||||
* Throws if verify vails.
|
||||
*/
|
||||
private void verifyHeader(InputStream in) throws IOException, DataFormatException {
|
||||
byte[] magic = new byte[MAGIC.length];
|
||||
byte[] magic = new byte[MAGIC_BYTES.length];
|
||||
DataHelper.read(in, magic);
|
||||
if (!DataHelper.eq(magic, MAGIC))
|
||||
if (!DataHelper.eq(magic, MAGIC_BYTES))
|
||||
throw new IOException("Not an su3 file");
|
||||
skip(in, 1);
|
||||
int foo = in.read();
|
||||
@ -204,9 +258,9 @@ public class SU3File {
|
||||
if (_contentLength <= 0)
|
||||
throw new IOException("bad content length");
|
||||
skip(in, 1);
|
||||
foo = in.read();
|
||||
if (foo != TYPE_ZIP)
|
||||
throw new IOException("bad type");
|
||||
_fileType = in.read();
|
||||
if (_fileType != TYPE_ZIP && _fileType != TYPE_XML)
|
||||
throw new IOException("bad file type");
|
||||
skip(in, 1);
|
||||
int cType = in.read();
|
||||
_contentType = BY_CODE.get(Integer.valueOf(cType));
|
||||
@ -231,17 +285,22 @@ public class SU3File {
|
||||
throw new EOFException();
|
||||
_signer = DataHelper.getUTF8(data);
|
||||
|
||||
KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates"));
|
||||
try {
|
||||
_signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
IOException ioe = new IOException("keystore error");
|
||||
ioe.initCause(gse);
|
||||
throw ioe;
|
||||
if (_verifySignature) {
|
||||
if (_certFile != null) {
|
||||
_signerPubkey = loadKey(_certFile);
|
||||
} else {
|
||||
KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates"));
|
||||
try {
|
||||
_signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
IOException ioe = new IOException("keystore error");
|
||||
ioe.initCause(gse);
|
||||
throw ioe;
|
||||
}
|
||||
if (_signerPubkey == null)
|
||||
throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (_signerPubkey == null)
|
||||
throw new IOException("unknown signer: " + _signer);
|
||||
_headerVerified = true;
|
||||
}
|
||||
|
||||
@ -287,9 +346,9 @@ public class SU3File {
|
||||
// read 10 bytes to get the sig type
|
||||
in.mark(10);
|
||||
// following is a dup of that in verifyHeader()
|
||||
byte[] magic = new byte[MAGIC.length];
|
||||
byte[] magic = new byte[MAGIC_BYTES.length];
|
||||
DataHelper.read(in, magic);
|
||||
if (!DataHelper.eq(magic, MAGIC))
|
||||
if (!DataHelper.eq(magic, MAGIC_BYTES))
|
||||
throw new IOException("Not an su3 file");
|
||||
skip(in, 1);
|
||||
int foo = in.read();
|
||||
@ -310,8 +369,10 @@ public class SU3File {
|
||||
verifyHeader(in);
|
||||
else
|
||||
skip(in, getContentOffset());
|
||||
if (_signerPubkey == null)
|
||||
throw new IOException("unknown signer: " + _signer);
|
||||
if (_verifySignature) {
|
||||
if (_signerPubkey == null)
|
||||
throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName());
|
||||
}
|
||||
if (migrateTo != null) // else verify only
|
||||
out = new FileOutputStream(migrateTo);
|
||||
byte[] buf = new byte[16*1024];
|
||||
@ -324,15 +385,19 @@ public class SU3File {
|
||||
out.write(buf, 0, read);
|
||||
tot += read;
|
||||
}
|
||||
byte[] sha = md.digest();
|
||||
din.on(false);
|
||||
Signature signature = new Signature(_sigType);
|
||||
signature.readBytes(in);
|
||||
SimpleDataStructure hash = _sigType.getHashInstance();
|
||||
hash.setData(sha);
|
||||
//System.out.println("hash\n" + HexDump.dump(sha));
|
||||
//System.out.println("sig\n" + HexDump.dump(signature.getData()));
|
||||
rv = _context.dsa().verifySignature(signature, hash, _signerPubkey);
|
||||
if (_verifySignature) {
|
||||
byte[] sha = md.digest();
|
||||
din.on(false);
|
||||
Signature signature = new Signature(_sigType);
|
||||
signature.readBytes(in);
|
||||
SimpleDataStructure hash = _sigType.getHashInstance();
|
||||
hash.setData(sha);
|
||||
//System.out.println("hash\n" + HexDump.dump(sha));
|
||||
//System.out.println("sig\n" + HexDump.dump(signature.getData()));
|
||||
rv = _context.dsa().verifySignature(signature, hash, _signerPubkey);
|
||||
} else {
|
||||
rv = true;
|
||||
}
|
||||
} catch (DataFormatException dfe) {
|
||||
IOException ioe = new IOException("foo");
|
||||
ioe.initCause(dfe);
|
||||
@ -352,11 +417,12 @@ public class SU3File {
|
||||
* Throws on all errors.
|
||||
*
|
||||
* @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 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 {
|
||||
InputStream in = null;
|
||||
DigestOutputStream out = null;
|
||||
@ -365,7 +431,7 @@ public class SU3File {
|
||||
in = new BufferedInputStream(new FileInputStream(content));
|
||||
MessageDigest md = sigType.getDigestInstance();
|
||||
out = new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(_file)), md);
|
||||
out.write(MAGIC);
|
||||
out.write(MAGIC_BYTES);
|
||||
out.write((byte) 0);
|
||||
out.write((byte) FILE_VERSION);
|
||||
DataHelper.writeLong(out, 2, sigType.getCode());
|
||||
@ -386,7 +452,9 @@ public class SU3File {
|
||||
throw new IllegalArgumentException("No content");
|
||||
DataHelper.writeLong(out, 8, contentLength);
|
||||
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);
|
||||
if (contentType < 0 || contentType > 255)
|
||||
throw new IllegalArgumentException("bad content type");
|
||||
@ -443,8 +511,11 @@ public class SU3File {
|
||||
// defaults
|
||||
String stype = null;
|
||||
String ctype = null;
|
||||
String ftype = null;
|
||||
String kfile = null;
|
||||
boolean error = false;
|
||||
Getopt g = new Getopt("SU3File", args, "t:c:");
|
||||
boolean shouldVerify = true;
|
||||
Getopt g = new Getopt("SU3File", args, "t:c:f:k:x");
|
||||
int c;
|
||||
while ((c = g.getopt()) != -1) {
|
||||
switch (c) {
|
||||
@ -456,6 +527,18 @@ public class SU3File {
|
||||
ctype = g.getOptarg();
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
ftype = g.getOptarg();
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
kfile = g.getOptarg();
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
shouldVerify = false;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case ':':
|
||||
default:
|
||||
@ -476,18 +559,18 @@ public class SU3File {
|
||||
Properties props = new Properties();
|
||||
props.setProperty("prng.bufferSize", "16384");
|
||||
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)) {
|
||||
Properties props = new Properties();
|
||||
props.setProperty("prng.bufferSize", "16384");
|
||||
new I2PAppContext(props);
|
||||
ok = bulkSignCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3));
|
||||
} else if ("verifysig".equals(cmd)) {
|
||||
ok = verifySigCLI(a.get(0));
|
||||
ok = verifySigCLI(a.get(0), kfile);
|
||||
} else if ("keygen".equals(cmd)) {
|
||||
ok = genKeysCLI(stype, a.get(0), a.get(1), a.get(2));
|
||||
} else if ("extract".equals(cmd)) {
|
||||
ok = extractCLI(a.get(0), a.get(1));
|
||||
ok = extractCLI(a.get(0), a.get(1), shouldVerify);
|
||||
} else {
|
||||
showUsageCLI();
|
||||
}
|
||||
@ -502,11 +585,11 @@ public class SU3File {
|
||||
|
||||
private static final void showUsageCLI() {
|
||||
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 bulksign [-c type|code] [-t type|code] directory 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 [-t type|code] [-c type|code] directory keystore.ks version you@mail.i2p");
|
||||
System.err.println(" SU3File showversion signedFile.su3");
|
||||
System.err.println(" SU3File verifysig signedFile.su3");
|
||||
System.err.println(" SU3File extract signedFile.su3 outFile.zip");
|
||||
System.err.println(" SU3File verifysig [-k file.crt] signedFile.su3 ## -k use this pubkey cert for verification");
|
||||
System.err.println(" SU3File extract [-x] [-k file.crt] signedFile.su3 outFile ## -x don't check sig");
|
||||
System.err.println(dumpTypes());
|
||||
}
|
||||
|
||||
@ -529,6 +612,9 @@ public class SU3File {
|
||||
buf.append(" DEFAULT");
|
||||
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();
|
||||
}
|
||||
|
||||
@ -554,6 +640,7 @@ public class SU3File {
|
||||
private static final boolean showVersionCLI(String signedFile) {
|
||||
try {
|
||||
SU3File file = new SU3File(signedFile);
|
||||
file.setVerifySignature(false);
|
||||
String versionString = file.getVersionString();
|
||||
if (versionString.equals(""))
|
||||
System.out.println("No version string found in file '" + signedFile + "'");
|
||||
@ -574,6 +661,7 @@ public class SU3File {
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip only
|
||||
* @return success
|
||||
* @since 0.9.9
|
||||
*/
|
||||
@ -593,7 +681,12 @@ public class SU3File {
|
||||
try {
|
||||
while (keypw.length() < 6) {
|
||||
System.out.print("Enter password for key \"" + signerName + "\": ");
|
||||
keypw = DataHelper.readLine(System.in).trim();
|
||||
keypw = DataHelper.readLine(System.in);
|
||||
if (keypw == null) {
|
||||
System.out.println("\nEOF reading password");
|
||||
return false;
|
||||
}
|
||||
keypw = keypw.trim();
|
||||
if (keypw.length() > 0 && keypw.length() < 6)
|
||||
System.out.println("Key password must be at least 6 characters");
|
||||
}
|
||||
@ -608,7 +701,7 @@ public class SU3File {
|
||||
if (!inputFile.endsWith(".zip"))
|
||||
continue;
|
||||
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)
|
||||
return false;
|
||||
success++;
|
||||
@ -622,7 +715,7 @@ public class SU3File {
|
||||
* @return success
|
||||
* @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) {
|
||||
SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : SigType.parseSigType(stype);
|
||||
if (type == null) {
|
||||
@ -634,19 +727,42 @@ public class SU3File {
|
||||
System.out.println("Content type " + ctype + " is not supported");
|
||||
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
|
||||
* @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) {
|
||||
try {
|
||||
while (keypw.length() < 6) {
|
||||
System.out.print("Enter password for key \"" + signerName + "\": ");
|
||||
keypw = DataHelper.readLine(System.in).trim();
|
||||
keypw = DataHelper.readLine(System.in);
|
||||
if (keypw == null) {
|
||||
System.out.println("\nEOF reading password");
|
||||
return false;
|
||||
}
|
||||
keypw = keypw.trim();
|
||||
if (keypw.length() > 0 && keypw.length() < 6)
|
||||
System.out.println("Key password must be at least 6 characters");
|
||||
}
|
||||
@ -657,7 +773,7 @@ public class SU3File {
|
||||
return false;
|
||||
}
|
||||
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 + "'");
|
||||
return true;
|
||||
} catch (GeneralSecurityException gse) {
|
||||
@ -672,10 +788,12 @@ public class SU3File {
|
||||
}
|
||||
|
||||
/** @return valid */
|
||||
private static final boolean verifySigCLI(String signedFile) {
|
||||
private static final boolean verifySigCLI(String signedFile, String pkFile) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
SU3File file = new SU3File(signedFile);
|
||||
if (pkFile != null)
|
||||
file.setPublicKeyCertificate(new File(pkFile));
|
||||
boolean isValidSignature = file.verify();
|
||||
if (isValidSignature)
|
||||
System.out.println("Signature VALID (signed by " + file.getSignerString() + ' ' + file._sigType + ')');
|
||||
@ -693,10 +811,11 @@ public class SU3File {
|
||||
* @return success
|
||||
* @since 0.9.9
|
||||
*/
|
||||
private static final boolean extractCLI(String signedFile, String outFile) {
|
||||
private static final boolean extractCLI(String signedFile, String outFile, boolean verifySig) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
SU3File file = new SU3File(signedFile);
|
||||
file.setVerifySignature(verifySig);
|
||||
File out = new File(outFile);
|
||||
boolean ok = file.verifyAndMigrate(out);
|
||||
if (ok)
|
||||
@ -740,11 +859,21 @@ public class SU3File {
|
||||
try {
|
||||
while (alias.length() == 0) {
|
||||
System.out.print("Enter key name (example@mail.i2p): ");
|
||||
alias = DataHelper.readLine(System.in).trim();
|
||||
alias = DataHelper.readLine(System.in);
|
||||
if (alias == null) {
|
||||
System.out.println("\nEOF reading key name");
|
||||
return false;
|
||||
}
|
||||
alias = alias.trim();
|
||||
}
|
||||
while (keypw.length() < 6) {
|
||||
System.out.print("Enter new key password: ");
|
||||
keypw = DataHelper.readLine(System.in).trim();
|
||||
keypw = DataHelper.readLine(System.in);
|
||||
if (keypw == null) {
|
||||
System.out.println("\nEOF reading password");
|
||||
return false;
|
||||
}
|
||||
keypw = keypw.trim();
|
||||
if (keypw.length() > 0 && keypw.length() < 6)
|
||||
System.out.println("Key password must be at least 6 characters");
|
||||
}
|
||||
@ -772,4 +901,26 @@ public class SU3File {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* For the -k CLI option
|
||||
* @return non-null, throws IOE on all errors
|
||||
* @since 0.9.15
|
||||
*/
|
||||
private static PublicKey loadKey(File kd) throws IOException {
|
||||
InputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(kd);
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
|
||||
cert.checkValidity();
|
||||
return cert.getPublicKey();
|
||||
} catch (GeneralSecurityException gse) {
|
||||
IOException ioe = new IOException("cert error");
|
||||
ioe.initCause(gse);
|
||||
throw ioe;
|
||||
} finally {
|
||||
try { if (fis != null) fis.close(); } catch (IOException foo) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +178,29 @@ public enum SigType {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if supported in this JVM
|
||||
* @since 0.9.15
|
||||
*/
|
||||
public static boolean isAvailable(int code) {
|
||||
SigType type = getByCode(code);
|
||||
if (type == null)
|
||||
return false;
|
||||
return type.isAvailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stype number or name
|
||||
* @return true if supported in this JVM
|
||||
* @since 0.9.15
|
||||
*/
|
||||
public static boolean isAvailable(String stype) {
|
||||
SigType type = parseSigType(stype);
|
||||
if (type == null)
|
||||
return false;
|
||||
return type.isAvailable();
|
||||
}
|
||||
|
||||
private static final Map<Integer, SigType> BY_CODE = new HashMap<Integer, SigType>();
|
||||
|
||||
static {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,7 @@ public class Base32 {
|
||||
};
|
||||
|
||||
private final static byte BAD_ENCODING = -9; // Indicates error in encoding
|
||||
|
||||
/** Defeats instantiation. */
|
||||
private Base32() { // nop
|
||||
}
|
||||
@ -136,6 +137,9 @@ public class Base32 {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns lower case.
|
||||
* Does not add trailing '='.
|
||||
*
|
||||
* @param source if null will return ""
|
||||
*/
|
||||
public static String encode(String source) {
|
||||
@ -143,6 +147,9 @@ public class Base32 {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns lower case.
|
||||
* Does not add trailing '='.
|
||||
*
|
||||
* @param source The data to convert non-null
|
||||
*/
|
||||
public static String encode(byte[] source) {
|
||||
@ -182,6 +189,8 @@ public class Base32 {
|
||||
/**
|
||||
* Decodes data from Base32 notation and
|
||||
* returns it as a string.
|
||||
* Case-insensitive.
|
||||
* Does not allow trailing '='.
|
||||
*
|
||||
* @param s the string to decode, if null returns null
|
||||
* @return The data as a string or null on failure
|
||||
@ -194,6 +203,9 @@ public class Base32 {
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive.
|
||||
* Does not allow trailing '='.
|
||||
*
|
||||
* @param s non-null
|
||||
* @return decoded data, null on error
|
||||
*/
|
||||
|
@ -130,17 +130,19 @@ public class KeysAndCert extends DataStructureImpl {
|
||||
&& DataHelper.eq(_certificate, ident._certificate);
|
||||
}
|
||||
|
||||
/** the public key has enough randomness in it to use it by itself for speed */
|
||||
/** the signing key has enough randomness in it to use it by itself for speed */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (_publicKey == null)
|
||||
// don't use public key, some app devs thinking of using
|
||||
// an all-zeros or leading-zeros public key for destinations
|
||||
if (_signingKey == null)
|
||||
return 0;
|
||||
return _publicKey.hashCode();
|
||||
return _signingKey.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(64);
|
||||
StringBuilder buf = new StringBuilder(256);
|
||||
buf.append('[').append(getClass().getSimpleName()).append(": ");
|
||||
buf.append("\n\tHash: ").append(getHash().toBase64());
|
||||
buf.append("\n\tCertificate: ").append(_certificate);
|
||||
|
Reference in New Issue
Block a user