use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class PacketBuilder method buildSessionCreatedPacket.
/**
* Build a new SessionCreated packet for the given peer, encrypting it
* as necessary.
*
* @return ready to send packet, or null if there was a problem
*/
public UDPPacket buildSessionCreatedPacket(InboundEstablishState state, int externalPort, SessionKey ourIntroKey) {
UDPPacket packet = buildPacketHeader(SESSION_CREATED_FLAG_BYTE);
DatagramPacket pkt = packet.getPacket();
byte[] data = pkt.getData();
int off = HEADER_SIZE;
InetAddress to = null;
try {
to = InetAddress.getByAddress(state.getSentIP());
} catch (UnknownHostException uhe) {
if (_log.shouldLog(Log.ERROR))
_log.error("How did we think this was a valid IP? " + state.getRemoteHostId().toString());
packet.release();
return null;
}
state.prepareSessionCreated();
byte[] sentIP = state.getSentIP();
if ((sentIP == null) || (sentIP.length <= 0) || (!_transport.isValid(sentIP))) {
if (_log.shouldLog(Log.ERROR))
_log.error("How did our sent IP become invalid? " + state);
state.fail();
packet.release();
return null;
}
// now for the body
System.arraycopy(state.getSentY(), 0, data, off, state.getSentY().length);
off += state.getSentY().length;
DataHelper.toLong(data, off, 1, sentIP.length);
off += 1;
System.arraycopy(sentIP, 0, data, off, sentIP.length);
off += sentIP.length;
DataHelper.toLong(data, off, 2, state.getSentPort());
off += 2;
DataHelper.toLong(data, off, 4, state.getSentRelayTag());
off += 4;
DataHelper.toLong(data, off, 4, state.getSentSignedOnTime());
off += 4;
// handle variable signature size
Signature sig = state.getSentSignature();
int siglen = sig.length();
System.arraycopy(sig.getData(), 0, data, off, siglen);
off += siglen;
// ok, we need another few bytes of random padding
int rem = siglen % 16;
int padding;
if (rem > 0) {
padding = 16 - rem;
_context.random().nextBytes(data, off, padding);
off += padding;
} else {
padding = 0;
}
if (_log.shouldLog(Log.DEBUG)) {
StringBuilder buf = new StringBuilder(128);
buf.append("Sending sessionCreated:");
buf.append(" Alice: ").append(Addresses.toString(sentIP, state.getSentPort()));
buf.append(" Bob: ").append(Addresses.toString(state.getReceivedOurIP(), externalPort));
buf.append(" RelayTag: ").append(state.getSentRelayTag());
buf.append(" SignedOn: ").append(state.getSentSignedOnTime());
buf.append(" signature: ").append(Base64.encode(sig.getData()));
buf.append("\nRawCreated: ").append(Base64.encode(data, 0, off));
buf.append("\nsignedTime: ").append(Base64.encode(data, off - padding - siglen - 4, 4));
_log.debug(buf.toString());
}
// ok, now the full data is in there, but we also need to encrypt
// the signature, which means we need the IV
byte[] iv = SimpleByteCache.acquire(UDPPacket.IV_SIZE);
_context.random().nextBytes(iv);
int encrWrite = siglen + padding;
int sigBegin = off - encrWrite;
_context.aes().encrypt(data, sigBegin, data, sigBegin, state.getCipherKey(), iv, encrWrite);
// pad up so we're on the encryption boundary
off = pad1(data, off);
off = pad2(data, off);
pkt.setLength(off);
authenticate(packet, ourIntroKey, ourIntroKey, iv);
setTo(packet, to, state.getSentPort());
SimpleByteCache.release(iv);
packet.setMessageType(TYPE_CREAT);
return packet;
}
use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class FamilyKeyCrypto method sign.
/**
* Caller must add family to RI also.
* throws on all errors
*
* @param family non-null, must match that we were initialized with or will throw GSE
* @param h non-null
* @return non-null options to be added to the RI
* @throws GeneralSecurityException on null hash, null or changed family, or signing error
*/
public Map<String, String> sign(String family, Hash h) throws GeneralSecurityException {
if (_privkey == null) {
_log.logAlways(Log.WARN, "family name now set, must restart router to generate or load keys");
throw new GeneralSecurityException("family name now set, must restart router to generate or load keys");
}
if (h == null)
throw new GeneralSecurityException("null router hash");
if (!_fname.equals(family)) {
_log.logAlways(Log.WARN, "family name changed, must restart router to generate or load new keys");
throw new GeneralSecurityException("family name changed, must restart router to generate or load new keys");
}
byte[] nb = DataHelper.getUTF8(_fname);
int len = nb.length + Hash.HASH_LENGTH;
byte[] b = new byte[len];
System.arraycopy(nb, 0, b, 0, nb.length);
System.arraycopy(h.getData(), 0, b, nb.length, Hash.HASH_LENGTH);
Signature sig = _context.dsa().sign(b, _privkey);
if (sig == null)
throw new GeneralSecurityException("sig failed");
Map<String, String> rv = new HashMap<String, String>(3);
rv.put(OPT_NAME, family);
rv.put(OPT_KEY, _pubkey.getType().getCode() + ":" + _pubkey.toBase64());
rv.put(OPT_SIG, sig.toBase64());
return rv;
}
use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class FamilyKeyCrypto method verify.
/**
* Verify the family in a RouterInfo, name already retrieved
* @since 0.9.28
*/
private boolean verify(RouterInfo ri, String name) {
Hash h = ri.getHash();
String ssig = ri.getOption(OPT_SIG);
if (ssig == null) {
if (_log.shouldInfo())
_log.info("No sig for " + h + ' ' + name);
return false;
}
String nameAndSig = _verified.get(h);
String riNameAndSig = name + ssig;
if (nameAndSig != null) {
if (nameAndSig.equals(riNameAndSig))
return true;
// name or sig changed
_verified.remove(h);
}
SigningPublicKey spk;
if (name.equals(_fname)) {
// us
spk = _pubkey;
} else {
if (_negativeCache.contains(h))
return false;
spk = loadCert(name);
if (spk == null) {
// look for a b64 key in the RI
String skey = ri.getOption(OPT_KEY);
if (skey != null) {
int colon = skey.indexOf(':');
// switched from ';' to ':' during dev, remove this later
if (colon < 0)
colon = skey.indexOf(';');
if (colon > 0) {
try {
int code = Integer.parseInt(skey.substring(0, colon));
SigType type = SigType.getByCode(code);
if (type != null) {
byte[] bkey = Base64.decode(skey.substring(colon + 1));
if (bkey != null) {
spk = new SigningPublicKey(type, bkey);
}
}
} catch (NumberFormatException e) {
if (_log.shouldInfo())
_log.info("Bad b64 family key: " + ri, e);
} catch (IllegalArgumentException e) {
if (_log.shouldInfo())
_log.info("Bad b64 family key: " + ri, e);
} catch (ArrayIndexOutOfBoundsException e) {
if (_log.shouldInfo())
_log.info("Bad b64 family key: " + ri, e);
}
}
}
if (spk == null) {
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("No cert or valid key for " + h + ' ' + name);
return false;
}
}
}
if (!spk.getType().isAvailable()) {
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Unsupported crypto for sig for " + h);
return false;
}
byte[] bsig = Base64.decode(ssig);
if (bsig == null) {
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Bad sig for " + h + ' ' + name + ' ' + ssig);
return false;
}
Signature sig;
try {
sig = new Signature(spk.getType(), bsig);
} catch (IllegalArgumentException iae) {
// wrong size (type mismatch)
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Bad sig for " + ri, iae);
return false;
}
byte[] nb = DataHelper.getUTF8(name);
byte[] b = new byte[nb.length + Hash.HASH_LENGTH];
System.arraycopy(nb, 0, b, 0, nb.length);
System.arraycopy(ri.getHash().getData(), 0, b, nb.length, Hash.HASH_LENGTH);
boolean rv = _context.dsa().verifySignature(sig, b, spk);
if (rv)
_verified.put(h, riNameAndSig);
else
_negativeCache.add(h);
if (_log.shouldInfo())
_log.info("Verified? " + rv + " for " + h + ' ' + name + ' ' + ssig);
return rv;
}
use of net.i2p.data.Signature in project i2p.i2p-bote by i2p.
the class ElGamal2048_DSA1024 method verify.
/**
* Only accepts <code>DSAPublicKey</code>s.
*/
@Override
public boolean verify(byte[] data, byte[] signature, PublicKey key) throws GeneralSecurityException {
DSAPublicKey dsaKey = castToDSA(key);
Signature signatureObj = new Signature(signature);
boolean valid = DSAEngine.getInstance().verifySignature(signatureObj, data, dsaKey.getI2PKey());
return valid;
}
use of net.i2p.data.Signature in project i2p.i2p by i2p.
the class TrustedUpdate method sign.
/**
* Uses the given {@link net.i2p.data.SigningPrivateKey} to sign the given
* input file along with its version string using DSA. The output will be a
* signed update file where the first 40 bytes are the resulting DSA
* signature, the next 16 bytes are the input file's version string encoded
* in UTF-8 (padded with trailing <code>0h</code> characters if necessary),
* and the remaining bytes are the raw bytes of the input file.
*
* @param inputFile The file to be signed.
* @param signedFile The signed update file to write.
* @param signingPrivateKey An instance of <code>SigningPrivateKey</code>
* to sign <code>inputFile</code> with.
* @param version The version string of the input file. If this is
* longer than 16 characters it will be truncated.
*
* @return An instance of {@link net.i2p.data.Signature}, or
* <code>null</code> if there was an error.
*/
public Signature sign(String inputFile, String signedFile, SigningPrivateKey signingPrivateKey, String version) {
byte[] versionHeader = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] versionRawBytes = null;
if (version.length() > VERSION_BYTES)
version = version.substring(0, VERSION_BYTES);
try {
versionRawBytes = version.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("your JVM doesnt support utf-8? " + e.getMessage());
}
System.arraycopy(versionRawBytes, 0, versionHeader, 0, versionRawBytes.length);
FileInputStream fileInputStream = null;
Signature signature = null;
SequenceInputStream bytesToSignInputStream = null;
ByteArrayInputStream versionHeaderInputStream = null;
try {
fileInputStream = new FileInputStream(inputFile);
versionHeaderInputStream = new ByteArrayInputStream(versionHeader);
bytesToSignInputStream = new SequenceInputStream(versionHeaderInputStream, fileInputStream);
signature = _context.dsa().sign(bytesToSignInputStream, signingPrivateKey);
} catch (IOException e) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error signing", e);
return null;
} finally {
if (bytesToSignInputStream != null)
try {
bytesToSignInputStream.close();
} catch (IOException ioe) {
}
if (fileInputStream != null)
try {
fileInputStream.close();
} catch (IOException ioe) {
}
}
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(signedFile);
fileOutputStream.write(signature.getData());
fileOutputStream.write(versionHeader);
fileInputStream = new FileInputStream(inputFile);
DataHelper.copy(fileInputStream, fileOutputStream);
fileOutputStream.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.log(Log.WARN, "Error writing signed file " + signedFile, ioe);
return null;
} finally {
if (fileInputStream != null)
try {
fileInputStream.close();
} catch (IOException ioe) {
}
if (fileOutputStream != null)
try {
fileOutputStream.close();
} catch (IOException ioe) {
}
}
return signature;
}
Aggregations