Signature check works

This commit is contained in:
Christian Basler 2015-05-15 12:36:57 +02:00
parent ee9c006794
commit ed14e95d70
6 changed files with 73 additions and 32 deletions

View File

@ -41,7 +41,7 @@ public class BitmessageAddress {
/** /**
* Used for V4 address encryption. It's easier to just create it regardless of address version. * Used for V4 address encryption. It's easier to just create it regardless of address version.
*/ */
private final byte[] privateEncryptionKey; private final byte[] pubkeyDecryptionKey;
private String address; private String address;
@ -62,7 +62,7 @@ public class BitmessageAddress {
// for the tag, the checksum has to be created with 0x00 padding // for the tag, the checksum has to be created with 0x00 padding
byte[] checksum = Security.doubleSha512(os.toByteArray(), ripe); byte[] checksum = Security.doubleSha512(os.toByteArray(), ripe);
this.tag = Arrays.copyOfRange(checksum, 32, 64); this.tag = Arrays.copyOfRange(checksum, 32, 64);
this.privateEncryptionKey = Arrays.copyOfRange(checksum, 0, 32); this.pubkeyDecryptionKey = Arrays.copyOfRange(checksum, 0, 32);
// but for the address and its checksum they need to be stripped // but for the address and its checksum they need to be stripped
int offset = Bytes.numberOfLeadingZeros(ripe); int offset = Bytes.numberOfLeadingZeros(ripe);
os.write(ripe, offset, ripe.length - offset); os.write(ripe, offset, ripe.length - offset);
@ -103,7 +103,7 @@ public class BitmessageAddress {
} }
checksum = Security.doubleSha512(Arrays.copyOfRange(bytes, 0, counter.length()), ripe); checksum = Security.doubleSha512(Arrays.copyOfRange(bytes, 0, counter.length()), ripe);
this.tag = Arrays.copyOfRange(checksum, 32, 64); this.tag = Arrays.copyOfRange(checksum, 32, 64);
this.privateEncryptionKey = Arrays.copyOfRange(checksum, 0, 32); this.pubkeyDecryptionKey = Arrays.copyOfRange(checksum, 0, 32);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -135,20 +135,18 @@ public class BitmessageAddress {
public void setPubkey(Pubkey pubkey) { public void setPubkey(Pubkey pubkey) {
if (pubkey instanceof V4Pubkey) { if (pubkey instanceof V4Pubkey) {
try { if (!Arrays.equals(tag, ((V4Pubkey) pubkey).getTag()))
V4Pubkey v4 = (V4Pubkey) pubkey;
if (!Arrays.equals(tag, v4.getTag()))
throw new IllegalArgumentException("Pubkey has incompatible tag"); throw new IllegalArgumentException("Pubkey has incompatible tag");
v4.decrypt(privateEncryptionKey);
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
if (!Arrays.equals(ripe, pubkey.getRipe())) if (!Arrays.equals(ripe, pubkey.getRipe()))
throw new IllegalArgumentException("Pubkey has incompatible ripe"); throw new IllegalArgumentException("Pubkey has incompatible ripe");
this.pubkey = pubkey; this.pubkey = pubkey;
} }
public byte[] getPubkeyDecryptionKey() {
return pubkeyDecryptionKey;
}
public PrivateKey getPrivateKey() { public PrivateKey getPrivateKey() {
return privateKey; return privateKey;
} }

View File

@ -25,4 +25,6 @@ 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;
boolean isDecrypted();
} }

View File

@ -90,6 +90,10 @@ public class ObjectMessage implements MessagePayload {
return new InventoryVector(Bytes.truncate(Security.doubleSha512(nonce, getPayloadBytesWithoutNonce()), 32)); return new InventoryVector(Bytes.truncate(Security.doubleSha512(nonce, getPayloadBytesWithoutNonce()), 32));
} }
private boolean isEncrypted() {
return payload instanceof Encrypted && !((Encrypted) payload).isDecrypted();
}
public boolean isSigned() { public boolean isSigned() {
return payload.isSigned(); return payload.isSigned();
} }
@ -103,10 +107,23 @@ public class ObjectMessage implements MessagePayload {
public void sign(PrivateKey key) { public void sign(PrivateKey key) {
// TODO // TODO
// Security.
} }
public boolean isSignatureValid() throws IOException { public void decrypt(PrivateKey key) throws IOException {
Pubkey pubkey = null; // TODO if (payload instanceof Encrypted){
((Encrypted) payload).decrypt(key.getPrivateEncryptionKey());
}
}
public void decrypt(byte[] privateEncryptionKey) throws IOException {
if (payload instanceof Encrypted){
((Encrypted) payload).decrypt(privateEncryptionKey);
}
}
public boolean isSignatureValid(Pubkey pubkey) throws IOException {
if (isEncrypted()) throw new IllegalStateException("Payload must be decrypted first");
return Security.isSignatureValid(getBytesToSign(), payload.getSignature(), pubkey); return Security.isSignatureValid(getBytesToSign(), payload.getSignature(), pubkey);
} }

View File

@ -65,12 +65,23 @@ public class V4Pubkey extends Pubkey implements Encrypted {
decrypted = V3Pubkey.read(encrypted.decrypt(privateKey), stream); decrypted = V3Pubkey.read(encrypted.decrypt(privateKey), stream);
} }
@Override
public boolean isDecrypted() {
return decrypted != null;
}
@Override @Override
public void write(OutputStream stream) throws IOException { public void write(OutputStream stream) throws IOException {
stream.write(tag); stream.write(tag);
encrypted.write(stream); encrypted.write(stream);
} }
@Override
public void writeBytesToSign(OutputStream out) throws IOException {
out.write(tag);
decrypted.writeBytesToSign(out);
}
@Override @Override
public long getVersion() { public long getVersion() {
return 4; return 4;

View File

@ -22,8 +22,14 @@ 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;
import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -31,9 +37,8 @@ import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.*;
import java.security.MessageDigest; import java.security.spec.KeySpec;
import java.security.SecureRandom;
import java.util.Arrays; import java.util.Arrays;
/** /**
@ -181,18 +186,24 @@ public class Security {
public static boolean isSignatureValid(byte[] bytesToSign, byte[] signature, Pubkey pubkey) { public static boolean isSignatureValid(byte[] bytesToSign, byte[] signature, Pubkey pubkey) {
ECPoint W = keyToPoint(pubkey.getSigningKey()); ECPoint W = keyToPoint(pubkey.getSigningKey());
// try { try {
// ECParameterSpec param = null; ECParameterSpec spec = new ECParameterSpec(
// KeySpec keySpec = new ECPublicKeySpec(W, param); EC_CURVE_PARAMETERS.getCurve(),
// PublicKey publicKey = KeyFactory.getInstance("ECDSA", "BC").generatePublic(keySpec); EC_CURVE_PARAMETERS.getG(),
// EC_CURVE_PARAMETERS.getN(),
// Signature sig = Signature.getInstance("ECDSA", "BC"); EC_CURVE_PARAMETERS.getH(),
// sig.initVerify(publicKey); EC_CURVE_PARAMETERS.getSeed()
// sig.update(bytesToSign); );
// return sig.verify(signature);
// } catch (Exception e) { KeySpec keySpec = new ECPublicKeySpec(W, spec);
// throw new RuntimeException(e); PublicKey publicKey = KeyFactory.getInstance("ECDSA", "BC").generatePublic(keySpec);
// }
return false; // TODO Signature sig = Signature.getInstance("ECDSA", "BC");
sig.initVerify(publicKey);
sig.update(bytesToSign);
return sig.verify(signature);
} catch (Exception e) {
throw new RuntimeException(e);
}
} }
} }

View File

@ -73,6 +73,7 @@ public class BitmessageAddressTest {
ObjectMessage object = TestUtils.loadObjectMessage(3, "V3Pubkey.payload"); ObjectMessage object = TestUtils.loadObjectMessage(3, "V3Pubkey.payload");
Pubkey pubkey = (Pubkey) object.getPayload(); Pubkey pubkey = (Pubkey) object.getPayload();
assertTrue(object.isSignatureValid(pubkey));
address.setPubkey(pubkey); address.setPubkey(pubkey);
assertArrayEquals(Bytes.fromHex("007402be6e76c3cb87caa946d0c003a3d4d8e1d5"), pubkey.getRipe()); assertArrayEquals(Bytes.fromHex("007402be6e76c3cb87caa946d0c003a3d4d8e1d5"), pubkey.getRipe());
@ -80,10 +81,11 @@ public class BitmessageAddressTest {
@Test @Test
public void testV4PubkeyImport() throws IOException { public void testV4PubkeyImport() throws IOException {
// TODO
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
V4Pubkey pubkey = (V4Pubkey) object.getPayload();
BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h"); BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
object.decrypt(address.getPubkeyDecryptionKey());
V4Pubkey pubkey = (V4Pubkey) object.getPayload();
assertTrue(object.isSignatureValid(pubkey));
address.setPubkey(pubkey); address.setPubkey(pubkey);
} }