Some code for supporting chans
This commit is contained in:
parent
3e5e431d6f
commit
ead5341b2e
@ -17,10 +17,7 @@
|
|||||||
package ch.dissem.bitmessage;
|
package ch.dissem.bitmessage;
|
||||||
|
|
||||||
import ch.dissem.bitmessage.entity.*;
|
import ch.dissem.bitmessage.entity.*;
|
||||||
import ch.dissem.bitmessage.entity.payload.Broadcast;
|
import ch.dissem.bitmessage.entity.payload.*;
|
||||||
import ch.dissem.bitmessage.entity.payload.Msg;
|
|
||||||
import ch.dissem.bitmessage.entity.payload.ObjectPayload;
|
|
||||||
import ch.dissem.bitmessage.entity.payload.ObjectType;
|
|
||||||
import ch.dissem.bitmessage.entity.payload.Pubkey.Feature;
|
import ch.dissem.bitmessage.entity.payload.Pubkey.Feature;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
||||||
@ -117,9 +114,17 @@ public class BitmessageContext {
|
|||||||
return identity;
|
return identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDistributedMailingList(String address, String alias) {
|
public BitmessageAddress joinChan(String passphrase, String address) {
|
||||||
// TODO
|
BitmessageAddress chan = BitmessageAddress.chan(address, passphrase);
|
||||||
throw new ApplicationException("not implemented");
|
ctx.getAddressRepository().save(chan);
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmessageAddress createChan(String passphrase) {
|
||||||
|
// FIXME: hardcoded stream number
|
||||||
|
BitmessageAddress chan = BitmessageAddress.chan(1, passphrase);
|
||||||
|
ctx.getAddressRepository().save(chan);
|
||||||
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(final BitmessageAddress from, final String subject, final String message) {
|
public void broadcast(final BitmessageAddress from, final String subject, final String message) {
|
||||||
|
@ -57,6 +57,7 @@ public class BitmessageAddress implements Serializable {
|
|||||||
|
|
||||||
private String alias;
|
private String alias;
|
||||||
private boolean subscribed;
|
private boolean subscribed;
|
||||||
|
private boolean chan;
|
||||||
|
|
||||||
BitmessageAddress(long version, long stream, byte[] ripe) {
|
BitmessageAddress(long version, long stream, byte[] ripe) {
|
||||||
try {
|
try {
|
||||||
@ -93,6 +94,27 @@ public class BitmessageAddress implements Serializable {
|
|||||||
this.pubkey = publicKey;
|
this.pubkey = publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BitmessageAddress(String address, String passphrase) {
|
||||||
|
this(address);
|
||||||
|
this.privateKey = new PrivateKey(this, passphrase);
|
||||||
|
if (!Arrays.equals(ripe, privateKey.getPubkey().getRipe())) {
|
||||||
|
throw new IllegalArgumentException("Wrong address or passphrase");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitmessageAddress chan(String address, String passphrase) {
|
||||||
|
BitmessageAddress result = new BitmessageAddress(address, passphrase);
|
||||||
|
result.chan = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitmessageAddress chan(long stream, String passphrase) {
|
||||||
|
PrivateKey privateKey = new PrivateKey(Pubkey.LATEST_VERSION, stream, passphrase);
|
||||||
|
BitmessageAddress result = new BitmessageAddress(privateKey);
|
||||||
|
result.chan = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public BitmessageAddress(PrivateKey privateKey) {
|
public BitmessageAddress(PrivateKey privateKey) {
|
||||||
this(privateKey.getPubkey());
|
this(privateKey.getPubkey());
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
@ -221,4 +243,8 @@ public class BitmessageAddress implements Serializable {
|
|||||||
public void setSubscribed(boolean subscribed) {
|
public void setSubscribed(boolean subscribed) {
|
||||||
this.subscribed = subscribed;
|
this.subscribed = subscribed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isChan() {
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package ch.dissem.bitmessage.entity.valueobject;
|
package ch.dissem.bitmessage.entity.valueobject;
|
||||||
|
|
||||||
|
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||||
import ch.dissem.bitmessage.entity.Streamable;
|
import ch.dissem.bitmessage.entity.Streamable;
|
||||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||||
import ch.dissem.bitmessage.exception.ApplicationException;
|
import ch.dissem.bitmessage.exception.ApplicationException;
|
||||||
@ -64,14 +65,32 @@ public class PrivateKey implements Streamable {
|
|||||||
this.pubkey = pubkey;
|
this.pubkey = pubkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrivateKey(long version, long stream, String passphrase, long nonceTrialsPerByte, long extraBytes, Pubkey.Feature... features) {
|
public PrivateKey(BitmessageAddress address, String passphrase) {
|
||||||
|
this(address.getVersion(), address.getStream(), passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrivateKey(long version, long stream, String passphrase) {
|
||||||
try {
|
try {
|
||||||
// FIXME: this is most definitely wrong
|
byte[] signingKey;
|
||||||
this.privateSigningKey = Bytes.truncate(security().sha512(passphrase.getBytes("UTF-8"), new byte[]{0}), 32);
|
int signingKeyNonce = 0;
|
||||||
this.privateEncryptionKey = Bytes.truncate(security().sha512(passphrase.getBytes("UTF-8"), new byte[]{1}), 32);
|
byte[] encryptionKey;
|
||||||
this.pubkey = security().createPubkey(version, stream, privateSigningKey, privateEncryptionKey,
|
int encryptionKeyNonce = 1;
|
||||||
nonceTrialsPerByte, extraBytes, features);
|
byte[] passPhraseBytes = passphrase.getBytes("UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
byte[] ripe;
|
||||||
|
do {
|
||||||
|
signingKey = Bytes.truncate(security().sha512(passPhraseBytes, Encode.varInt(signingKeyNonce)), 32);
|
||||||
|
encryptionKey = Bytes.truncate(security().sha512(passPhraseBytes, Encode.varInt(encryptionKeyNonce)), 32);
|
||||||
|
byte[] publicSigningKey = security().createPublicKey(signingKey);
|
||||||
|
byte[] publicEncryptionKey = security().createPublicKey(encryptionKey);
|
||||||
|
ripe = security().ripemd160(security().sha512(publicSigningKey, publicEncryptionKey));
|
||||||
|
|
||||||
|
signingKeyNonce += 2;
|
||||||
|
encryptionKeyNonce += 2;
|
||||||
|
} while (ripe[0] != 0);
|
||||||
|
this.privateSigningKey = signingKey;
|
||||||
|
this.privateEncryptionKey = encryptionKey;
|
||||||
|
this.pubkey = security().createPubkey(version, stream, privateSigningKey, privateEncryptionKey, 0, 0);
|
||||||
|
} catch (IOException e) {
|
||||||
throw new ApplicationException(e);
|
throw new ApplicationException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,34 @@ public class Encode {
|
|||||||
varInt(value, stream, null);
|
varInt(value, stream, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] varInt(long value) throws IOException {
|
||||||
|
final byte[] result;
|
||||||
|
if (value < 0) {
|
||||||
|
// This is due to the fact that Java doesn't really support unsigned values.
|
||||||
|
// Please be aware that this might be an error due to a smaller negative value being cast to long.
|
||||||
|
// Normally, negative values shouldn't occur within the protocol, and I large enough longs
|
||||||
|
// to being recognized as negatives aren't realistic.
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(9);
|
||||||
|
buffer.put((byte) 0xff);
|
||||||
|
result = buffer.putLong(value).array();
|
||||||
|
} else if (value < 0xfd) {
|
||||||
|
result = new byte[]{(byte) value};
|
||||||
|
} else if (value <= 0xffffL) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(3);
|
||||||
|
buffer.put((byte) 0xfd);
|
||||||
|
result = buffer.putShort((short) value).array();
|
||||||
|
} else if (value <= 0xffffffffL) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(5);
|
||||||
|
buffer.put((byte) 0xfe);
|
||||||
|
result = buffer.putInt((int) value).array();
|
||||||
|
} else {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(9);
|
||||||
|
buffer.put((byte) 0xff);
|
||||||
|
result = buffer.putLong(value).array();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static void varInt(long value, OutputStream stream, AccessCounter counter) throws IOException {
|
public static void varInt(long value, OutputStream stream, AccessCounter counter) throws IOException {
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
// This is due to the fact that Java doesn't really support unsigned values.
|
// This is due to the fact that Java doesn't really support unsigned values.
|
||||||
@ -81,7 +109,7 @@ public class Encode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void int16(long value, OutputStream stream, AccessCounter counter) throws IOException {
|
public static void int16(long value, OutputStream stream, AccessCounter counter) throws IOException {
|
||||||
stream.write(ByteBuffer.allocate(4).putInt((int) value).array(), 2, 2);
|
stream.write(ByteBuffer.allocate(2).putShort((short) value).array());
|
||||||
inc(counter, 2);
|
inc(counter, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ import static ch.dissem.bitmessage.entity.payload.ObjectType.*;
|
|||||||
import static ch.dissem.bitmessage.utils.MessageMatchers.object;
|
import static ch.dissem.bitmessage.utils.MessageMatchers.object;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
@ -206,4 +206,21 @@ public class BitmessageContextTest {
|
|||||||
.build();
|
.build();
|
||||||
ctx.send(msg);
|
ctx.send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ensureChanIsJoined() {
|
||||||
|
String chanAddress = "BM-2cW67GEKkHGonXKZLCzouLLxnLym3azS8r";
|
||||||
|
BitmessageAddress chan = ctx.joinChan("general", chanAddress);
|
||||||
|
assertNotNull(chan);
|
||||||
|
assertEquals(chan.getAddress(), chanAddress);
|
||||||
|
assertTrue(chan.isChan());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ensureChanIsCreated() {
|
||||||
|
BitmessageAddress chan = ctx.createChan("test");
|
||||||
|
assertNotNull(chan);
|
||||||
|
assertEquals(chan.getVersion(), Pubkey.LATEST_VERSION);
|
||||||
|
assertTrue(chan.isChan());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,10 @@ import ch.dissem.bitmessage.entity.payload.Pubkey;
|
|||||||
import ch.dissem.bitmessage.entity.payload.V4Pubkey;
|
import ch.dissem.bitmessage.entity.payload.V4Pubkey;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
||||||
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
import ch.dissem.bitmessage.utils.*;
|
import ch.dissem.bitmessage.utils.Base58;
|
||||||
|
import ch.dissem.bitmessage.utils.Bytes;
|
||||||
|
import ch.dissem.bitmessage.utils.Strings;
|
||||||
|
import ch.dissem.bitmessage.utils.TestUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
Loading…
Reference in New Issue
Block a user