rewrite Persona and Name in java

pull/24/head
Zlatin Balevsky 2019-11-07 17:41:32 +00:00
parent c998011873
commit cad5301827
5 changed files with 154 additions and 141 deletions

View File

@ -1,46 +0,0 @@
package com.muwire.core
import java.nio.charset.StandardCharsets
/**
* A name of persona, file or search term
*/
public class Name {
final String name
Name(String name) {
this.name = name
}
Name(InputStream nameStream) throws IOException {
DataInputStream dis = new DataInputStream(nameStream)
int length = dis.readUnsignedShort()
byte [] nameBytes = new byte[length]
dis.readFully(nameBytes)
this.name = new String(nameBytes, StandardCharsets.UTF_8)
}
public void write(OutputStream out) throws IOException {
DataOutputStream dos = new DataOutputStream(out)
byte [] bytes = name.getBytes(StandardCharsets.UTF_8)
dos.writeShort(bytes.length)
dos.write(bytes)
}
public getName() {
name
}
@Override
public int hashCode() {
name.hashCode()
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Name))
return false
Name other = (Name)o
name.equals(other.name)
}
}

View File

@ -1,94 +0,0 @@
package com.muwire.core
import net.i2p.crypto.DSAEngine
import net.i2p.crypto.SigType
import net.i2p.data.Base64
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 String base64
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
}
public String toBase64() {
if (base64 == null) {
def baos = new ByteArrayOutputStream()
write(baos)
base64 = Base64.encode(baos.toByteArray())
}
base64
}
@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)
}
public static void main(String []args) {
if (args.length != 1) {
println "This utility decodes a bas64-encoded persona"
System.exit(1)
}
Persona p = new Persona(new ByteArrayInputStream(Base64.decode(args[0])))
println p.getHumanReadableName()
}
}

View File

@ -1,4 +1,4 @@
package com.muwire.core
package com.muwire.core;
class InvalidSignatureException extends Exception {

View File

@ -0,0 +1,51 @@
package com.muwire.core;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
/**
* A name of persona, file or search term
*/
public class Name {
final String name;
Name(String name) {
this.name = name;
}
Name(InputStream nameStream) throws IOException {
DataInputStream dis = new DataInputStream(nameStream);
int length = dis.readUnsignedShort();
byte [] nameBytes = new byte[length];
dis.readFully(nameBytes);
this.name = new String(nameBytes, StandardCharsets.UTF_8);
}
public void write(OutputStream out) throws IOException {
DataOutputStream dos = new DataOutputStream(out);
byte [] bytes = name.getBytes(StandardCharsets.UTF_8);
dos.writeShort(bytes.length);
dos.write(bytes);
}
public String getName() {
return name;
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Name))
return false;
Name other = (Name)o;
return name.equals(other.name);
}
}

View File

@ -0,0 +1,102 @@
package com.muwire.core;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.i2p.crypto.DSAEngine;
import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
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 String base64;
private volatile byte[] payload;
public Persona(InputStream personaStream) throws IOException, DataFormatException, 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)
throws IOException, DataFormatException {
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);
return DSAEngine.getInstance().verifySignature(signature, payload, spk);
}
public void write(OutputStream out) throws IOException, DataFormatException {
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);
return humanReadableName;
}
public String toBase64() throws DataFormatException, IOException {
if (base64 == null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
write(baos);
base64 = Base64.encode(baos.toByteArray());
}
return base64;
}
@Override
public int hashCode() {
return name.hashCode() ^ destination.hashCode();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Persona))
return false;
Persona other = (Persona)o;
return name.equals(other.name) && destination.equals(other.destination);
}
public static void main(String []args) throws Exception {
if (args.length != 1) {
System.out.println("This utility decodes a bas64-encoded persona");
System.exit(1);
}
Persona p = new Persona(new ByteArrayInputStream(Base64.decode(args[0])));
System.out.println(p.getHumanReadableName());
}
}