diff --git a/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala b/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala index ea8588f..1a9dcdc 100644 --- a/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala +++ b/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala @@ -2,6 +2,7 @@ package com.github.fluency03.blockchain package core import com.github.fluency03.blockchain.core.BlockHeader.hashOfBlockHeader +import com.github.fluency03.blockchain.crypto.SHA256 import org.json4s.native.JsonMethods.{compact, render} import org.json4s.{Extraction, JValue} diff --git a/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala b/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala index 9f62110..187ace5 100644 --- a/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala +++ b/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala @@ -1,6 +1,8 @@ package com.github.fluency03.blockchain package core +import com.github.fluency03.blockchain.crypto.SHA256 + import scala.annotation.tailrec object Merkle { diff --git a/src/main/scala/com/github/fluency03/blockchain/core/SingleWallet.scala b/src/main/scala/com/github/fluency03/blockchain/core/SingleWallet.scala index d6b05af..1348919 100644 --- a/src/main/scala/com/github/fluency03/blockchain/core/SingleWallet.scala +++ b/src/main/scala/com/github/fluency03/blockchain/core/SingleWallet.scala @@ -5,12 +5,13 @@ import java.security.KeyPair import com.github.fluency03.blockchain.core.SingleWallet.balanceOfWallet import com.github.fluency03.blockchain.core.Transaction.signTxIn +import com.github.fluency03.blockchain.crypto.Secp256k1 import scala.collection.mutable case class SingleWallet() { - private[this] val keyPair: KeyPair = Crypto.generateKeyPair() + private[this] val keyPair: KeyPair = Secp256k1.generateKeyPair() lazy val address: String = keyPair.getPublic.toHex diff --git a/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala b/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala index dafff94..9b46674 100644 --- a/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala +++ b/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala @@ -3,8 +3,9 @@ package core import java.security.KeyPair -import com.github.fluency03.blockchain.Crypto.recoverPublicKey +import com.github.fluency03.blockchain.crypto.Secp256k1.recoverPublicKey import com.github.fluency03.blockchain.core.Transaction.{hashOfTransaction, validateTransaction} +import com.github.fluency03.blockchain.crypto.{SHA256, Secp256k1} import org.json4s.native.JsonMethods.{compact, render} import org.json4s.{Extraction, JValue} @@ -83,7 +84,7 @@ object Transaction { def signTxIn(txId: Bytes, txIn: TxIn, keyPair: KeyPair, uTxO: TxOut): Option[TxIn] = if (keyPair.getPublic.toHex != uTxO.address) None - else Some(TxIn(txIn.previousOut, Crypto.sign(txId, keyPair.getPrivate.getEncoded).toHex)) + else Some(TxIn(txIn.previousOut, Secp256k1.sign(txId, keyPair.getPrivate.getEncoded).toHex)) // validate TxIn's signature def validateTxIn(txIn: TxIn, txId: String, uTxOs: mutable.Map[Outpoint, TxOut]): Boolean = @@ -96,7 +97,7 @@ object Transaction { } def validateTxIn(txId: Bytes, txOut: TxOut, txIn: TxIn): Boolean = - Crypto.verify(txId, recoverPublicKey(txOut.address).getEncoded, txIn.signature.hex2Bytes) + Secp256k1.verify(txId, recoverPublicKey(txOut.address).getEncoded, txIn.signature.hex2Bytes) // validate TxOut: Sum of TxOuts is equal to the sum of TxIns def validateTxOutValues(transaction: Transaction, uTxOs: mutable.Map[Outpoint, TxOut]): Boolean = diff --git a/src/main/scala/com/github/fluency03/blockchain/Base58.scala b/src/main/scala/com/github/fluency03/blockchain/crypto/Base58.scala similarity index 99% rename from src/main/scala/com/github/fluency03/blockchain/Base58.scala rename to src/main/scala/com/github/fluency03/blockchain/crypto/Base58.scala index bff83a8..945851e 100644 --- a/src/main/scala/com/github/fluency03/blockchain/Base58.scala +++ b/src/main/scala/com/github/fluency03/blockchain/crypto/Base58.scala @@ -1,4 +1,5 @@ package com.github.fluency03.blockchain +package crypto import org.bouncycastle.util.encoders.Hex diff --git a/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala b/src/main/scala/com/github/fluency03/blockchain/crypto/RIPEMD160.scala similarity index 97% rename from src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala rename to src/main/scala/com/github/fluency03/blockchain/crypto/RIPEMD160.scala index ff9a3ee..e419135 100644 --- a/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala +++ b/src/main/scala/com/github/fluency03/blockchain/crypto/RIPEMD160.scala @@ -1,4 +1,5 @@ package com.github.fluency03.blockchain +package crypto import org.bouncycastle.crypto.digests.RIPEMD160Digest diff --git a/src/main/scala/com/github/fluency03/blockchain/SHA256.scala b/src/main/scala/com/github/fluency03/blockchain/crypto/SHA256.scala similarity index 98% rename from src/main/scala/com/github/fluency03/blockchain/SHA256.scala rename to src/main/scala/com/github/fluency03/blockchain/crypto/SHA256.scala index a76ddc5..e1c10a4 100644 --- a/src/main/scala/com/github/fluency03/blockchain/SHA256.scala +++ b/src/main/scala/com/github/fluency03/blockchain/crypto/SHA256.scala @@ -1,4 +1,5 @@ package com.github.fluency03.blockchain +package crypto import java.security.MessageDigest diff --git a/src/main/scala/com/github/fluency03/blockchain/Crypto.scala b/src/main/scala/com/github/fluency03/blockchain/crypto/Secp256k1.scala similarity index 98% rename from src/main/scala/com/github/fluency03/blockchain/Crypto.scala rename to src/main/scala/com/github/fluency03/blockchain/crypto/Secp256k1.scala index 5c05595..9e5d904 100644 --- a/src/main/scala/com/github/fluency03/blockchain/Crypto.scala +++ b/src/main/scala/com/github/fluency03/blockchain/crypto/Secp256k1.scala @@ -1,4 +1,5 @@ package com.github.fluency03.blockchain +package crypto import java.math.BigInteger import java.security._ @@ -9,7 +10,7 @@ import org.bouncycastle.jce.interfaces.{ECPrivateKey, ECPublicKey} import org.bouncycastle.jce.provider.BouncyCastleProvider import org.bouncycastle.jce.spec.{ECParameterSpec, ECPrivateKeySpec, ECPublicKeySpec} -object Crypto { +object Secp256k1 { Security.addProvider(new BouncyCastleProvider) diff --git a/src/main/scala/com/github/fluency03/blockchain/package.scala b/src/main/scala/com/github/fluency03/blockchain/package.scala index 5f85872..49afe74 100644 --- a/src/main/scala/com/github/fluency03/blockchain/package.scala +++ b/src/main/scala/com/github/fluency03/blockchain/package.scala @@ -4,8 +4,9 @@ import java.nio.charset.Charset import java.security.{PrivateKey, PublicKey} import java.time.Instant -import com.github.fluency03.blockchain.Crypto.{privateKeyToHex, publicKeyToHex} +import com.github.fluency03.blockchain.crypto.Secp256k1.{privateKeyToHex, publicKeyToHex} import com.github.fluency03.blockchain.core.{Peer, PeerSimple, TxIn, TxOut} +import com.github.fluency03.blockchain.crypto.{RIPEMD160, SHA256} import org.bouncycastle.crypto.digests.RIPEMD160Digest import org.bouncycastle.util.encoders.{Base64, Hex} import org.json4s.native.Serialization @@ -100,6 +101,6 @@ package object blockchain { /** * Decode a Base64 to String. */ - def fromBase64(base64: String): String = new String(Base64.decode(base64), "UTF-8") + def fromBase64(base64: String): String = new String(Base64.decode(base64)) } diff --git a/src/test/scala/com/github/fluency03/blockchain/core/BlockTest.scala b/src/test/scala/com/github/fluency03/blockchain/core/BlockTest.scala index 27fbb40..5ba5d57 100644 --- a/src/test/scala/com/github/fluency03/blockchain/core/BlockTest.scala +++ b/src/test/scala/com/github/fluency03/blockchain/core/BlockTest.scala @@ -6,6 +6,7 @@ import java.security.KeyPair import com.github.fluency03.blockchain.core.Block.allTransValidOf import com.github.fluency03.blockchain.core.BlockHeader.hashOfBlockHeader import com.github.fluency03.blockchain.core.Transaction.{COINBASE_AMOUNT, createCoinbaseTx, signTxIn, updateUTxOs} +import com.github.fluency03.blockchain.crypto.Secp256k1 import org.json4s.JValue import org.json4s.JsonAST.{JArray, JInt, JObject, JString} import org.json4s.JsonDSL._ @@ -154,7 +155,7 @@ class BlockTest extends FlatSpec with Matchers { genesis.allTransAreValid(uTxOs) shouldEqual true allTransValidOf(Nil, 0, uTxOs) shouldEqual false - val pair1 = Crypto.generateKeyPair() + val pair1 = Secp256k1.generateKeyPair() val address1 = pair1.getPublic.toHex val ts = getCurrentTimestamp @@ -171,7 +172,7 @@ class BlockTest extends FlatSpec with Matchers { nextBlock.allTransAreValid(uTxOs) shouldEqual false val genesisPrivate: String = Source.fromResource("private-key").getLines.mkString - val keyPair = new KeyPair(Crypto.recoverPublicKey(genesisMiner), Crypto.recoverPrivateKey(genesisPrivate)) + val keyPair = new KeyPair(Secp256k1.recoverPublicKey(genesisMiner), Secp256k1.recoverPrivateKey(genesisPrivate)) val signedTxIns = tx.txIns.map(txIn => signTxIn(tx.id.hex2Bytes, txIn, keyPair, uTxOs)).filter(_.isDefined).map(_.get) signedTxIns.length shouldEqual tx.txIns.length val signedTx = Transaction(signedTxIns, Seq(TxOut(address1, COINBASE_AMOUNT)), ts) diff --git a/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala b/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala index f6749f3..122f6a3 100644 --- a/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala +++ b/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala @@ -3,6 +3,7 @@ package core import com.github.fluency03.blockchain.core.Merkle._ import com.github.fluency03.blockchain.core.Transaction.createCoinbaseTx +import com.github.fluency03.blockchain.crypto.SHA256 import org.scalatest.{FlatSpec, Matchers} class MerkleTest extends FlatSpec with Matchers { diff --git a/src/test/scala/com/github/fluency03/blockchain/core/TransactionTest.scala b/src/test/scala/com/github/fluency03/blockchain/core/TransactionTest.scala index 1071396..3f89cb0 100644 --- a/src/test/scala/com/github/fluency03/blockchain/core/TransactionTest.scala +++ b/src/test/scala/com/github/fluency03/blockchain/core/TransactionTest.scala @@ -4,6 +4,7 @@ package core import java.security.KeyPair import com.github.fluency03.blockchain.core.Transaction._ +import com.github.fluency03.blockchain.crypto.Secp256k1 import org.json4s.JValue import org.json4s.native.JsonMethods.parse import org.scalatest.{FlatSpec, Matchers} @@ -94,11 +95,11 @@ class TransactionTest extends FlatSpec with Matchers { "Transaction" should "be able to be signed by key pair." in { val txIn = TxIn(Outpoint("def0", 0), "abc") - val pair: KeyPair = Crypto.generateKeyPair() + val pair: KeyPair = Secp256k1.generateKeyPair() val hash = "ace0" - val signature = Crypto.sign(hash.hex2Bytes, pair.getPrivate.getEncoded) - Crypto.verify(hash.hex2Bytes, pair.getPublic.getEncoded, signature) shouldEqual true + val signature = Secp256k1.sign(hash.hex2Bytes, pair.getPrivate.getEncoded) + Secp256k1.verify(hash.hex2Bytes, pair.getPublic.getEncoded, signature) shouldEqual true val uTxOs: mutable.Map[Outpoint, TxOut] = mutable.Map.empty[Outpoint, TxOut] val signedTxIn0 = signTxIn(hash, txIn, pair, uTxOs) @@ -115,15 +116,15 @@ class TransactionTest extends FlatSpec with Matchers { signedTxIn shouldEqual Some(TxIn(Outpoint("def0", 0), signedTxIn.get.signature)) signedTxIn.get.previousOut shouldEqual Outpoint("def0", 0) - Crypto.verify(hash.hex2Bytes, pair.getPublic.getEncoded, signedTxIn.get.signature.hex2Bytes) shouldEqual true + Secp256k1.verify(hash.hex2Bytes, pair.getPublic.getEncoded, signedTxIn.get.signature.hex2Bytes) shouldEqual true } "Transaction" should "have valid TxIns." in { - val pair: KeyPair = Crypto.generateKeyPair() + val pair: KeyPair = Secp256k1.generateKeyPair() val hash = "ace0" - val signature = Crypto.sign(hash.hex2Bytes, pair.getPrivate.getEncoded) - Crypto.verify(hash.hex2Bytes, pair.getPublic.getEncoded, signature) shouldEqual true + val signature = Secp256k1.sign(hash.hex2Bytes, pair.getPrivate.getEncoded) + Secp256k1.verify(hash.hex2Bytes, pair.getPublic.getEncoded, signature) shouldEqual true val txIn = TxIn(Outpoint("def0", 0), "abc1") val uTxOs: mutable.Map[Outpoint, TxOut] = mutable.Map.empty[Outpoint, TxOut] @@ -139,7 +140,7 @@ class TransactionTest extends FlatSpec with Matchers { } "Transaction" should "have valid TxOut values." in { - val pair: KeyPair = Crypto.generateKeyPair() + val pair: KeyPair = Secp256k1.generateKeyPair() val uTxOs: mutable.Map[Outpoint, TxOut] = mutable.Map.empty[Outpoint, TxOut] uTxOs += (Outpoint("def0", 1) -> TxOut("abc4", 20)) @@ -176,9 +177,9 @@ class TransactionTest extends FlatSpec with Matchers { } "Transaction" should "have be validatable." in { - val pair1 = Crypto.generateKeyPair() + val pair1 = Secp256k1.generateKeyPair() val address1 = pair1.getPublic.toHex - val pair2 = Crypto.generateKeyPair() + val pair2 = Secp256k1.generateKeyPair() val address2 = pair2.getPublic.toHex val randHash = "".toSha256 val tx: Transaction = Transaction( diff --git a/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala b/src/test/scala/com/github/fluency03/blockchain/crypto/Base58Test.scala similarity index 99% rename from src/test/scala/com/github/fluency03/blockchain/Base58Test.scala rename to src/test/scala/com/github/fluency03/blockchain/crypto/Base58Test.scala index c87d1d9..284bf33 100644 --- a/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala +++ b/src/test/scala/com/github/fluency03/blockchain/crypto/Base58Test.scala @@ -1,4 +1,5 @@ package com.github.fluency03.blockchain +package crypto import org.scalatest.{FlatSpec, Matchers} diff --git a/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala b/src/test/scala/com/github/fluency03/blockchain/crypto/RIPEMD160Test.scala similarity index 98% rename from src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala rename to src/test/scala/com/github/fluency03/blockchain/crypto/RIPEMD160Test.scala index f99b72e..0b9a2c4 100644 --- a/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala +++ b/src/test/scala/com/github/fluency03/blockchain/crypto/RIPEMD160Test.scala @@ -1,4 +1,5 @@ package com.github.fluency03.blockchain +package crypto import org.scalatest.{FlatSpec, Matchers} diff --git a/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala b/src/test/scala/com/github/fluency03/blockchain/crypto/SHA256Test.scala similarity index 99% rename from src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala rename to src/test/scala/com/github/fluency03/blockchain/crypto/SHA256Test.scala index 7ef4f58..7fc946e 100644 --- a/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala +++ b/src/test/scala/com/github/fluency03/blockchain/crypto/SHA256Test.scala @@ -1,4 +1,5 @@ package com.github.fluency03.blockchain +package crypto import org.scalatest.{FlatSpec, Matchers} diff --git a/src/test/scala/com/github/fluency03/blockchain/CryptoTest.scala b/src/test/scala/com/github/fluency03/blockchain/crypto/Secp256k1Test.scala similarity index 78% rename from src/test/scala/com/github/fluency03/blockchain/CryptoTest.scala rename to src/test/scala/com/github/fluency03/blockchain/crypto/Secp256k1Test.scala index e16b37d..880a17c 100644 --- a/src/test/scala/com/github/fluency03/blockchain/CryptoTest.scala +++ b/src/test/scala/com/github/fluency03/blockchain/crypto/Secp256k1Test.scala @@ -1,13 +1,12 @@ package com.github.fluency03.blockchain - -import com.github.fluency03.blockchain.Crypto._ +package crypto import java.security.KeyPair -import org.bouncycastle.jce.interfaces.{ECPrivateKey, ECPublicKey} +import com.github.fluency03.blockchain.crypto.Secp256k1._ import org.scalatest.{FlatSpec, Matchers} -class CryptoTest extends FlatSpec with Matchers { +class Secp256k1Test extends FlatSpec with Matchers { "Crypto" should "be able to sign a data and verify the signature. " in { val pair: KeyPair = generateKeyPair() @@ -21,7 +20,7 @@ class CryptoTest extends FlatSpec with Matchers { recoverPublicKey(pair.getPublic.toHex) shouldEqual pair.getPublic recoverPrivateKey(pair.getPrivate.toHex) shouldEqual pair.getPrivate - Crypto.publicKeyToAddress("04B4D653FCBB4B96000C99343F23B08A44FA306031E0587F9E657AB" + + Secp256k1.publicKeyToAddress("04B4D653FCBB4B96000C99343F23B08A44FA306031E0587F9E657AB" + "4A2541129368D7D9BB05CD8AFBDF7705A6540D98028236965553F91BF1C5B4F70073F55B55D") shouldEqual "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" }