Inventory items are now saved only if processing didn't fail. Receiving messages works, but there seems to be a problem with the POW check in some circumstances.
This commit is contained in:
parent
6b3b361aa3
commit
b793526f2f
@ -206,7 +206,7 @@ public class Application {
|
|||||||
|
|
||||||
private void messages() {
|
private void messages() {
|
||||||
String command;
|
String command;
|
||||||
List<Plaintext> messages = ctx.messages().findMessages(Plaintext.Status.RECEIVED);
|
List<Plaintext> messages = ctx.messages().findMessages(Plaintext.Status.NEW);
|
||||||
do {
|
do {
|
||||||
System.out.println();
|
System.out.println();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -230,7 +230,7 @@ public class Application {
|
|||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
try {
|
try {
|
||||||
int index = Integer.parseInt(command);
|
int index = Integer.parseInt(command) - 1;
|
||||||
show(messages.get(index));
|
show(messages.get(index));
|
||||||
} catch (NumberFormatException | IndexOutOfBoundsException e) {
|
} catch (NumberFormatException | IndexOutOfBoundsException e) {
|
||||||
System.out.println("Unknown command. Please try again.");
|
System.out.println("Unknown command. Please try again.");
|
||||||
@ -249,9 +249,9 @@ public class Application {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
String command;
|
String command;
|
||||||
do {
|
do {
|
||||||
System.out.printf("r) reply");
|
System.out.println("r) reply");
|
||||||
System.out.println("d) delete");
|
System.out.println("d) delete");
|
||||||
System.out.printf("b) back");
|
System.out.println("b) back");
|
||||||
command = nextCommand();
|
command = nextCommand();
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "r":
|
case "r":
|
||||||
|
@ -142,11 +142,7 @@ public class BitmessageContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void startup(Listener listener) {
|
public void startup(Listener listener) {
|
||||||
MessageListener messageListener = new DefaultMessageListener(ctx, listener);
|
ctx.getNetworkHandler().start(new DefaultMessageListener(ctx, listener));
|
||||||
for (ObjectMessage object : ctx.getInventory().getObjects(0, 0, PUBKEY, MSG)) {
|
|
||||||
messageListener.receive(object);
|
|
||||||
}
|
|
||||||
ctx.getNetworkHandler().start(messageListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
@ -20,6 +20,7 @@ import ch.dissem.bitmessage.entity.BitmessageAddress;
|
|||||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
import ch.dissem.bitmessage.entity.payload.*;
|
import ch.dissem.bitmessage.entity.payload.*;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
import ch.dissem.bitmessage.ports.NetworkHandler;
|
import ch.dissem.bitmessage.ports.NetworkHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -28,6 +29,7 @@ import java.io.IOException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ch.dissem.bitmessage.entity.Plaintext.Status.DOING_PROOF_OF_WORK;
|
import static ch.dissem.bitmessage.entity.Plaintext.Status.DOING_PROOF_OF_WORK;
|
||||||
|
import static ch.dissem.bitmessage.entity.Plaintext.Status.NEW;
|
||||||
import static ch.dissem.bitmessage.entity.Plaintext.Status.SENT;
|
import static ch.dissem.bitmessage.entity.Plaintext.Status.SENT;
|
||||||
import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
||||||
|
|
||||||
@ -42,7 +44,7 @@ class DefaultMessageListener implements NetworkHandler.MessageListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void receive(ObjectMessage object) {
|
public void receive(ObjectMessage object) throws IOException {
|
||||||
ObjectPayload payload = object.getPayload();
|
ObjectPayload payload = object.getPayload();
|
||||||
if (payload.getType() == null) return;
|
if (payload.getType() == null) return;
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ class DefaultMessageListener implements NetworkHandler.MessageListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void receive(ObjectMessage object, Pubkey pubkey) {
|
protected void receive(ObjectMessage object, Pubkey pubkey) throws IOException {
|
||||||
BitmessageAddress address;
|
BitmessageAddress address;
|
||||||
try {
|
try {
|
||||||
if (pubkey instanceof V4Pubkey) {
|
if (pubkey instanceof V4Pubkey) {
|
||||||
@ -106,26 +108,28 @@ class DefaultMessageListener implements NetworkHandler.MessageListener {
|
|||||||
ctx.getMessageRepository().save(msg);
|
ctx.getMessageRepository().save(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException | IOException e) {
|
} catch (DecryptionFailedException ignore) {
|
||||||
LOG.debug(e.getMessage(), e);
|
LOG.debug(ignore.getMessage(), ignore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void receive(ObjectMessage object, Msg msg) {
|
protected void receive(ObjectMessage object, Msg msg) throws IOException {
|
||||||
for (BitmessageAddress identity : ctx.getAddressRepo().getIdentities()) {
|
for (BitmessageAddress identity : ctx.getAddressRepo().getIdentities()) {
|
||||||
try {
|
try {
|
||||||
msg.decrypt(identity.getPrivateKey().getPrivateEncryptionKey());
|
msg.decrypt(identity.getPrivateKey().getPrivateEncryptionKey());
|
||||||
msg.getPlaintext().setTo(identity);
|
msg.getPlaintext().setTo(identity);
|
||||||
object.isSignatureValid(msg.getPlaintext().getFrom().getPubkey());
|
object.isSignatureValid(msg.getPlaintext().getFrom().getPubkey());
|
||||||
|
msg.getPlaintext().setStatus(NEW);
|
||||||
ctx.getMessageRepository().save(msg.getPlaintext());
|
ctx.getMessageRepository().save(msg.getPlaintext());
|
||||||
listener.receive(msg.getPlaintext());
|
listener.receive(msg.getPlaintext());
|
||||||
break;
|
break;
|
||||||
} catch (IOException | RuntimeException ignore) {
|
} catch (DecryptionFailedException ignore) {
|
||||||
|
LOG.debug(ignore.getMessage(), ignore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void receive(ObjectMessage object, Broadcast broadcast) {
|
protected void receive(ObjectMessage object, Broadcast broadcast) throws IOException {
|
||||||
// TODO this should work fine as-is, but checking the tag might be more efficient
|
// TODO this should work fine as-is, but checking the tag might be more efficient
|
||||||
// V5Broadcast v5 = broadcast instanceof V5Broadcast ? (V5Broadcast) broadcast : null;
|
// V5Broadcast v5 = broadcast instanceof V5Broadcast ? (V5Broadcast) broadcast : null;
|
||||||
for (BitmessageAddress subscription : ctx.getAddressRepo().getSubscriptions()) {
|
for (BitmessageAddress subscription : ctx.getAddressRepo().getSubscriptions()) {
|
||||||
@ -133,7 +137,7 @@ class DefaultMessageListener implements NetworkHandler.MessageListener {
|
|||||||
broadcast.decrypt(subscription.getPubkeyDecryptionKey());
|
broadcast.decrypt(subscription.getPubkeyDecryptionKey());
|
||||||
object.isSignatureValid(broadcast.getPlaintext().getFrom().getPubkey());
|
object.isSignatureValid(broadcast.getPlaintext().getFrom().getPubkey());
|
||||||
listener.receive(broadcast.getPlaintext());
|
listener.receive(broadcast.getPlaintext());
|
||||||
} catch (IOException ignore) {
|
} catch (DecryptionFailedException ignore) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package ch.dissem.bitmessage.entity;
|
package ch.dissem.bitmessage.entity;
|
||||||
|
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,7 +26,7 @@ import java.io.IOException;
|
|||||||
public interface Encrypted {
|
public interface Encrypted {
|
||||||
void encrypt(byte[] publicKey) throws IOException;
|
void encrypt(byte[] publicKey) throws IOException;
|
||||||
|
|
||||||
void decrypt(byte[] privateKey) throws IOException;
|
void decrypt(byte[] privateKey) throws IOException, DecryptionFailedException;
|
||||||
|
|
||||||
boolean isDecrypted();
|
boolean isDecrypted();
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import ch.dissem.bitmessage.entity.payload.ObjectType;
|
|||||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
import ch.dissem.bitmessage.utils.Bytes;
|
import ch.dissem.bitmessage.utils.Bytes;
|
||||||
import ch.dissem.bitmessage.utils.Encode;
|
import ch.dissem.bitmessage.utils.Encode;
|
||||||
import ch.dissem.bitmessage.utils.Security;
|
import ch.dissem.bitmessage.utils.Security;
|
||||||
@ -116,13 +117,13 @@ public class ObjectMessage implements MessagePayload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decrypt(PrivateKey key) throws IOException {
|
public void decrypt(PrivateKey key) throws IOException, DecryptionFailedException {
|
||||||
if (payload instanceof Encrypted) {
|
if (payload instanceof Encrypted) {
|
||||||
((Encrypted) payload).decrypt(key.getPrivateEncryptionKey());
|
((Encrypted) payload).decrypt(key.getPrivateEncryptionKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decrypt(byte[] privateEncryptionKey) throws IOException {
|
public void decrypt(byte[] privateEncryptionKey) throws IOException, DecryptionFailedException {
|
||||||
if (payload instanceof Encrypted) {
|
if (payload instanceof Encrypted) {
|
||||||
((Encrypted) payload).decrypt(privateEncryptionKey);
|
((Encrypted) payload).decrypt(privateEncryptionKey);
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ public class Plaintext implements Streamable {
|
|||||||
public void setTo(BitmessageAddress to) {
|
public void setTo(BitmessageAddress to) {
|
||||||
if (this.to.getVersion() != 0)
|
if (this.to.getVersion() != 0)
|
||||||
throw new RuntimeException("Correct address already set");
|
throw new RuntimeException("Correct address already set");
|
||||||
if (Arrays.equals(this.to.getRipe(), to.getRipe())) {
|
if (!Arrays.equals(this.to.getRipe(), to.getRipe())) {
|
||||||
throw new RuntimeException("RIPEs don't match");
|
throw new RuntimeException("RIPEs don't match");
|
||||||
}
|
}
|
||||||
this.to = to;
|
this.to = to;
|
||||||
@ -210,7 +210,7 @@ public class Plaintext implements Streamable {
|
|||||||
SENT_ACKNOWLEDGED,
|
SENT_ACKNOWLEDGED,
|
||||||
|
|
||||||
// For received messages
|
// For received messages
|
||||||
RECEIVED,
|
NEW,
|
||||||
READ
|
READ
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,9 +348,6 @@ public class Plaintext implements Streamable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Plaintext build() {
|
public Plaintext build() {
|
||||||
if (id == null) {
|
|
||||||
id = UUID.randomUUID();
|
|
||||||
}
|
|
||||||
if (from == null) {
|
if (from == null) {
|
||||||
from = new BitmessageAddress(Factory.createPubkey(
|
from = new BitmessageAddress(Factory.createPubkey(
|
||||||
addressVersion,
|
addressVersion,
|
||||||
|
@ -18,6 +18,7 @@ package ch.dissem.bitmessage.entity.payload;
|
|||||||
|
|
||||||
import ch.dissem.bitmessage.entity.Encrypted;
|
import ch.dissem.bitmessage.entity.Encrypted;
|
||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ public abstract class Broadcast extends ObjectPayload implements Encrypted {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decrypt(byte[] privateKey) throws IOException {
|
public void decrypt(byte[] privateKey) throws IOException, DecryptionFailedException {
|
||||||
plaintext = Plaintext.read(encrypted.decrypt(privateKey));
|
plaintext = Plaintext.read(encrypted.decrypt(privateKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package ch.dissem.bitmessage.entity.payload;
|
package ch.dissem.bitmessage.entity.payload;
|
||||||
|
|
||||||
import ch.dissem.bitmessage.entity.Streamable;
|
import ch.dissem.bitmessage.entity.Streamable;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
import ch.dissem.bitmessage.utils.*;
|
import ch.dissem.bitmessage.utils.*;
|
||||||
import org.bouncycastle.crypto.BufferedBlockCipher;
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||||
import org.bouncycastle.crypto.CipherParameters;
|
import org.bouncycastle.crypto.CipherParameters;
|
||||||
@ -99,7 +100,7 @@ public class CryptoBox implements Streamable {
|
|||||||
/**
|
/**
|
||||||
* @see <a href='https://bitmessage.org/wiki/Encryption#Decryption'>https://bitmessage.org/wiki/Encryption#Decryption</a>
|
* @see <a href='https://bitmessage.org/wiki/Encryption#Decryption'>https://bitmessage.org/wiki/Encryption#Decryption</a>
|
||||||
*/
|
*/
|
||||||
public InputStream decrypt(byte[] privateKey) {
|
public InputStream decrypt(byte[] privateKey) throws DecryptionFailedException {
|
||||||
// 1. The private key used to decrypt is called k.
|
// 1. The private key used to decrypt is called k.
|
||||||
BigInteger k = Security.keyToBigInt(privateKey);
|
BigInteger k = Security.keyToBigInt(privateKey);
|
||||||
// 2. Do an EC point multiply with private key k and public key R. This gives you public key P.
|
// 2. Do an EC point multiply with private key k and public key R. This gives you public key P.
|
||||||
@ -113,7 +114,7 @@ public class CryptoBox implements Streamable {
|
|||||||
// 5. Calculate MAC' with HMACSHA256, using key_m as salt and IV + R + cipher text as data.
|
// 5. Calculate MAC' with HMACSHA256, using key_m as salt and IV + R + cipher text as data.
|
||||||
// 6. Compare MAC with MAC'. If not equal, decryption will fail.
|
// 6. Compare MAC with MAC'. If not equal, decryption will fail.
|
||||||
if (!Arrays.equals(mac, calculateMac(key_m))) {
|
if (!Arrays.equals(mac, calculateMac(key_m))) {
|
||||||
throw new RuntimeException("Invalid MAC while decrypting");
|
throw new DecryptionFailedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Decrypt the cipher text with AES-256-CBC, using IV as initialization vector, key_e as decryption key
|
// 7. Decrypt the cipher text with AES-256-CBC, using IV as initialization vector, key_e as decryption key
|
||||||
|
@ -18,6 +18,7 @@ package ch.dissem.bitmessage.entity.payload;
|
|||||||
|
|
||||||
import ch.dissem.bitmessage.entity.Encrypted;
|
import ch.dissem.bitmessage.entity.Encrypted;
|
||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -85,7 +86,7 @@ public class Msg extends ObjectPayload implements Encrypted {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decrypt(byte[] privateKey) throws IOException {
|
public void decrypt(byte[] privateKey) throws IOException, DecryptionFailedException {
|
||||||
plaintext = Plaintext.read(encrypted.decrypt(privateKey));
|
plaintext = Plaintext.read(encrypted.decrypt(privateKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package ch.dissem.bitmessage.entity.payload;
|
|||||||
|
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||||
import ch.dissem.bitmessage.entity.Encrypted;
|
import ch.dissem.bitmessage.entity.Encrypted;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
import ch.dissem.bitmessage.utils.Decode;
|
import ch.dissem.bitmessage.utils.Decode;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -65,7 +66,7 @@ public class V4Pubkey extends Pubkey implements Encrypted {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decrypt(byte[] privateKey) throws IOException {
|
public void decrypt(byte[] privateKey) throws IOException, DecryptionFailedException {
|
||||||
decrypted = V3Pubkey.read(encrypted.decrypt(privateKey), stream);
|
decrypted = V3Pubkey.read(encrypted.decrypt(privateKey), stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,6 @@ import java.io.IOException;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by chris on 13.03.15.
|
|
||||||
*/
|
|
||||||
public class InventoryVector implements Streamable {
|
public class InventoryVector implements Streamable {
|
||||||
/**
|
/**
|
||||||
* Hash of the object
|
* Hash of the object
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package ch.dissem.bitmessage.exception;
|
||||||
|
|
||||||
|
public class DecryptionFailedException extends Exception {
|
||||||
|
}
|
@ -21,6 +21,8 @@ import ch.dissem.bitmessage.entity.ObjectMessage;
|
|||||||
import ch.dissem.bitmessage.entity.payload.ObjectPayload;
|
import ch.dissem.bitmessage.entity.payload.ObjectPayload;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles incoming messages
|
* Handles incoming messages
|
||||||
*/
|
*/
|
||||||
@ -32,6 +34,6 @@ public interface NetworkHandler {
|
|||||||
void offer(InventoryVector iv);
|
void offer(InventoryVector iv);
|
||||||
|
|
||||||
interface MessageListener {
|
interface MessageListener {
|
||||||
void receive(ObjectMessage object);
|
void receive(ObjectMessage object) throws IOException;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
package ch.dissem.bitmessage.utils;
|
package ch.dissem.bitmessage.utils;
|
||||||
|
|
||||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||||
import ch.dissem.bitmessage.entity.payload.*;
|
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||||
import ch.dissem.bitmessage.factory.Factory;
|
import ch.dissem.bitmessage.factory.Factory;
|
||||||
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
||||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||||
@ -35,7 +35,6 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.security.spec.KeySpec;
|
import java.security.spec.KeySpec;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -110,11 +109,10 @@ public class Security {
|
|||||||
* @throws IOException if proof of work doesn't check out
|
* @throws IOException if proof of work doesn't check out
|
||||||
*/
|
*/
|
||||||
public static void checkProofOfWork(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) throws IOException {
|
public static void checkProofOfWork(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) throws IOException {
|
||||||
if (Bytes.lt(
|
byte[] target = getProofOfWorkTarget(object, nonceTrialsPerByte, extraBytes);
|
||||||
getProofOfWorkTarget(object, nonceTrialsPerByte, extraBytes),
|
byte[] value = Security.doubleSha512(object.getNonce(), getInitialHash(object));
|
||||||
Security.doubleSha512(object.getNonce(), getInitialHash(object)),
|
if (Bytes.lt(target, value, 8)) {
|
||||||
8)) {
|
throw new IOException("Insufficient proof of work: " + Strings.hex(target) + " required, " + Strings.hex(Arrays.copyOfRange(value, 0, 8)) + " achieved.");
|
||||||
throw new IOException("Insufficient proof of work");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import ch.dissem.bitmessage.entity.payload.CryptoBox;
|
|||||||
import ch.dissem.bitmessage.entity.payload.GenericPayload;
|
import ch.dissem.bitmessage.entity.payload.GenericPayload;
|
||||||
import ch.dissem.bitmessage.entity.payload.Msg;
|
import ch.dissem.bitmessage.entity.payload.Msg;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
import ch.dissem.bitmessage.utils.Security;
|
import ch.dissem.bitmessage.utils.Security;
|
||||||
import ch.dissem.bitmessage.utils.TestUtils;
|
import ch.dissem.bitmessage.utils.TestUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -35,7 +36,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
|
|
||||||
public class EncryptionTest {
|
public class EncryptionTest {
|
||||||
@Test
|
@Test
|
||||||
public void ensureDecryptedDataIsSameAsBeforeEncryption() throws IOException {
|
public void ensureDecryptedDataIsSameAsBeforeEncryption() throws IOException, DecryptionFailedException {
|
||||||
GenericPayload before = new GenericPayload(1, Security.randomBytes(100));
|
GenericPayload before = new GenericPayload(1, Security.randomBytes(100));
|
||||||
|
|
||||||
PrivateKey privateKey = new PrivateKey(false, 1, 1000, 1000);
|
PrivateKey privateKey = new PrivateKey(false, 1, 1000, 1000);
|
||||||
@ -47,7 +48,7 @@ public class EncryptionTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensureMessageCanBeDecrypted() throws IOException {
|
public void ensureMessageCanBeDecrypted() throws IOException, DecryptionFailedException {
|
||||||
PrivateKey privateKey = PrivateKey.read(TestUtils.getResource("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8.privkey"));
|
PrivateKey privateKey = PrivateKey.read(TestUtils.getResource("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8.privkey"));
|
||||||
BitmessageAddress identity = new BitmessageAddress(privateKey);
|
BitmessageAddress identity = new BitmessageAddress(privateKey);
|
||||||
assertEquals("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8", identity.getAddress());
|
assertEquals("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8", identity.getAddress());
|
||||||
|
@ -24,6 +24,7 @@ import ch.dissem.bitmessage.entity.payload.ObjectType;
|
|||||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
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.utils.TestUtils;
|
import ch.dissem.bitmessage.utils.TestUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -56,23 +57,15 @@ public class SignatureTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensureMessageIsProperlySigned() throws IOException {
|
public void ensureMessageIsProperlySigned() throws IOException, DecryptionFailedException {
|
||||||
BitmessageAddress identity = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
BitmessageAddress identity = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||||
|
|
||||||
ObjectMessage object = TestUtils.loadObjectMessage(3, "V1Msg.payload");
|
ObjectMessage object = TestUtils.loadObjectMessage(3, "V1Msg.payload");
|
||||||
Msg msg = (Msg) object.getPayload();
|
Msg msg = (Msg) object.getPayload();
|
||||||
msg.decrypt(identity.getPrivateKey().getPrivateEncryptionKey());
|
msg.decrypt(identity.getPrivateKey().getPrivateEncryptionKey());
|
||||||
Plaintext plaintext = msg.getPlaintext();
|
Plaintext plaintext = msg.getPlaintext();
|
||||||
assertEquals(0, object.getExpiresTime());
|
assertEquals(TestUtils.loadContact().getPubkey(), plaintext.getFrom().getPubkey());
|
||||||
assertEquals(loadPubkey(), plaintext.getFrom().getPubkey());
|
|
||||||
assertNotNull(plaintext);
|
assertNotNull(plaintext);
|
||||||
assertTrue(object.isSignatureValid(plaintext.getFrom().getPubkey()));
|
assertTrue(object.isSignatureValid(plaintext.getFrom().getPubkey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private V4Pubkey loadPubkey() throws IOException {
|
|
||||||
BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
|
||||||
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
|
|
||||||
object.decrypt(address.getPubkeyDecryptionKey());
|
|
||||||
return (V4Pubkey) object.getPayload();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package ch.dissem.bitmessage.entity;
|
|||||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
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.utils.*;
|
import ch.dissem.bitmessage.utils.*;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ public class BitmessageAddressTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testV4PubkeyImport() throws IOException {
|
public void testV4PubkeyImport() throws IOException, DecryptionFailedException {
|
||||||
BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
||||||
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
|
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
|
||||||
object.decrypt(address.getPubkeyDecryptionKey());
|
object.decrypt(address.getPubkeyDecryptionKey());
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package ch.dissem.bitmessage.entity;
|
package ch.dissem.bitmessage.entity;
|
||||||
|
|
||||||
import ch.dissem.bitmessage.entity.payload.*;
|
import ch.dissem.bitmessage.entity.payload.*;
|
||||||
|
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||||
import ch.dissem.bitmessage.factory.Factory;
|
import ch.dissem.bitmessage.factory.Factory;
|
||||||
import ch.dissem.bitmessage.utils.TestUtils;
|
import ch.dissem.bitmessage.utils.TestUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -76,7 +77,7 @@ public class SerializationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensurePlaintextIsSerializedAndDeserializedCorrectly() throws IOException {
|
public void ensurePlaintextIsSerializedAndDeserializedCorrectly() throws IOException, DecryptionFailedException {
|
||||||
Plaintext p1 = new Plaintext.Builder()
|
Plaintext p1 = new Plaintext.Builder()
|
||||||
.from(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
.from(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
||||||
.to(TestUtils.loadContact())
|
.to(TestUtils.loadContact())
|
||||||
|
@ -20,6 +20,7 @@ import ch.dissem.bitmessage.entity.BitmessageAddress;
|
|||||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||||
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.factory.Factory;
|
import ch.dissem.bitmessage.factory.Factory;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -68,7 +69,7 @@ public class TestUtils {
|
|||||||
return identity;
|
return identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BitmessageAddress loadContact() throws IOException {
|
public static BitmessageAddress loadContact() throws IOException, DecryptionFailedException {
|
||||||
BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
||||||
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
|
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
|
||||||
object.decrypt(address.getPubkeyDecryptionKey());
|
object.decrypt(address.getPubkeyDecryptionKey());
|
||||||
|
@ -121,7 +121,7 @@ public class Connection implements Runnable {
|
|||||||
+ msg.getPayload().getCommand());
|
+ msg.getPayload().getCommand());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException ignore) {
|
||||||
if (state == ACTIVE) {
|
if (state == ACTIVE) {
|
||||||
sendQueue();
|
sendQueue();
|
||||||
}
|
}
|
||||||
@ -157,12 +157,11 @@ public class Connection implements Runnable {
|
|||||||
try {
|
try {
|
||||||
LOG.debug("Received object " + objectMessage.getInventoryVector());
|
LOG.debug("Received object " + objectMessage.getInventoryVector());
|
||||||
Security.checkProofOfWork(objectMessage, ctx.getNetworkNonceTrialsPerByte(), ctx.getNetworkExtraBytes());
|
Security.checkProofOfWork(objectMessage, ctx.getNetworkNonceTrialsPerByte(), ctx.getNetworkExtraBytes());
|
||||||
|
listener.receive(objectMessage);
|
||||||
ctx.getInventory().storeObject(objectMessage);
|
ctx.getInventory().storeObject(objectMessage);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.debug(e.getMessage(), e);
|
LOG.error("Stream " + objectMessage.getStream() + ", object type " + objectMessage.getType() + ": " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
// It's probably pointless, but let the listener decide if we accept the message for the client.
|
|
||||||
listener.receive(objectMessage);
|
|
||||||
break;
|
break;
|
||||||
case ADDR:
|
case ADDR:
|
||||||
Addr addr = (Addr) messagePayload;
|
Addr addr = (Addr) messagePayload;
|
||||||
|
@ -96,7 +96,7 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
|
|||||||
if (publicKeyBlob != null) {
|
if (publicKeyBlob != null) {
|
||||||
Pubkey pubkey = Factory.readPubkey(address.getVersion(), address.getStream(),
|
Pubkey pubkey = Factory.readPubkey(address.getVersion(), address.getStream(),
|
||||||
publicKeyBlob.getBinaryStream(), (int) publicKeyBlob.length(), false);
|
publicKeyBlob.getBinaryStream(), (int) publicKeyBlob.length(), false);
|
||||||
if (address.getVersion() == 4) {
|
if (address.getVersion() == 4 && pubkey instanceof V3Pubkey) {
|
||||||
pubkey = new V4Pubkey((V3Pubkey) pubkey);
|
pubkey = new V4Pubkey((V3Pubkey) pubkey);
|
||||||
}
|
}
|
||||||
address.setPubkey(pubkey);
|
address.setPubkey(pubkey);
|
||||||
@ -140,11 +140,11 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
|
|||||||
|
|
||||||
private void update(BitmessageAddress address) throws IOException, SQLException {
|
private void update(BitmessageAddress address) throws IOException, SQLException {
|
||||||
PreparedStatement ps = getConnection().prepareStatement(
|
PreparedStatement ps = getConnection().prepareStatement(
|
||||||
"UPDATE Address SET address=?, alias=?, public_key=?, private_key=?");
|
"UPDATE Address SET alias=?, public_key=?, private_key=? WHERE address=?");
|
||||||
ps.setString(1, address.getAddress());
|
ps.setString(1, address.getAlias());
|
||||||
ps.setString(2, address.getAlias());
|
writePubkey(ps, 2, address.getPubkey());
|
||||||
writePubkey(ps, 3, address.getPubkey());
|
writeBlob(ps, 3, address.getPrivateKey());
|
||||||
writeBlob(ps, 4, address.getPrivateKey());
|
ps.setString(4, address.getAddress());
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Plaintext> findMessages(Label label) {
|
public List<Plaintext> findMessages(Label label) {
|
||||||
return find("id IN SELECT message_id FROM Message_Label WHERE label_id=" + label.getId());
|
return find("id IN (SELECT message_id FROM Message_Label WHERE label_id=" + label.getId() + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,7 +94,7 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
|||||||
List<Label> result = new ArrayList<>();
|
List<Label> result = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
Statement stmt = getConnection().createStatement();
|
Statement stmt = getConnection().createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT label, color FROM Label WHERE id IN SELECT label_id FROM Message_Label WHERE message_id=" + messageId);
|
ResultSet rs = stmt.executeQuery("SELECT label, color FROM Label WHERE id IN (SELECT label_id FROM Message_Label WHERE message_id=" + messageId + ")");
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
result.add(new Label(rs.getString("label"), rs.getInt("color")));
|
result.add(new Label(rs.getString("label"), rs.getInt("color")));
|
||||||
}
|
}
|
||||||
@ -109,8 +109,8 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
|||||||
// save from address if necessary
|
// save from address if necessary
|
||||||
if (message.getId() == null) {
|
if (message.getId() == null) {
|
||||||
BitmessageAddress savedAddress = ctx.getAddressRepo().getAddress(message.getFrom().getAddress());
|
BitmessageAddress savedAddress = ctx.getAddressRepo().getAddress(message.getFrom().getAddress());
|
||||||
if (savedAddress.getPrivateKey() == null) {
|
if (savedAddress == null || savedAddress.getPrivateKey() == null) {
|
||||||
if (savedAddress.getAlias() != null) {
|
if (savedAddress != null && savedAddress.getAlias() != null) {
|
||||||
message.getFrom().setAlias(savedAddress.getAlias());
|
message.getFrom().setAlias(savedAddress.getAlias());
|
||||||
}
|
}
|
||||||
ctx.getAddressRepo().save(message.getFrom());
|
ctx.getAddressRepo().save(message.getFrom());
|
||||||
@ -157,7 +157,11 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
|||||||
writeBlob(ps, 3, message);
|
writeBlob(ps, 3, message);
|
||||||
ps.setLong(4, message.getSent());
|
ps.setLong(4, message.getSent());
|
||||||
ps.setLong(5, message.getReceived());
|
ps.setLong(5, message.getReceived());
|
||||||
|
if (message.getStatus() != null)
|
||||||
ps.setString(6, message.getStatus().name());
|
ps.setString(6, message.getStatus().name());
|
||||||
|
else
|
||||||
|
ps.setString(6, null);
|
||||||
|
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
|
|
||||||
// get generated id
|
// get generated id
|
||||||
@ -168,10 +172,14 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
|||||||
|
|
||||||
private void update(Connection connection, Plaintext message) throws SQLException, IOException {
|
private void update(Connection connection, Plaintext message) throws SQLException, IOException {
|
||||||
PreparedStatement ps = connection.prepareStatement(
|
PreparedStatement ps = connection.prepareStatement(
|
||||||
"UPDATE Message SET sent=?, received=?, status=?");
|
"UPDATE Message SET sent=?, received=?, status=? WHERE id=?");
|
||||||
ps.setLong(1, message.getSent());
|
ps.setLong(1, message.getSent());
|
||||||
ps.setLong(2, message.getReceived());
|
ps.setLong(2, message.getReceived());
|
||||||
|
ps.setLong(3, (Long) message.getId());
|
||||||
|
if (message.getStatus() != null)
|
||||||
ps.setString(3, message.getStatus().name());
|
ps.setString(3, message.getStatus().name());
|
||||||
|
else
|
||||||
|
ps.setString(3, null);
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user