Signature check works
This commit is contained in:
		| @@ -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; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user