Skip to content

Commit

Permalink
refactor crypto package
Browse files Browse the repository at this point in the history
  • Loading branch information
fluency03 committed May 6, 2018
1 parent 3015009 commit e403833
Show file tree
Hide file tree
Showing 16 changed files with 39 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.github.fluency03.blockchain
package core

import com.github.fluency03.blockchain.crypto.SHA256

import scala.annotation.tailrec

object Merkle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down Expand Up @@ -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 =
Expand All @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.github.fluency03.blockchain
package crypto

import org.bouncycastle.util.encoders.Hex

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.github.fluency03.blockchain
package crypto

import org.bouncycastle.crypto.digests.RIPEMD160Digest

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.github.fluency03.blockchain
package crypto

import java.security.MessageDigest

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.github.fluency03.blockchain
package crypto

import java.math.BigInteger
import java.security._
Expand All @@ -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)

Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/com/github/fluency03/blockchain/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))

}
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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)
Expand All @@ -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]
Expand All @@ -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))
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.github.fluency03.blockchain
package crypto

import org.scalatest.{FlatSpec, Matchers}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.github.fluency03.blockchain
package crypto

import org.scalatest.{FlatSpec, Matchers}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.github.fluency03.blockchain
package crypto

import org.scalatest.{FlatSpec, Matchers}

Expand Down
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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"
}
Expand Down

0 comments on commit e403833

Please sign in to comment.