From 1d3340a547dd61cc3839e28244c48a1e3a82b224 Mon Sep 17 00:00:00 2001 From: Christian Basler Date: Thu, 8 Jun 2017 21:56:31 +0200 Subject: [PATCH] Migrated cryptography and some improvements --- README.md | 2 +- .../ch/dissem/bitmessage/BitmessageContext.kt | 10 +- .../cryptography/bc/BouncyCryptography.java | 145 ----------------- .../cryptography/bc/BouncyCryptography.kt | 122 +++++++++++++++ .../bitmessage/security/CryptographyTest.kt | 2 +- .../cryptography/sc/SpongyCryptography.java | 147 ------------------ .../cryptography/sc/SpongyCryptography.kt | 122 +++++++++++++++ .../bitmessage/security/CryptographyTest.kt | 18 +-- .../java/ch/dissem/bitmessage/demo/Main.java | 2 +- .../java/ch/dissem/bitmessage/SystemTest.java | 4 +- .../networking/NetworkHandlerTest.java | 4 +- .../bitmessage/wif/WifExporterTest.java | 4 +- .../bitmessage/wif/WifImporterTest.java | 4 +- 13 files changed, 270 insertions(+), 316 deletions(-) delete mode 100644 cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.java create mode 100644 cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.kt delete mode 100644 cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.java create mode 100644 cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.kt diff --git a/README.md b/README.md index 75f2b28..dcbffa4 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ BitmessageContext ctx = new BitmessageContext.Builder() .powRepo(new JdbcProofOfWorkRepository(jdbcConfig)) .nodeRegistry(new JdbcNodeRegistry(jdbcConfig)) .networkHandler(new NioNetworkHandler()) - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .listener(System.out::println) .build(); ``` diff --git a/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.kt b/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.kt index ef4b1d6..175e378 100644 --- a/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.kt +++ b/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.kt @@ -311,7 +311,6 @@ class BitmessageContext private constructor(builder: BitmessageContext.Builder) } catch (e: Exception) { LOG.debug(e.message, e) } - } } @@ -410,6 +409,15 @@ class BitmessageContext private constructor(builder: BitmessageContext.Builder) return this } + fun listener(listener: (Plaintext) -> Unit): Builder { + this.listener = object : Listener { + override fun receive(plaintext: Plaintext) { + listener.invoke(plaintext) + } + } + return this + } + fun connectionLimit(connectionLimit: Int): Builder { this.connectionLimit = connectionLimit return this diff --git a/cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.java b/cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.java deleted file mode 100644 index bc8ec93..0000000 --- a/cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2015 Christian Basler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.dissem.bitmessage.cryptography.bc; - -import ch.dissem.bitmessage.entity.payload.Pubkey; -import ch.dissem.bitmessage.entity.valueobject.PrivateKey; -import ch.dissem.bitmessage.exception.ApplicationException; -import ch.dissem.bitmessage.ports.AbstractCryptography; -import org.bouncycastle.asn1.x9.X9ECParameters; -import org.bouncycastle.crypto.BufferedBlockCipher; -import org.bouncycastle.crypto.CipherParameters; -import org.bouncycastle.crypto.InvalidCipherTextException; -import org.bouncycastle.crypto.ec.CustomNamedCurves; -import org.bouncycastle.crypto.engines.AESEngine; -import org.bouncycastle.crypto.modes.CBCBlockCipher; -import org.bouncycastle.crypto.paddings.PKCS7Padding; -import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; -import org.bouncycastle.crypto.params.KeyParameter; -import org.bouncycastle.crypto.params.ParametersWithIV; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.jce.spec.ECParameterSpec; -import org.bouncycastle.jce.spec.ECPrivateKeySpec; -import org.bouncycastle.jce.spec.ECPublicKeySpec; -import org.bouncycastle.math.ec.ECPoint; - -import java.math.BigInteger; -import java.security.*; -import java.security.spec.KeySpec; -import java.util.Arrays; - -/** - * As Spongycastle can't be used on the Oracle JVM, and Bouncycastle doesn't work properly on Android (thanks, Google), - * this is the Bouncycastle implementation. - */ -public class BouncyCryptography extends AbstractCryptography { - private static final X9ECParameters EC_CURVE_PARAMETERS = CustomNamedCurves.getByName("secp256k1"); - - public BouncyCryptography() { - super(new BouncyCastleProvider()); - } - - @Override - public byte[] crypt(boolean encrypt, byte[] data, byte[] key_e, byte[] initializationVector) { - BufferedBlockCipher cipher = new PaddedBufferedBlockCipher( - new CBCBlockCipher(new AESEngine()), - new PKCS7Padding() - ); - CipherParameters params = new ParametersWithIV(new KeyParameter(key_e), initializationVector); - - cipher.init(encrypt, params); - - byte[] buffer = new byte[cipher.getOutputSize(data.length)]; - int length = cipher.processBytes(data, 0, data.length, buffer, 0); - try { - length += cipher.doFinal(buffer, length); - } catch (InvalidCipherTextException e) { - throw new IllegalArgumentException(e); - } - if (length < buffer.length) { - return Arrays.copyOfRange(buffer, 0, length); - } - return buffer; - } - - @Override - public byte[] createPublicKey(byte[] privateKey) { - return EC_CURVE_PARAMETERS.getG().multiply(keyToBigInt(privateKey)).normalize().getEncoded(false); - } - - private ECPoint keyToPoint(byte[] publicKey) { - BigInteger x = new BigInteger(1, Arrays.copyOfRange(publicKey, 1, 33)); - BigInteger y = new BigInteger(1, Arrays.copyOfRange(publicKey, 33, 65)); - return EC_CURVE_PARAMETERS.getCurve().createPoint(x, y); - } - - @Override - public boolean isSignatureValid(byte[] data, byte[] signature, Pubkey pubkey) { - try { - ECParameterSpec spec = new ECParameterSpec( - EC_CURVE_PARAMETERS.getCurve(), - EC_CURVE_PARAMETERS.getG(), - EC_CURVE_PARAMETERS.getN(), - EC_CURVE_PARAMETERS.getH(), - EC_CURVE_PARAMETERS.getSeed() - ); - - ECPoint Q = keyToPoint(pubkey.getSigningKey()); - KeySpec keySpec = new ECPublicKeySpec(Q, spec); - PublicKey publicKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider).generatePublic(keySpec); - - return doCheckSignature(data, signature, publicKey); - } catch (GeneralSecurityException e) { - throw new ApplicationException(e); - } - } - - @Override - public byte[] getSignature(byte[] data, PrivateKey privateKey) { - try { - ECParameterSpec spec = new ECParameterSpec( - EC_CURVE_PARAMETERS.getCurve(), - EC_CURVE_PARAMETERS.getG(), - EC_CURVE_PARAMETERS.getN(), - EC_CURVE_PARAMETERS.getH(), - EC_CURVE_PARAMETERS.getSeed() - ); - - BigInteger d = keyToBigInt(privateKey.getPrivateSigningKey()); - KeySpec keySpec = new ECPrivateKeySpec(d, spec); - java.security.PrivateKey privKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider) - .generatePrivate(keySpec); - - return doSign(data, privKey); - } catch (GeneralSecurityException e) { - throw new ApplicationException(e); - } - } - - @Override - public byte[] multiply(byte[] K, byte[] r) { - return keyToPoint(K).multiply(keyToBigInt(r)).normalize().getEncoded(false); - } - - @Override - public byte[] createPoint(byte[] x, byte[] y) { - return EC_CURVE_PARAMETERS.getCurve().createPoint( - new BigInteger(1, x), - new BigInteger(1, y) - ).getEncoded(false); - } -} diff --git a/cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.kt b/cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.kt new file mode 100644 index 0000000..89e38e2 --- /dev/null +++ b/cryptography-bc/src/main/java/ch/dissem/bitmessage/cryptography/bc/BouncyCryptography.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2015 Christian Basler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.dissem.bitmessage.cryptography.bc + +import ch.dissem.bitmessage.entity.payload.Pubkey +import ch.dissem.bitmessage.entity.valueobject.PrivateKey +import ch.dissem.bitmessage.ports.AbstractCryptography +import org.bouncycastle.crypto.InvalidCipherTextException +import org.bouncycastle.crypto.ec.CustomNamedCurves +import org.bouncycastle.crypto.engines.AESEngine +import org.bouncycastle.crypto.modes.CBCBlockCipher +import org.bouncycastle.crypto.paddings.PKCS7Padding +import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher +import org.bouncycastle.crypto.params.KeyParameter +import org.bouncycastle.crypto.params.ParametersWithIV +import org.bouncycastle.jce.provider.BouncyCastleProvider +import org.bouncycastle.jce.spec.ECParameterSpec +import org.bouncycastle.jce.spec.ECPrivateKeySpec +import org.bouncycastle.jce.spec.ECPublicKeySpec +import org.bouncycastle.math.ec.ECPoint +import java.math.BigInteger +import java.security.KeyFactory +import java.util.* + +/** + * As Spongycastle can't be used on the Oracle JVM, and Bouncycastle doesn't work properly on Android (thanks, Google), + * this is the Bouncycastle implementation. + */ +object BouncyCryptography : AbstractCryptography(BouncyCastleProvider()) { + private val EC_CURVE_PARAMETERS = CustomNamedCurves.getByName("secp256k1") + + override fun crypt(encrypt: Boolean, data: ByteArray, key_e: ByteArray, initializationVector: ByteArray): ByteArray { + val cipher = PaddedBufferedBlockCipher( + CBCBlockCipher(AESEngine()), + PKCS7Padding() + ) + val params = ParametersWithIV(KeyParameter(key_e), initializationVector) + + cipher.init(encrypt, params) + + val buffer = ByteArray(cipher.getOutputSize(data.size)) + var length = cipher.processBytes(data, 0, data.size, buffer, 0) + try { + length += cipher.doFinal(buffer, length) + } catch (e: InvalidCipherTextException) { + throw IllegalArgumentException(e) + } + + if (length < buffer.size) { + return Arrays.copyOfRange(buffer, 0, length) + } + return buffer + } + + override fun createPublicKey(privateKey: ByteArray): ByteArray { + return EC_CURVE_PARAMETERS.g.multiply(keyToBigInt(privateKey)).normalize().getEncoded(false) + } + + private fun keyToPoint(publicKey: ByteArray): ECPoint { + val x = BigInteger(1, Arrays.copyOfRange(publicKey, 1, 33)) + val y = BigInteger(1, Arrays.copyOfRange(publicKey, 33, 65)) + return EC_CURVE_PARAMETERS.curve.createPoint(x, y) + } + + override fun isSignatureValid(data: ByteArray, signature: ByteArray, pubkey: Pubkey): Boolean { + val spec = ECParameterSpec( + EC_CURVE_PARAMETERS.curve, + EC_CURVE_PARAMETERS.g, + EC_CURVE_PARAMETERS.n, + EC_CURVE_PARAMETERS.h, + EC_CURVE_PARAMETERS.seed + ) + + val Q = keyToPoint(pubkey.signingKey) + val keySpec = ECPublicKeySpec(Q, spec) + val publicKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider).generatePublic(keySpec) + + return doCheckSignature(data, signature, publicKey) + } + + override fun getSignature(data: ByteArray, privateKey: PrivateKey): ByteArray { + val spec = ECParameterSpec( + EC_CURVE_PARAMETERS.curve, + EC_CURVE_PARAMETERS.g, + EC_CURVE_PARAMETERS.n, + EC_CURVE_PARAMETERS.h, + EC_CURVE_PARAMETERS.seed + ) + + val d = keyToBigInt(privateKey.privateSigningKey) + val keySpec = ECPrivateKeySpec(d, spec) + val privKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider) + .generatePrivate(keySpec) + + return doSign(data, privKey) + } + + override fun multiply(k: ByteArray, r: ByteArray): ByteArray { + return keyToPoint(k).multiply(keyToBigInt(r)).normalize().getEncoded(false) + } + + override fun createPoint(x: ByteArray, y: ByteArray): ByteArray { + return EC_CURVE_PARAMETERS.curve.createPoint( + BigInteger(1, x), + BigInteger(1, y) + ).getEncoded(false) + } +} diff --git a/cryptography-bc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt b/cryptography-bc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt index 1897512..c51c296 100644 --- a/cryptography-bc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt +++ b/cryptography-bc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt @@ -163,7 +163,7 @@ class CryptographyTest { val TEST_RIPEMD160 = DatatypeConverter.parseHexBinary("" + "cd566972b5e50104011a92b59fa8e0b1234851ae") - private val crypto = BouncyCryptography() + private val crypto = BouncyCryptography init { Singleton.initialize(crypto) diff --git a/cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.java b/cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.java deleted file mode 100644 index f86e6c2..0000000 --- a/cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2015 Christian Basler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.dissem.bitmessage.cryptography.sc; - -import ch.dissem.bitmessage.entity.payload.Pubkey; -import ch.dissem.bitmessage.entity.valueobject.PrivateKey; -import ch.dissem.bitmessage.exception.ApplicationException; -import ch.dissem.bitmessage.ports.AbstractCryptography; -import org.spongycastle.asn1.x9.X9ECParameters; -import org.spongycastle.crypto.BufferedBlockCipher; -import org.spongycastle.crypto.CipherParameters; -import org.spongycastle.crypto.InvalidCipherTextException; -import org.spongycastle.crypto.ec.CustomNamedCurves; -import org.spongycastle.crypto.engines.AESEngine; -import org.spongycastle.crypto.modes.CBCBlockCipher; -import org.spongycastle.crypto.paddings.PKCS7Padding; -import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher; -import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.crypto.params.ParametersWithIV; -import org.spongycastle.jce.provider.BouncyCastleProvider; -import org.spongycastle.jce.spec.ECParameterSpec; -import org.spongycastle.jce.spec.ECPrivateKeySpec; -import org.spongycastle.jce.spec.ECPublicKeySpec; -import org.spongycastle.math.ec.ECPoint; - -import java.math.BigInteger; -import java.security.GeneralSecurityException; -import java.security.KeyFactory; -import java.security.PublicKey; -import java.security.spec.KeySpec; -import java.util.Arrays; - -/** - * As Spongycastle can't be used on the Oracle JVM, and Bouncycastle doesn't work properly on Android (thanks, Google), - * this is the Spongycastle implementation. - */ -public class SpongyCryptography extends AbstractCryptography { - private static final X9ECParameters EC_CURVE_PARAMETERS = CustomNamedCurves.getByName("secp256k1"); - - public SpongyCryptography() { - super(new BouncyCastleProvider()); - } - - @Override - public byte[] crypt(boolean encrypt, byte[] data, byte[] key_e, byte[] initializationVector) { - BufferedBlockCipher cipher = new PaddedBufferedBlockCipher( - new CBCBlockCipher(new AESEngine()), - new PKCS7Padding() - ); - CipherParameters params = new ParametersWithIV(new KeyParameter(key_e), initializationVector); - - cipher.init(encrypt, params); - - byte[] buffer = new byte[cipher.getOutputSize(data.length)]; - int length = cipher.processBytes(data, 0, data.length, buffer, 0); - try { - length += cipher.doFinal(buffer, length); - } catch (InvalidCipherTextException e) { - throw new IllegalArgumentException(e); - } - if (length < buffer.length) { - return Arrays.copyOfRange(buffer, 0, length); - } - return buffer; - } - - @Override - public byte[] createPublicKey(byte[] privateKey) { - return EC_CURVE_PARAMETERS.getG().multiply(keyToBigInt(privateKey)).normalize().getEncoded(false); - } - - private ECPoint keyToPoint(byte[] publicKey) { - BigInteger x = new BigInteger(1, Arrays.copyOfRange(publicKey, 1, 33)); - BigInteger y = new BigInteger(1, Arrays.copyOfRange(publicKey, 33, 65)); - return EC_CURVE_PARAMETERS.getCurve().createPoint(x, y); - } - - @Override - public boolean isSignatureValid(byte[] data, byte[] signature, Pubkey pubkey) { - try { - ECParameterSpec spec = new ECParameterSpec( - EC_CURVE_PARAMETERS.getCurve(), - EC_CURVE_PARAMETERS.getG(), - EC_CURVE_PARAMETERS.getN(), - EC_CURVE_PARAMETERS.getH(), - EC_CURVE_PARAMETERS.getSeed() - ); - - ECPoint Q = keyToPoint(pubkey.getSigningKey()); - KeySpec keySpec = new ECPublicKeySpec(Q, spec); - PublicKey publicKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider).generatePublic(keySpec); - - return doCheckSignature(data, signature, publicKey); - } catch (GeneralSecurityException e) { - throw new ApplicationException(e); - } - } - - @Override - public byte[] getSignature(byte[] data, PrivateKey privateKey) { - try { - ECParameterSpec spec = new ECParameterSpec( - EC_CURVE_PARAMETERS.getCurve(), - EC_CURVE_PARAMETERS.getG(), - EC_CURVE_PARAMETERS.getN(), - EC_CURVE_PARAMETERS.getH(), - EC_CURVE_PARAMETERS.getSeed() - ); - - BigInteger d = keyToBigInt(privateKey.getPrivateSigningKey()); - KeySpec keySpec = new ECPrivateKeySpec(d, spec); - java.security.PrivateKey privKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider) - .generatePrivate(keySpec); - - return doSign(data, privKey); - } catch (GeneralSecurityException e) { - throw new ApplicationException(e); - } - } - - @Override - public byte[] multiply(byte[] K, byte[] r) { - return keyToPoint(K).multiply(keyToBigInt(r)).normalize().getEncoded(false); - } - - @Override - public byte[] createPoint(byte[] x, byte[] y) { - return EC_CURVE_PARAMETERS.getCurve().createPoint( - new BigInteger(1, x), - new BigInteger(1, y) - ).getEncoded(false); - } -} diff --git a/cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.kt b/cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.kt new file mode 100644 index 0000000..f2e2320 --- /dev/null +++ b/cryptography-sc/src/main/java/ch/dissem/bitmessage/cryptography/sc/SpongyCryptography.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2015 Christian Basler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.dissem.bitmessage.cryptography.sc + +import ch.dissem.bitmessage.entity.payload.Pubkey +import ch.dissem.bitmessage.entity.valueobject.PrivateKey +import ch.dissem.bitmessage.ports.AbstractCryptography +import org.spongycastle.crypto.InvalidCipherTextException +import org.spongycastle.crypto.ec.CustomNamedCurves +import org.spongycastle.crypto.engines.AESEngine +import org.spongycastle.crypto.modes.CBCBlockCipher +import org.spongycastle.crypto.paddings.PKCS7Padding +import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher +import org.spongycastle.crypto.params.KeyParameter +import org.spongycastle.crypto.params.ParametersWithIV +import org.spongycastle.jce.provider.BouncyCastleProvider +import org.spongycastle.jce.spec.ECParameterSpec +import org.spongycastle.jce.spec.ECPrivateKeySpec +import org.spongycastle.jce.spec.ECPublicKeySpec +import org.spongycastle.math.ec.ECPoint +import java.math.BigInteger +import java.security.KeyFactory +import java.util.* + +/** + * As Spongycastle can't be used on the Oracle JVM, and Bouncycastle doesn't work properly on Android (thanks, Google), + * this is the Spongycastle implementation. + */ +object SpongyCryptography : AbstractCryptography(BouncyCastleProvider()) { + private val EC_CURVE_PARAMETERS = CustomNamedCurves.getByName("secp256k1") + + override fun crypt(encrypt: Boolean, data: ByteArray, key_e: ByteArray, initializationVector: ByteArray): ByteArray { + val cipher = PaddedBufferedBlockCipher( + CBCBlockCipher(AESEngine()), + PKCS7Padding() + ) + val params = ParametersWithIV(KeyParameter(key_e), initializationVector) + + cipher.init(encrypt, params) + + val buffer = ByteArray(cipher.getOutputSize(data.size)) + var length = cipher.processBytes(data, 0, data.size, buffer, 0) + try { + length += cipher.doFinal(buffer, length) + } catch (e: InvalidCipherTextException) { + throw IllegalArgumentException(e) + } + + if (length < buffer.size) { + return Arrays.copyOfRange(buffer, 0, length) + } + return buffer + } + + override fun createPublicKey(privateKey: ByteArray): ByteArray { + return EC_CURVE_PARAMETERS.g.multiply(keyToBigInt(privateKey)).normalize().getEncoded(false) + } + + private fun keyToPoint(publicKey: ByteArray): ECPoint { + val x = BigInteger(1, Arrays.copyOfRange(publicKey, 1, 33)) + val y = BigInteger(1, Arrays.copyOfRange(publicKey, 33, 65)) + return EC_CURVE_PARAMETERS.curve.createPoint(x, y) + } + + override fun isSignatureValid(data: ByteArray, signature: ByteArray, pubkey: Pubkey): Boolean { + val spec = ECParameterSpec( + EC_CURVE_PARAMETERS.curve, + EC_CURVE_PARAMETERS.g, + EC_CURVE_PARAMETERS.n, + EC_CURVE_PARAMETERS.h, + EC_CURVE_PARAMETERS.seed + ) + + val Q = keyToPoint(pubkey.signingKey) + val keySpec = ECPublicKeySpec(Q, spec) + val publicKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider).generatePublic(keySpec) + + return doCheckSignature(data, signature, publicKey) + } + + override fun getSignature(data: ByteArray, privateKey: PrivateKey): ByteArray { + val spec = ECParameterSpec( + EC_CURVE_PARAMETERS.curve, + EC_CURVE_PARAMETERS.g, + EC_CURVE_PARAMETERS.n, + EC_CURVE_PARAMETERS.h, + EC_CURVE_PARAMETERS.seed + ) + + val d = keyToBigInt(privateKey.privateSigningKey) + val keySpec = ECPrivateKeySpec(d, spec) + val privKey = KeyFactory.getInstance(ALGORITHM_ECDSA, provider) + .generatePrivate(keySpec) + + return doSign(data, privKey) + } + + override fun multiply(k: ByteArray, r: ByteArray): ByteArray { + return keyToPoint(k).multiply(keyToBigInt(r)).normalize().getEncoded(false) + } + + override fun createPoint(x: ByteArray, y: ByteArray): ByteArray { + return EC_CURVE_PARAMETERS.curve.createPoint( + BigInteger(1, x), + BigInteger(1, y) + ).getEncoded(false) + } +} diff --git a/cryptography-sc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt b/cryptography-sc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt index e456159..c8eafe0 100644 --- a/cryptography-sc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt +++ b/cryptography-sc/src/test/java/ch/dissem/bitmessage/security/CryptographyTest.kt @@ -16,7 +16,6 @@ package ch.dissem.bitmessage.security -import ch.dissem.bitmessage.InternalContext import ch.dissem.bitmessage.cryptography.sc.SpongyCryptography import ch.dissem.bitmessage.entity.ObjectMessage import ch.dissem.bitmessage.entity.payload.GenericPayload @@ -26,21 +25,16 @@ import ch.dissem.bitmessage.ports.MultiThreadedPOWEngine import ch.dissem.bitmessage.ports.ProofOfWorkEngine import ch.dissem.bitmessage.utils.CallbackWaiter import ch.dissem.bitmessage.utils.Singleton +import ch.dissem.bitmessage.utils.TestUtils import ch.dissem.bitmessage.utils.UnixTime -import org.junit.Assert -import org.junit.BeforeClass -import org.junit.Test - -import javax.xml.bind.DatatypeConverter -import java.io.ByteArrayInputStream -import java.io.IOException - import ch.dissem.bitmessage.utils.UnixTime.DAY import ch.dissem.bitmessage.utils.UnixTime.MINUTE import org.hamcrest.CoreMatchers.`is` import org.junit.Assert.* -import org.mockito.Mockito.mock -import org.mockito.Mockito.`when` +import org.junit.Test +import java.io.ByteArrayInputStream +import java.io.IOException +import javax.xml.bind.DatatypeConverter /** * @author Christian Basler @@ -168,7 +162,7 @@ class CryptographyTest { val TEST_RIPEMD160 = DatatypeConverter.parseHexBinary("" + "cd566972b5e50104011a92b59fa8e0b1234851ae") - private val crypto = SpongyCryptography() + private val crypto = SpongyCryptography init { Singleton.initialize(crypto) diff --git a/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java b/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java index 1da2910..2c9ca8e 100644 --- a/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java +++ b/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java @@ -61,7 +61,7 @@ public class Main { .messageRepo(new JdbcMessageRepository(jdbcConfig)) .powRepo(new JdbcProofOfWorkRepository(jdbcConfig)) .networkHandler(new NioNetworkHandler()) - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .port(48444); if (options.localPort != null) { ctxBuilder.nodeRegistry(new NodeRegistry() { diff --git a/demo/src/test/java/ch/dissem/bitmessage/SystemTest.java b/demo/src/test/java/ch/dissem/bitmessage/SystemTest.java index fe3343d..293741f 100644 --- a/demo/src/test/java/ch/dissem/bitmessage/SystemTest.java +++ b/demo/src/test/java/ch/dissem/bitmessage/SystemTest.java @@ -94,7 +94,7 @@ public class SystemTest { .port(alicePort) .nodeRegistry(new TestNodeRegistry(bobPort)) .networkHandler(aliceNetworkHandler) - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .listener(aliceListener) .labeler(aliceLabeler) .build(); @@ -110,7 +110,7 @@ public class SystemTest { .port(bobPort) .nodeRegistry(new TestNodeRegistry(alicePort)) .networkHandler(bobNetworkHandler) - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .listener(bobListener) .labeler(new DebugLabeler("Bob")) .build(); diff --git a/networking/src/test/java/ch/dissem/bitmessage/networking/NetworkHandlerTest.java b/networking/src/test/java/ch/dissem/bitmessage/networking/NetworkHandlerTest.java index f079ede..a4e7d54 100644 --- a/networking/src/test/java/ch/dissem/bitmessage/networking/NetworkHandlerTest.java +++ b/networking/src/test/java/ch/dissem/bitmessage/networking/NetworkHandlerTest.java @@ -98,7 +98,7 @@ public class NetworkHandlerTest { .port(peerAddress.getPort()) .nodeRegistry(new TestNodeRegistry()) .networkHandler(peerNetworkHandler) - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .listener(mock(BitmessageContext.Listener.class)) .customCommandHandler(new CustomCommandHandler() { @Override @@ -133,7 +133,7 @@ public class NetworkHandlerTest { .port(6002) .nodeRegistry(new TestNodeRegistry(peerAddress)) .networkHandler(nodeNetworkHandler) - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .listener(mock(BitmessageContext.Listener.class)) .build(); } diff --git a/wif/src/test/java/ch/dissem/bitmessage/wif/WifExporterTest.java b/wif/src/test/java/ch/dissem/bitmessage/wif/WifExporterTest.java index 225f2f9..d5e8bde 100644 --- a/wif/src/test/java/ch/dissem/bitmessage/wif/WifExporterTest.java +++ b/wif/src/test/java/ch/dissem/bitmessage/wif/WifExporterTest.java @@ -36,7 +36,7 @@ public class WifExporterTest { @Before public void setUp() throws Exception { ctx = new BitmessageContext.Builder() - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .networkHandler(mock(NetworkHandler.class)) .inventory(mock(Inventory.class)) .messageRepo(mock(MessageRepository.class)) @@ -104,4 +104,4 @@ public class WifExporterTest { exporter.addIdentity(chan); assertEquals(expected, exporter.toString()); } -} \ No newline at end of file +} diff --git a/wif/src/test/java/ch/dissem/bitmessage/wif/WifImporterTest.java b/wif/src/test/java/ch/dissem/bitmessage/wif/WifImporterTest.java index 398ff20..2116b3a 100644 --- a/wif/src/test/java/ch/dissem/bitmessage/wif/WifImporterTest.java +++ b/wif/src/test/java/ch/dissem/bitmessage/wif/WifImporterTest.java @@ -36,7 +36,7 @@ public class WifImporterTest { @Before public void setUp() throws Exception { ctx = new BitmessageContext.Builder() - .cryptography(new BouncyCryptography()) + .cryptography(BouncyCryptography.INSTANCE) .networkHandler(mock(NetworkHandler.class)) .inventory(mock(Inventory.class)) .messageRepo(mock(MessageRepository.class)) @@ -113,4 +113,4 @@ public class WifImporterTest { BitmessageAddress chan = importer.getIdentities().get(0); assertTrue(chan.isChan()); } -} \ No newline at end of file +}