use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class ProofHelper method getProof.
public String getProof() {
StringBuilder buf = new StringBuilder(512);
RouterInfo us = _context.router().getRouterInfo();
buf.append("Hash: ").append(us.getIdentity().calculateHash().toBase64()).append('\n');
// buf.append("Ident: ").append(us.getIdentity().toBase64()).append('\n');
for (RouterAddress addr : us.getAddresses()) {
buf.append(addr.getTransportStyle()).append(": ").append(addr.getHost()).append('\n');
}
buf.append("Caps: ").append(us.getCapabilities()).append('\n');
// no trailing newline
buf.append("Date: ").append(new Date());
String msg = buf.toString();
byte[] data = DataHelper.getUTF8(msg);
Signature sig = _context.dsa().sign(data, _context.keyManager().getSigningPrivateKey());
buf.setLength(0);
buf.append("---BEGIN I2P SIGNED MESSAGE---\n");
buf.append(msg);
buf.append("\n---BEGIN I2P SIGNATURE---\n");
buf.append(sig.toBase64());
buf.append("\n---END I2P SIGNATURE---");
return buf.toString();
}
use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class Packet method readPacket.
/**
* Read the packet from the buffer (starting at the offset) and return
* the number of bytes read.
*
* @param buffer packet buffer containing the data
* @param offset index into the buffer to start readign
* @param length how many bytes within the buffer past the offset are
* part of the packet?
*
* @throws IllegalArgumentException if the data is b0rked
*/
public void readPacket(byte[] buffer, int offset, int length) throws IllegalArgumentException {
if (buffer.length - offset < length)
throw new IllegalArgumentException("len=" + buffer.length + " off=" + offset + " length=" + length);
if (// min header size
length < 22)
throw new IllegalArgumentException("Too small: len=" + buffer.length);
int cur = offset;
setSendStreamId(DataHelper.fromLong(buffer, cur, 4));
cur += 4;
setReceiveStreamId(DataHelper.fromLong(buffer, cur, 4));
cur += 4;
setSequenceNum(DataHelper.fromLong(buffer, cur, 4));
cur += 4;
setAckThrough(DataHelper.fromLong(buffer, cur, 4));
cur += 4;
int numNacks = buffer[cur] & 0xff;
cur++;
if (length < 22 + numNacks * 4)
throw new IllegalArgumentException("Too small with " + numNacks + " nacks: " + length);
if (numNacks > 0) {
long[] nacks = new long[numNacks];
for (int i = 0; i < numNacks; i++) {
nacks[i] = DataHelper.fromLong(buffer, cur, 4);
cur += 4;
}
setNacks(nacks);
} else {
setNacks(null);
}
setResendDelay(buffer[cur] & 0xff);
cur++;
setFlags((int) DataHelper.fromLong(buffer, cur, 2));
cur += 2;
int optionSize = (int) DataHelper.fromLong(buffer, cur, 2);
cur += 2;
if (length < 22 + numNacks * 4 + optionSize)
throw new IllegalArgumentException("Too small with " + numNacks + " nacks and " + optionSize + " options: " + length);
int payloadBegin = cur + optionSize;
int payloadSize = length - payloadBegin;
if ((payloadSize < 0) || (payloadSize > MAX_PAYLOAD_SIZE))
throw new IllegalArgumentException("length: " + length + " offset: " + offset + " begin: " + payloadBegin);
// skip ahead to the payload
// _payload = new ByteArray(new byte[payloadSize]);
_payload = new ByteArray(buffer, payloadBegin, payloadSize);
// ok now lets go back and deal with the options
if (isFlagSet(FLAG_DELAY_REQUESTED)) {
setOptionalDelay((int) DataHelper.fromLong(buffer, cur, 2));
cur += 2;
}
if (isFlagSet(FLAG_FROM_INCLUDED)) {
ByteArrayInputStream bais = new ByteArrayInputStream(buffer, cur, length - cur);
try {
Destination optionFrom = Destination.create(bais);
cur += optionFrom.size();
_optionFrom = optionFrom;
} catch (IOException ioe) {
throw new IllegalArgumentException("Bad from field", ioe);
} catch (DataFormatException dfe) {
throw new IllegalArgumentException("Bad from field", dfe);
}
}
if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED)) {
setOptionalMaxSize((int) DataHelper.fromLong(buffer, cur, 2));
cur += 2;
}
if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
Signature optionSignature;
Destination from = getOptionalFrom();
if (from != null) {
optionSignature = new Signature(from.getSigningPublicKey().getType());
} else {
// super cheat for now, look for correct type,
// assume no more options. If we add to the options
// we will have to ask the manager.
// We will get this wrong for Ed25519, same length as P256...
// See verifySignature() below where we will recast the signature to
// the correct type if necessary
int siglen = payloadBegin - cur;
SigType type = null;
for (SigType t : SigType.values()) {
if (t.getSigLen() == siglen) {
type = t;
break;
}
}
if (type == null) {
if (siglen < Signature.SIGNATURE_BYTES)
throw new IllegalArgumentException("unknown sig type len=" + siglen);
// Hope it's the default type with some unknown options following;
// if not the sig will fail later
type = SigType.DSA_SHA1;
siglen = Signature.SIGNATURE_BYTES;
}
optionSignature = new Signature(type);
}
byte[] buf = new byte[optionSignature.length()];
System.arraycopy(buffer, cur, buf, 0, buf.length);
optionSignature.setData(buf);
setOptionalSignature(optionSignature);
cur += buf.length;
}
}
use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class BlocklistEntries method main.
/**
* BlocklistEntries [-p keystorepw] input.txt keystore.ks you@mail.i2p
* File format: One entry per line, # starts a comment, ! starts an unblock entry.
* Single IPv4 or IPv6 address only (no mask allowed), or 44-char base 64 router hash.
* See MAX_ENTRIES above.
*/
public static void main(String[] args) {
if (args.length < 3) {
System.err.println("Usage: BlocklistEntries [-p keystorepw] input.txt keystore.ks you@mail.i2p");
System.exit(1);
}
int st;
String kspass;
if (args[0].equals("-p")) {
kspass = args[1];
st = 2;
} else {
kspass = KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD;
st = 0;
}
String inputFile = args[st++];
String privateKeyFile = args[st++];
String signerName = args[st];
I2PAppContext ctx = new I2PAppContext();
List<String> elist = new ArrayList<String>(16);
List<String> rlist = new ArrayList<String>(4);
StringBuilder buf = new StringBuilder();
long now = System.currentTimeMillis();
String date = RFC3339Date.to3339Date(now);
buf.append(date).append('\n');
;
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "UTF-8"));
String s = null;
while ((s = br.readLine()) != null) {
int index = s.indexOf('#');
if (index == 0)
// comment
continue;
if (index > 0)
s = s.substring(0, index);
s = s.trim();
if (s.length() < 7) {
if (s.length() > 0)
System.err.println("Bad line: " + s);
continue;
}
if (s.startsWith("!")) {
rlist.add(s.substring(1));
} else {
elist.add(s);
buf.append(s).append('\n');
;
}
}
} catch (IOException ioe) {
System.err.println("load error from " + args[0]);
ioe.printStackTrace();
System.exit(1);
} finally {
if (br != null)
try {
br.close();
} catch (IOException ioe) {
}
}
if (elist.isEmpty() && rlist.isEmpty()) {
System.err.println("nothing to sign");
System.exit(1);
}
if (elist.size() > MAX_ENTRIES) {
System.err.println("too many blocks, max is " + MAX_ENTRIES);
System.exit(1);
}
for (String s : rlist) {
buf.append('!').append(s).append('\n');
}
SigningPrivateKey spk = null;
try {
String keypw = "";
while (keypw.length() < 6) {
System.err.print("Enter password for key \"" + signerName + "\": ");
keypw = DataHelper.readLine(System.in);
if (keypw == null) {
System.out.println("\nEOF reading password");
System.exit(1);
}
keypw = keypw.trim();
if (keypw.length() > 0 && keypw.length() < 6)
System.out.println("Key password must be at least 6 characters");
}
File pkfile = new File(privateKeyFile);
PrivateKey pk = KeyStoreUtil.getPrivateKey(pkfile, kspass, signerName, keypw);
if (pk == null) {
System.out.println("Private key for " + signerName + " not found in keystore " + privateKeyFile);
System.exit(1);
}
spk = SigUtil.fromJavaKey(pk);
} catch (GeneralSecurityException gse) {
System.out.println("Error signing input file '" + inputFile + "'");
gse.printStackTrace();
System.exit(1);
} catch (IOException ioe) {
System.out.println("Error signing input file '" + inputFile + "'");
ioe.printStackTrace();
System.exit(1);
}
SigType type = spk.getType();
byte[] data = DataHelper.getUTF8(buf.toString());
Signature ssig = ctx.dsa().sign(data, spk);
if (ssig == null) {
System.err.println("sign failed");
System.exit(1);
}
String bsig = Base64.encode(ssig.getData());
// verify
BlocklistEntries ble = new BlocklistEntries(elist.size());
ble.entries.addAll(elist);
ble.removes.addAll(rlist);
ble.supdated = date;
ble.signer = signerName;
ble.sig = type.getCode() + ":" + bsig;
boolean ok = ble.verify(ctx);
if (!ok) {
System.err.println("verify failed");
System.exit(1);
}
System.out.println(" <i2p:blocklist signer=\"" + signerName + "\" sig=\"" + type.getCode() + ':' + bsig + "\">");
System.out.println(" <updated>" + date + "</updated>");
for (String e : elist) {
System.out.println(" <i2p:block>" + e + "</i2p:block>");
}
for (String e : rlist) {
System.out.println(" <i2p:unblock>" + e + "</i2p:unblock>");
}
System.out.println(" </i2p:blocklist>");
}
use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class BlocklistEntries method verify.
public synchronized boolean verify(I2PAppContext ctx) {
if (verified)
return true;
if (signer == null || sig == null || supdated == null)
return false;
if (updated > ctx.clock().now() + MAX_FUTURE)
return false;
Log log = ctx.logManager().getLog(BlocklistEntries.class);
String[] ss = DataHelper.split(sig, ":", 2);
if (ss.length != 2) {
log.error("blocklist feed bad sig: " + sig);
return false;
}
SigType type = SigType.parseSigType(ss[0]);
if (type == null) {
log.error("blocklist feed bad sig: " + sig);
return false;
}
if (!type.isAvailable()) {
log.error("blocklist feed sigtype unavailable: " + sig);
return false;
}
byte[] bsig = Base64.decode(ss[1]);
if (bsig == null) {
log.error("blocklist feed bad sig: " + sig);
return false;
}
Signature ssig;
try {
ssig = new Signature(type, bsig);
} catch (IllegalArgumentException iae) {
log.error("blocklist feed bad sig: " + sig);
return false;
}
// look in both install dir and config dir for the signer cert
KeyRing ring = new DirKeyRing(new File(ctx.getBaseDir(), "certificates"));
PublicKey pubkey;
try {
pubkey = ring.getKey(signer, CONTENT_ROUTER, type);
} catch (IOException ioe) {
log.error("blocklist feed error", ioe);
return false;
} catch (GeneralSecurityException gse) {
log.error("blocklist feed error", gse);
return false;
}
if (pubkey == null) {
boolean diff = true;
try {
diff = !ctx.getBaseDir().getCanonicalPath().equals(ctx.getConfigDir().getCanonicalPath());
} catch (IOException ioe) {
}
if (diff) {
ring = new DirKeyRing(new File(ctx.getConfigDir(), "certificates"));
try {
pubkey = ring.getKey(signer, CONTENT_ROUTER, type);
} catch (IOException ioe) {
log.error("blocklist feed error", ioe);
return false;
} catch (GeneralSecurityException gse) {
log.error("blocklist feed error", gse);
return false;
}
}
if (pubkey == null) {
log.error("unknown signer for blocklist feed: " + signer);
return false;
}
}
SigningPublicKey spubkey;
try {
spubkey = SigUtil.fromJavaKey(pubkey, type);
} catch (GeneralSecurityException gse) {
log.error("blocklist feed bad sig: " + sig, gse);
return false;
}
StringBuilder buf = new StringBuilder(256);
buf.append(supdated).append('\n');
for (String s : entries) {
buf.append(s).append('\n');
}
for (String s : removes) {
buf.append('!').append(s).append('\n');
}
byte[] data = DataHelper.getUTF8(buf.toString());
boolean rv = ctx.dsa().verifySignature(ssig, data, spubkey);
if (rv)
log.info("blocklist feed sig ok");
else
log.error("blocklist feed sig verify fail: " + signer);
verified = rv;
return rv;
}
use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class SU3File method verifyAndMigrate.
/**
* One-pass verify and extract the content.
* Recommend extracting to a temp location as the sig is not checked until
* after extraction. This will delete the file if the sig does not verify.
* Throws IOE on all format errors.
*
* @param migrateTo the output file, probably in zip format. Null for verify only.
* @return true if signature is good
*/
public boolean verifyAndMigrate(File migrateTo) throws IOException {
InputStream in = null;
FileOutputStream out = null;
boolean rv = false;
try {
in = new BufferedInputStream(new FileInputStream(_file));
// read 10 bytes to get the sig type
in.mark(10);
// following is a dup of that in verifyHeader()
byte[] magic = new byte[MAGIC_BYTES.length];
DataHelper.read(in, magic);
if (!DataHelper.eq(magic, MAGIC_BYTES))
throw new IOException("Not an su3 file");
skip(in, 1);
int foo = in.read();
if (foo != FILE_VERSION)
throw new IOException("bad file version");
skip(in, 1);
int sigTypeCode = in.read();
_sigType = SigType.getByCode(sigTypeCode);
if (_sigType == null)
throw new IOException("unknown sig type: " + sigTypeCode);
// end duplicate code
// rewind
in.reset();
MessageDigest md = _sigType.getDigestInstance();
DigestInputStream din = new DigestInputStream(in, md);
in = din;
if (!_headerVerified)
verifyHeader(in);
else
skip(in, getContentOffset());
if (_verifySignature) {
if (_signerPubkey == null)
throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName());
}
if (// else verify only
migrateTo != null)
out = new SecureFileOutputStream(migrateTo);
byte[] buf = new byte[16 * 1024];
long tot = 0;
while (tot < _contentLength) {
int read = in.read(buf, 0, (int) Math.min(buf.length, _contentLength - tot));
if (read < 0)
throw new EOFException();
if (// else verify only
migrateTo != null)
out.write(buf, 0, read);
tot += read;
}
if (_verifySignature) {
byte[] sha = md.digest();
din.on(false);
Signature signature = new Signature(_sigType);
signature.readBytes(in);
int avail = in.available();
if (avail > 0)
throw new IOException(avail + " bytes data after sig");
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);
throw ioe;
} finally {
if (in != null)
try {
in.close();
} catch (IOException ioe) {
}
if (out != null) {
// so do a POSIX flush and sync to ensure it will be there.
try {
out.flush();
out.getFD().sync();
} catch (IOException ioe) {
}
try {
out.close();
} catch (IOException ioe) {
}
}
if (migrateTo != null && !rv)
migrateTo.delete();
}
return rv;
}
Aggregations