Signature check works
This commit is contained in:
parent
ee9c006794
commit
ed14e95d70
@ -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;
|
throw new IllegalArgumentException("Pubkey has incompatible tag");
|
||||||
if (!Arrays.equals(tag, v4.getTag()))
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user