serialization of personas. Load persona on startup
This commit is contained in:
8
core/src/main/groovy/com/muwire/core/Constants.groovy
Normal file
8
core/src/main/groovy/com/muwire/core/Constants.groovy
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.muwire.core
|
||||
|
||||
import net.i2p.crypto.SigType
|
||||
|
||||
class Constants {
|
||||
public static final byte PERSONA_VERSION = (byte)1
|
||||
public static final SigType SIG_TYPE = SigType.ECDSA_SHA512_P521 // TODO: decide which
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
package com.muwire.core
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import com.muwire.core.connection.ConnectionAcceptor
|
||||
import com.muwire.core.connection.ConnectionEstablisher
|
||||
import com.muwire.core.connection.ConnectionEvent
|
||||
@@ -21,6 +23,12 @@ import net.i2p.client.I2PSession
|
||||
import net.i2p.client.streaming.I2PSocketManager
|
||||
import net.i2p.client.streaming.I2PSocketManagerFactory
|
||||
import net.i2p.client.streaming.I2PSocketOptions
|
||||
import net.i2p.crypto.DSAEngine
|
||||
import net.i2p.crypto.SigType
|
||||
import net.i2p.data.Destination
|
||||
import net.i2p.data.PrivateKey
|
||||
import net.i2p.data.Signature
|
||||
import net.i2p.data.SigningPrivateKey
|
||||
|
||||
@Log
|
||||
class Core {
|
||||
@@ -46,14 +54,13 @@ class Core {
|
||||
props = new MuWireSettings(props)
|
||||
|
||||
|
||||
|
||||
log.info("initializing I2P socket manager")
|
||||
def i2pClient = new I2PClientFactory().createClient()
|
||||
File keyDat = new File(home, "key.dat")
|
||||
if (!keyDat.exists()) {
|
||||
log.info("Creating new key.dat")
|
||||
keyDat.withOutputStream {
|
||||
i2pClient.createDestination(it)
|
||||
i2pClient.createDestination(it, Constants.SIG_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +75,32 @@ class Core {
|
||||
socketManager.getDefaultOptions().setConnectTimeout(30000)
|
||||
i2pSession = socketManager.getSession()
|
||||
|
||||
|
||||
Persona me
|
||||
def destination = new Destination()
|
||||
def spk = new SigningPrivateKey(Constants.SIG_TYPE)
|
||||
keyDat.withInputStream {
|
||||
destination.readBytes(it)
|
||||
def privateKey = new PrivateKey()
|
||||
privateKey.readBytes(it)
|
||||
spk.readBytes(it)
|
||||
}
|
||||
|
||||
def baos = new ByteArrayOutputStream()
|
||||
def daos = new DataOutputStream(baos)
|
||||
daos.write(Constants.PERSONA_VERSION)
|
||||
daos.writeShort((short)props.getNickname().length())
|
||||
daos.write(props.getNickname().getBytes(StandardCharsets.UTF_8))
|
||||
destination.writeBytes(daos)
|
||||
daos.flush()
|
||||
byte [] payload = baos.toByteArray()
|
||||
Signature sig = DSAEngine.getInstance().sign(payload, spk)
|
||||
|
||||
baos = new ByteArrayOutputStream()
|
||||
baos.write(payload)
|
||||
sig.writeBytes(baos)
|
||||
me = new Persona(new ByteArrayInputStream(baos.toByteArray()))
|
||||
log.info("Loaded myself as "+me.getHumanReadableName())
|
||||
|
||||
EventBus eventBus = new EventBus()
|
||||
|
||||
log.info("initializing trust service")
|
||||
|
@@ -0,0 +1,17 @@
|
||||
package com.muwire.core
|
||||
|
||||
class InvalidSignatureException extends Exception {
|
||||
|
||||
public InvalidSignatureException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public InvalidSignatureException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidSignatureException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@@ -10,7 +10,7 @@ class MuWireSettings {
|
||||
isLeaf = Boolean.valueOf(props.get("leaf","false"))
|
||||
allowUntrusted = Boolean.valueOf(props.get("allowUntrusted","true"))
|
||||
crawlerResponse = CrawlerResponse.valueOf(props.get("crawlerResponse","REGISTERED"))
|
||||
nickname = props.getProperty("nickname")
|
||||
nickname = props.getProperty("nickname","MuWireUser")
|
||||
}
|
||||
|
||||
final boolean isLeaf
|
||||
@@ -37,4 +37,8 @@ class MuWireSettings {
|
||||
void setCrawlerResponse(CrawlerResponse crawlerResponse) {
|
||||
this.crawlerResponse = crawlerResponse
|
||||
}
|
||||
|
||||
String getNickname() {
|
||||
nickname
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ public class Name {
|
||||
public void write(OutputStream out) throws IOException {
|
||||
DataOutputStream dos = new DataOutputStream(out)
|
||||
dos.writeShort(name.length())
|
||||
dos.writeBuffer(name.getBytes(StandardCharsets.UTF_8))
|
||||
dos.write(name.getBytes(StandardCharsets.UTF_8))
|
||||
}
|
||||
|
||||
public getName() {
|
||||
|
74
core/src/main/groovy/com/muwire/core/Persona.groovy
Normal file
74
core/src/main/groovy/com/muwire/core/Persona.groovy
Normal file
@@ -0,0 +1,74 @@
|
||||
package com.muwire.core
|
||||
|
||||
import net.i2p.crypto.DSAEngine
|
||||
import net.i2p.crypto.SigType
|
||||
import net.i2p.data.Destination
|
||||
import net.i2p.data.Signature
|
||||
import net.i2p.data.SigningPublicKey
|
||||
|
||||
public class Persona {
|
||||
private static final int SIG_LEN = Constants.SIG_TYPE.getSigLen()
|
||||
|
||||
private final byte version
|
||||
private final Name name
|
||||
private final Destination destination
|
||||
private final byte[] sig
|
||||
private volatile String humanReadableName
|
||||
private volatile byte[] payload
|
||||
|
||||
public Persona(InputStream personaStream) throws IOException, InvalidSignatureException {
|
||||
version = (byte) (personaStream.read() & 0xFF)
|
||||
if (version != Constants.PERSONA_VERSION)
|
||||
throw new IOException("Unknown version "+version)
|
||||
|
||||
name = new Name(personaStream)
|
||||
destination = Destination.create(personaStream)
|
||||
sig = new byte[SIG_LEN]
|
||||
DataInputStream dis = new DataInputStream(personaStream)
|
||||
dis.readFully(sig)
|
||||
if (!verify(version, name, destination, sig))
|
||||
throw new InvalidSignatureException(getHumanReadableName() + " didn't verify")
|
||||
}
|
||||
|
||||
private static boolean verify(byte version, Name name, Destination destination, byte [] sig) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()
|
||||
baos.write(version)
|
||||
name.write(baos)
|
||||
destination.writeBytes(baos)
|
||||
byte[] payload = baos.toByteArray()
|
||||
SigningPublicKey spk = destination.getSigningPublicKey()
|
||||
Signature signature = new Signature(Constants.SIG_TYPE, sig)
|
||||
DSAEngine.getInstance().verifySignature(signature, payload, spk)
|
||||
}
|
||||
|
||||
public void write(OutputStream out) throws IOException {
|
||||
if (payload == null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()
|
||||
baos.write(version)
|
||||
name.write(baos)
|
||||
destination.writeBytes(baos)
|
||||
baos.write(sig)
|
||||
payload = baos.toByteArray()
|
||||
}
|
||||
out.write(payload)
|
||||
}
|
||||
|
||||
public String getHumanReadableName() {
|
||||
if (humanReadableName == null)
|
||||
humanReadableName = name.getName() + "@" + destination.toBase32().substring(0,32)
|
||||
humanReadableName
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
name.hashCode() ^ destination.hashCode()
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Persona))
|
||||
return false
|
||||
Persona other = (Persona)o
|
||||
name.equals(other.name) && destination.equals(other.destination)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user