From 819ea7c35498c81c178c1fcbae26a7541b1009c9 Mon Sep 17 00:00:00 2001 From: fluency03 Date: Sun, 6 May 2018 15:01:55 +0200 Subject: [PATCH] refactor ripemd160 --- .../github/fluency03/blockchain/Crypto.scala | 2 +- .../fluency03/blockchain/RIPEMD160.scala | 19 ++++++++++++ .../github/fluency03/blockchain/package.scala | 29 ++++--------------- .../fluency03/blockchain/Base58Test.scala | 11 ------- .../fluency03/blockchain/CryptoTest.scala | 4 +++ .../fluency03/blockchain/RIPEMD160Test.scala | 15 ++++++++++ .../fluency03/blockchain/SHA256Test.scala | 7 ----- 7 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/main/scala/com/github/fluency03/blockchain/Crypto.scala b/src/main/scala/com/github/fluency03/blockchain/Crypto.scala index f5aff58..5c05595 100644 --- a/src/main/scala/com/github/fluency03/blockchain/Crypto.scala +++ b/src/main/scala/com/github/fluency03/blockchain/Crypto.scala @@ -71,7 +71,7 @@ object Crypto { privateKey.asInstanceOf[ECPrivateKey].getD.toByteArray def publicKeyToAddress(publicKey: String, networkBytes: String = "00"): String = - Base58.checkEncode(networkBytes.hex2Bytes ++ publicKey.hex2Bytes.toHash160Bytes) + Base58.checkEncode(networkBytes.hex2Bytes ++ publicKey.hex2Bytes.toHash160Digest) diff --git a/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala b/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala index 7d7388f..ff9a3ee 100644 --- a/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala +++ b/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala @@ -1,5 +1,24 @@ package com.github.fluency03.blockchain +import org.bouncycastle.crypto.digests.RIPEMD160Digest + object RIPEMD160 { + def hash(str: String): String = hash(str.getBytes) + + def hash(bytes: Bytes): String = hashToDigest(bytes).map("%02x".format(_)).mkString + + def hashToDigest(bytes: Bytes): Bytes = { + val (raw, messageDigest) = (bytes, new RIPEMD160Digest()) + messageDigest.update(raw, 0, raw.length) + val out = Array.fill[Byte](messageDigest.getDigestSize)(0) + messageDigest.doFinal(out, 0) + out + } + + def doubleHash(bytes: Bytes): String = hash(SHA256.hashToDigest(bytes)) + + def doubleHashToDigest(bytes: Bytes): Bytes = hashToDigest(SHA256.hashToDigest(bytes)) + + } diff --git a/src/main/scala/com/github/fluency03/blockchain/package.scala b/src/main/scala/com/github/fluency03/blockchain/package.scala index 721c22c..6f86fcd 100644 --- a/src/main/scala/com/github/fluency03/blockchain/package.scala +++ b/src/main/scala/com/github/fluency03/blockchain/package.scala @@ -39,7 +39,7 @@ package object blockchain { def hex2Binary: String = binaryOfHex(str) def toBase64: String = base64Of(str.getBytes) def toSha256: String = SHA256.hash(str) - def toRipemd160Of: String = ripemd160Of(str) + def toRipemd160: String = RIPEMD160.hash(str) } implicit class BytesImplicit(val bytes: Bytes) { @@ -48,10 +48,10 @@ package object blockchain { def toBase64: String = base64Of(bytes) def toSha256: String = SHA256.hash(bytes) def toSha256Digest: Bytes = SHA256.hashToDigest(bytes) - def toRipemd160Of: String = ripemd160Of(bytes) - def toRipemd160ODigest: Bytes = ripemd160ODigestOf(bytes) - def toHash160: String = hash160Of(bytes) - def toHash160Bytes: Bytes = hash160BytesOf(bytes) + def toRipemd160Of: String = RIPEMD160.hash(bytes) + def toRipemd160ODigest: Bytes = RIPEMD160.hashToDigest(bytes) + def toHash160: String = RIPEMD160.doubleHash(bytes) + def toHash160Digest: Bytes = RIPEMD160.doubleHashToDigest(bytes) } implicit class PublicKeyImplicit(val publicKey: PublicKey) { @@ -102,23 +102,4 @@ package object blockchain { */ def fromBase64(base64: String): String = new String(Base64.decode(base64), "UTF-8") - - def ripemd160Of(str: String): String = ripemd160Of(str.getBytes) - - def ripemd160Of(bytes: Bytes): String = ripemd160ODigestOf(bytes).map("%02x".format(_)).mkString - - def ripemd160ODigestOf(bytes: Bytes): Bytes = { - val (raw, messageDigest) = (bytes, new RIPEMD160Digest()) - messageDigest.update(raw, 0, raw.length) - val out = Array.fill[Byte](messageDigest.getDigestSize)(0) - messageDigest.doFinal(out, 0) - out - } - - def hash160Of(bytes: Bytes): String = ripemd160Of(SHA256.hashToDigest(bytes)) - - def hash160BytesOf(bytes: Bytes): Bytes = ripemd160ODigestOf(SHA256.hashToDigest(bytes)) - - - } diff --git a/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala b/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala index 71a8a60..c87d1d9 100644 --- a/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala +++ b/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala @@ -25,17 +25,6 @@ class Base58Test extends FlatSpec with Matchers { "04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a254112" + "9368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d" - ripemd160Of("61956bf4e271df1cd88a9a7828a59c88eb7ea13c176c4d03355ac27129760673") shouldEqual - "352b0b6bd7284755d5c685fb7793c9f4d672c5ff" - ripemd160Of("abcd") shouldEqual "2e7e536fd487deaa943fda5522d917bdb9011b7a" - ripemd160Of("205575f4f33a39ff47f569613a694c6321d6cdd7") shouldEqual "bd4e962413308b4a6689aa0e7cff5e419391c3db" - ripemd160Of("bitcoin") shouldEqual "5891bf40b0b0e8e19f524bdc2e842d012264624b" - ripemd160Of("blockchain") shouldEqual "5c403af45cae136a79eea3c7e9f79c3dd049776b" - - Crypto.publicKeyToAddress("04B4D653FCBB4B96000C99343F23B08A44FA306031E0587F9E657AB" + - "4A2541129368D7D9BB05CD8AFBDF7705A6540D98028236965553F91BF1C5B4F70073F55B55D") shouldEqual - "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" - Base58.encodeHex("0088C2D2FA846282C870A76CADECBE45C4ACD72BB655DA1216") shouldEqual "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" diff --git a/src/test/scala/com/github/fluency03/blockchain/CryptoTest.scala b/src/test/scala/com/github/fluency03/blockchain/CryptoTest.scala index fc19e38..e16b37d 100644 --- a/src/test/scala/com/github/fluency03/blockchain/CryptoTest.scala +++ b/src/test/scala/com/github/fluency03/blockchain/CryptoTest.scala @@ -20,6 +20,10 @@ class CryptoTest extends FlatSpec with Matchers { recoverPrivateKey(privateKeyToHex(pair.getPrivate)) shouldEqual pair.getPrivate recoverPublicKey(pair.getPublic.toHex) shouldEqual pair.getPublic recoverPrivateKey(pair.getPrivate.toHex) shouldEqual pair.getPrivate + + Crypto.publicKeyToAddress("04B4D653FCBB4B96000C99343F23B08A44FA306031E0587F9E657AB" + + "4A2541129368D7D9BB05CD8AFBDF7705A6540D98028236965553F91BF1C5B4F70073F55B55D") shouldEqual + "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" } diff --git a/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala b/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala index 316358b..c23a71e 100644 --- a/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala +++ b/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala @@ -6,6 +6,21 @@ class RIPEMD160Test extends FlatSpec with Matchers { "RIPEMD160" should "encode String to RIPEMD160 and decode it back to original." in { + RIPEMD160.hash("173BDED8F2A2069C193E63EA30DC8FD20E815EC3642B9C24AD7002C03D1BFB9B".hex2Bytes) shouldEqual + "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".toLowerCase + + RIPEMD160.doubleHashToDigest(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" + + "29368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d").hex2Bytes) shouldEqual + "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".hex2Bytes + + RIPEMD160.hash("61956bf4e271df1cd88a9a7828a59c88eb7ea13c176c4d03355ac27129760673") shouldEqual + "352b0b6bd7284755d5c685fb7793c9f4d672c5ff" + RIPEMD160.hash("abcd") shouldEqual "2e7e536fd487deaa943fda5522d917bdb9011b7a" + RIPEMD160.hash("205575f4f33a39ff47f569613a694c6321d6cdd7") shouldEqual "bd4e962413308b4a6689aa0e7cff5e419391c3db" + RIPEMD160.hash("bitcoin") shouldEqual "5891bf40b0b0e8e19f524bdc2e842d012264624b" + RIPEMD160.hash("blockchain") shouldEqual "5c403af45cae136a79eea3c7e9f79c3dd049776b" + + } diff --git a/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala b/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala index 97347ac..7ef4f58 100644 --- a/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala +++ b/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala @@ -25,13 +25,6 @@ class SHA256Test extends FlatSpec with Matchers { SHA256.hash("1F87490FC565C795595563D56412A0100CD1F29FFB60A3779789FE0C018C6164".hex2Bytes) shouldEqual "55DA1216A5EF5BAE605B543A5A9CE2AC8A8FA1781AA037F35DE3F2222BAD8127".toLowerCase - ripemd160Of("173BDED8F2A2069C193E63EA30DC8FD20E815EC3642B9C24AD7002C03D1BFB9B".hex2Bytes) shouldEqual - "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".toLowerCase - - hash160BytesOf(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" + - "29368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d").hex2Bytes) shouldEqual - "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".hex2Bytes - SHA256.hashToDigest("00".hex2Bytes ++ "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".hex2Bytes) shouldEqual "1F87490FC565C795595563D56412A0100CD1F29FFB60A3779789FE0C018C6164".hex2Bytes }