use of net.i2p.data.SimpleDataStructure in project i2p.i2p by i2p.
the class I2PSocketManagerFull method addSubsession.
/**
* For a server, you must call connect() on the returned object.
* Connecting the primary session does NOT connect any subsessions.
* If the primary session is not connected, connecting a subsession will connect the primary session first.
*
* @return a new subsession, non-null
* @param privateKeyStream null for transient, if non-null must have same encryption keys as primary session
* and different signing keys
* @param opts subsession options if any, may be null
* @since 0.9.21
*/
public I2PSession addSubsession(InputStream privateKeyStream, Properties opts) throws I2PSessionException {
if (privateKeyStream == null) {
// We don't actually need the same pubkey in the dest, just in the LS.
// The dest one is unused. But this is how we find the LS keys
// to reuse in RequestLeaseSetMessageHandler.
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
try {
SigType type = getSigType(opts);
if (type != SigType.DSA_SHA1) {
// hassle, have to set up the padding and cert, see I2PClientImpl
throw new I2PSessionException("type " + type + " unsupported");
}
PublicKey pub = _session.getMyDestination().getPublicKey();
PrivateKey priv = _session.getDecryptionKey();
SimpleDataStructure[] keys = _context.keyGenerator().generateSigningKeys(type);
pub.writeBytes(keyStream);
// signing pub
keys[0].writeBytes(keyStream);
Certificate.NULL_CERT.writeBytes(keyStream);
priv.writeBytes(keyStream);
// signing priv
keys[1].writeBytes(keyStream);
} catch (GeneralSecurityException e) {
throw new I2PSessionException("Error creating keys", e);
} catch (I2PException e) {
throw new I2PSessionException("Error creating keys", e);
} catch (IOException e) {
throw new I2PSessionException("Error creating keys", e);
} catch (RuntimeException e) {
throw new I2PSessionException("Error creating keys", e);
}
privateKeyStream = new ByteArrayInputStream(keyStream.toByteArray());
}
I2PSession rv = _session.addSubsession(privateKeyStream, opts);
boolean added = _subsessions.add(rv);
if (!added) {
// shouldn't happen
_session.removeSubsession(rv);
throw new I2PSessionException("dup");
}
ConnectionOptions defaultOptions = new ConnectionOptions(opts);
int protocol = defaultOptions.getEnforceProtocol() ? I2PSession.PROTO_STREAMING : I2PSession.PROTO_ANY;
rv.addMuxedSessionListener(_connectionManager.getMessageHandler(), protocol, defaultOptions.getLocalPort());
if (_log.shouldLog(Log.WARN))
_log.warn("Added subsession " + rv);
return rv;
}
use of net.i2p.data.SimpleDataStructure 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;
}
use of net.i2p.data.SimpleDataStructure in project i2p.i2p by i2p.
the class SU3File method write.
/**
* One-pass wrap and sign the content.
* Writes to the file specified in the constructor.
* Throws on all errors.
*
* @param content the input file, probably in zip format
* @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 fileType, int contentType, String version, String signer, PrivateKey privkey, SigType sigType) throws IOException {
InputStream in = null;
DigestOutputStream out = null;
boolean ok = false;
try {
in = new BufferedInputStream(new FileInputStream(content));
MessageDigest md = sigType.getDigestInstance();
out = new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(_file)), md);
out.write(MAGIC_BYTES);
out.write((byte) 0);
out.write((byte) FILE_VERSION);
DataHelper.writeLong(out, 2, sigType.getCode());
DataHelper.writeLong(out, 2, sigType.getSigLen());
out.write((byte) 0);
byte[] verBytes = DataHelper.getUTF8(version);
if (verBytes.length == 0 || verBytes.length > 255)
throw new IllegalArgumentException("bad version length");
int verLen = Math.max(verBytes.length, MIN_VERSION_BYTES);
out.write((byte) verLen);
out.write((byte) 0);
byte[] signerBytes = DataHelper.getUTF8(signer);
if (signerBytes.length == 0 || signerBytes.length > 255)
throw new IllegalArgumentException("bad signer length");
out.write((byte) signerBytes.length);
long contentLength = content.length();
if (contentLength <= 0)
throw new IllegalArgumentException("No content");
DataHelper.writeLong(out, 8, contentLength);
out.write((byte) 0);
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");
out.write((byte) contentType);
out.write(new byte[12]);
out.write(verBytes);
if (verBytes.length < MIN_VERSION_BYTES)
out.write(new byte[MIN_VERSION_BYTES - verBytes.length]);
out.write(signerBytes);
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();
out.write(buf, 0, read);
tot += read;
}
byte[] sha = md.digest();
out.on(false);
SimpleDataStructure hash = sigType.getHashInstance();
hash.setData(sha);
Signature signature = _context.dsa().sign(hash, privkey, sigType);
if (signature == null)
throw new IOException("sig fail");
// System.out.println("hash\n" + HexDump.dump(sha));
// System.out.println("sig\n" + HexDump.dump(signature.getData()));
signature.writeBytes(out);
ok = 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)
try {
out.close();
} catch (IOException ioe) {
}
if (!ok)
_file.delete();
}
}
use of net.i2p.data.SimpleDataStructure in project i2p.i2p by i2p.
the class I2PClientImpl method createDestination.
/**
* Create the destination with the given payload and write it out along with
* the PrivateKey and SigningPrivateKey to the destKeyStream
*
* If cert is a KeyCertificate, the signing keypair will be of the specified type.
* The KeyCertificate data must be .............................
* The padding if any will be randomized. The extra key data if any will be set in the
* key cert.
*
* Caller must close stream.
*
* @param destKeyStream location to write out the destination, PrivateKey, and SigningPrivateKey,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
*/
public Destination createDestination(OutputStream destKeyStream, Certificate cert) throws I2PException, IOException {
Destination d = new Destination();
Object[] keypair = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey publicKey = (PublicKey) keypair[0];
PrivateKey privateKey = (PrivateKey) keypair[1];
SimpleDataStructure[] signingKeys;
if (cert.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
KeyCertificate kcert = cert.toKeyCertificate();
SigType type = kcert.getSigType();
try {
signingKeys = KeyGenerator.getInstance().generateSigningKeys(type);
} catch (GeneralSecurityException gse) {
throw new I2PException("keygen fail", gse);
}
} else {
signingKeys = KeyGenerator.getInstance().generateSigningKeys();
}
SigningPublicKey signingPubKey = (SigningPublicKey) signingKeys[0];
SigningPrivateKey signingPrivKey = (SigningPrivateKey) signingKeys[1];
d.setPublicKey(publicKey);
d.setSigningPublicKey(signingPubKey);
if (cert.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
// fix up key certificate or padding
KeyCertificate kcert = cert.toKeyCertificate();
SigType type = kcert.getSigType();
int len = type.getPubkeyLen();
if (len < 128) {
byte[] pad = new byte[128 - len];
RandomSource.getInstance().nextBytes(pad);
d.setPadding(pad);
} else if (len > 128) {
System.arraycopy(signingPubKey.getData(), 128, kcert.getPayload(), KeyCertificate.HEADER_LENGTH, len - 128);
}
}
d.setCertificate(cert);
d.writeBytes(destKeyStream);
privateKey.writeBytes(destKeyStream);
signingPrivKey.writeBytes(destKeyStream);
destKeyStream.flush();
return d;
}
use of net.i2p.data.SimpleDataStructure in project i2p.i2p by i2p.
the class KeyGenerator method generatePKIKeys.
/**
* Same as above but different return type
* @since 0.8.7
*/
public SimpleDataStructure[] generatePKIKeys() {
BigInteger a = new NativeBigInteger(getElGamalExponentSize(), _context.random());
BigInteger aalpha = CryptoConstants.elgg.modPow(a, CryptoConstants.elgp);
SimpleDataStructure[] keys = new SimpleDataStructure[2];
keys[0] = new PublicKey();
keys[1] = new PrivateKey();
try {
keys[0].setData(SigUtil.rectify(aalpha, PublicKey.KEYSIZE_BYTES));
keys[1].setData(SigUtil.rectify(a, PrivateKey.KEYSIZE_BYTES));
} catch (InvalidKeyException ike) {
throw new IllegalArgumentException(ike);
}
return keys;
}
Aggregations