mirror of
https://github.com/corda/corda.git
synced 2024-12-19 21:17:58 +00:00
CORDA-4076: Fix SecureHash compatibility with previous versions (#6801)
This commit is contained in:
parent
d9f905cb81
commit
14e545826c
@ -22,9 +22,7 @@ import java.util.function.Supplier
|
|||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
@KeepForDJVM
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
sealed class SecureHash(val algorithm: String, bytes: ByteArray) : OpaqueBytes(bytes) {
|
sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
|
||||||
constructor(bytes: ByteArray) : this(SHA2_256, bytes)
|
|
||||||
|
|
||||||
/** SHA-256 is part of the SHA-2 hash function family. Generated hash is fixed size, 256-bits (32-bytes). */
|
/** SHA-256 is part of the SHA-2 hash function family. Generated hash is fixed size, 256-bits (32-bytes). */
|
||||||
class SHA256(bytes: ByteArray) : SecureHash(bytes) {
|
class SHA256(bytes: ByteArray) : SecureHash(bytes) {
|
||||||
init {
|
init {
|
||||||
@ -52,7 +50,7 @@ sealed class SecureHash(val algorithm: String, bytes: ByteArray) : OpaqueBytes(b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASH(algorithm: String, bytes: ByteArray) : SecureHash(algorithm, bytes) {
|
class HASH(val algorithm: String, bytes: ByteArray) : SecureHash(bytes) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
return when {
|
return when {
|
||||||
this === other -> true
|
this === other -> true
|
||||||
@ -63,6 +61,10 @@ sealed class SecureHash(val algorithm: String, bytes: ByteArray) : OpaqueBytes(b
|
|||||||
|
|
||||||
override fun hashCode() = ByteBuffer.wrap(bytes).int
|
override fun hashCode() = ByteBuffer.wrap(bytes).int
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "$algorithm$DELIMITER${toHexString()}"
|
||||||
|
}
|
||||||
|
|
||||||
override fun generate(data: ByteArray): SecureHash {
|
override fun generate(data: ByteArray): SecureHash {
|
||||||
return HASH(algorithm, digestAs(algorithm, data))
|
return HASH(algorithm, digestAs(algorithm, data))
|
||||||
}
|
}
|
||||||
@ -70,9 +72,7 @@ sealed class SecureHash(val algorithm: String, bytes: ByteArray) : OpaqueBytes(b
|
|||||||
|
|
||||||
fun toHexString(): String = bytes.toHexString()
|
fun toHexString(): String = bytes.toHexString()
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String = bytes.toHexString()
|
||||||
return "$algorithm$DELIMITER${toHexString()}"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first [prefixLen] hexadecimal digits of the [SecureHash] value.
|
* Returns the first [prefixLen] hexadecimal digits of the [SecureHash] value.
|
||||||
@ -354,6 +354,11 @@ fun ByteArray.hashAs(algorithm: String): SecureHash = SecureHash.hashAs(algorith
|
|||||||
*/
|
*/
|
||||||
fun OpaqueBytes.hashAs(algorithm: String): SecureHash = SecureHash.hashAs(algorithm, bytes)
|
fun OpaqueBytes.hashAs(algorithm: String): SecureHash = SecureHash.hashAs(algorithm, bytes)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash algorithm.
|
||||||
|
*/
|
||||||
|
val SecureHash.algorithm: String get() = if (this is SecureHash.HASH) algorithm else SecureHash.SHA2_256
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide the [FastThreadLocal] class behind a [Supplier] interface
|
* Hide the [FastThreadLocal] class behind a [Supplier] interface
|
||||||
* so that we can remove it for core-deterministic.
|
* so that we can remove it for core-deterministic.
|
||||||
|
@ -4,6 +4,7 @@ import net.corda.core.KeepForDJVM
|
|||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.DigestService
|
import net.corda.core.crypto.DigestService
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.crypto.algorithm
|
||||||
import net.corda.core.crypto.hashAs
|
import net.corda.core.crypto.hashAs
|
||||||
import net.corda.core.crypto.internal.DigestAlgorithmFactory
|
import net.corda.core.crypto.internal.DigestAlgorithmFactory
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
|
@ -33,20 +33,23 @@ class Blake2s256DigestServiceTest {
|
|||||||
@Test(timeout = 300_000)
|
@Test(timeout = 300_000)
|
||||||
fun testBlankHash() {
|
fun testBlankHash() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"C59F682376D137F3F255E671E207D1F2374EBE504E9314208A52D9F88D69E8C8",
|
"BLAKE_TEST:C59F682376D137F3F255E671E207D1F2374EBE504E9314208A52D9F88D69E8C8",
|
||||||
service.hash(byteArrayOf()).toHexString()
|
service.hash(byteArrayOf()).toString()
|
||||||
)
|
)
|
||||||
|
assertEquals("C59F682376D137F3F255E671E207D1F2374EBE504E9314208A52D9F88D69E8C8", service.hash(byteArrayOf()).toHexString())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 300_000)
|
@Test(timeout = 300_000)
|
||||||
fun testHashBytes() {
|
fun testHashBytes() {
|
||||||
val hash = service.hash(byteArrayOf(0x64, -0x13, 0x42, 0x3a))
|
val hash = service.hash(byteArrayOf(0x64, -0x13, 0x42, 0x3a))
|
||||||
|
assertEquals("BLAKE_TEST:9EEA14092257E759ADAA56539A7A88DA1F68F03ABE3D9552A21D4731F4E6ECA0", hash.toString())
|
||||||
assertEquals("9EEA14092257E759ADAA56539A7A88DA1F68F03ABE3D9552A21D4731F4E6ECA0", hash.toHexString())
|
assertEquals("9EEA14092257E759ADAA56539A7A88DA1F68F03ABE3D9552A21D4731F4E6ECA0", hash.toHexString())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 300_000)
|
@Test(timeout = 300_000)
|
||||||
fun testHashString() {
|
fun testHashString() {
|
||||||
val hash = service.hash("test")
|
val hash = service.hash("test")
|
||||||
|
assertEquals("BLAKE_TEST:AB76E8F7EEA1968C183D343B756EC812E47D4BC7A3F061F4DDE8948B3E05DAF2", hash.toString())
|
||||||
assertEquals("AB76E8F7EEA1968C183D343B756EC812E47D4BC7A3F061F4DDE8948B3E05DAF2", hash.toHexString())
|
assertEquals("AB76E8F7EEA1968C183D343B756EC812E47D4BC7A3F061F4DDE8948B3E05DAF2", hash.toHexString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.core.crypto.SecureHash
|
|||||||
import net.corda.core.crypto.SignableData
|
import net.corda.core.crypto.SignableData
|
||||||
import net.corda.core.crypto.SignatureMetadata
|
import net.corda.core.crypto.SignatureMetadata
|
||||||
import net.corda.core.crypto.TransactionSignature
|
import net.corda.core.crypto.TransactionSignature
|
||||||
|
import net.corda.core.crypto.algorithm
|
||||||
import net.corda.core.flows.NotaryError
|
import net.corda.core.flows.NotaryError
|
||||||
import net.corda.core.internal.digestService
|
import net.corda.core.internal.digestService
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package net.corda.serialization.internal
|
||||||
|
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.crypto.SecureHash.Companion.SHA2_256
|
||||||
|
import net.corda.core.crypto.SecureHash.Companion.SHA2_512
|
||||||
|
import net.corda.core.crypto.algorithm
|
||||||
|
import net.corda.core.serialization.SerializationDefaults
|
||||||
|
import net.corda.core.serialization.deserialize
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.testing.core.SerializationEnvironmentRule
|
||||||
|
import org.junit.Assert.assertArrayEquals
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class SecureHashSerializationTest {
|
||||||
|
@Rule
|
||||||
|
@JvmField
|
||||||
|
val testSerialization = SerializationEnvironmentRule()
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `serialize and deserialize SHA-256`() {
|
||||||
|
val before = SecureHash.randomSHA256()
|
||||||
|
val bytes = before.serialize(context = SerializationDefaults.P2P_CONTEXT.withoutReferences()).bytes
|
||||||
|
val after = bytes.deserialize<SecureHash>()
|
||||||
|
assertEquals(before, after)
|
||||||
|
assertArrayEquals(before.bytes, after.bytes)
|
||||||
|
assertEquals(before.algorithm, after.algorithm)
|
||||||
|
assertEquals(after.algorithm, SHA2_256)
|
||||||
|
assertTrue(after is SecureHash.SHA256)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `serialize and deserialize SHA-512`() {
|
||||||
|
val before = SecureHash.random(SHA2_512)
|
||||||
|
val bytes = before.serialize(context = SerializationDefaults.P2P_CONTEXT.withoutReferences()).bytes
|
||||||
|
val after = bytes.deserialize<SecureHash>()
|
||||||
|
assertEquals(before, after)
|
||||||
|
assertArrayEquals(before.bytes, after.bytes)
|
||||||
|
assertEquals(before.algorithm, after.algorithm)
|
||||||
|
assertEquals(after.algorithm, SHA2_512)
|
||||||
|
assertTrue(after is SecureHash.HASH)
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package net.corda.tools.shell;
|
package net.corda.tools.shell;
|
||||||
|
|
||||||
import net.corda.core.crypto.SecureHash;
|
import net.corda.core.crypto.SecureHash;
|
||||||
|
import net.corda.core.crypto.SecureHashKt;
|
||||||
import net.corda.core.internal.VisibleForTesting;
|
import net.corda.core.internal.VisibleForTesting;
|
||||||
import net.corda.core.messaging.CordaRPCOps;
|
import net.corda.core.messaging.CordaRPCOps;
|
||||||
import net.corda.core.messaging.StateMachineTransactionMapping;
|
import net.corda.core.messaging.StateMachineTransactionMapping;
|
||||||
@ -60,7 +61,7 @@ public class HashLookupShellCommand extends CordaRpcOpsShellCommand {
|
|||||||
Optional<SecureHash> match = mapping.stream()
|
Optional<SecureHash> match = mapping.stream()
|
||||||
.map(StateMachineTransactionMapping::getTransactionId)
|
.map(StateMachineTransactionMapping::getTransactionId)
|
||||||
.filter(
|
.filter(
|
||||||
txId -> txId.equals(txIdHashParsed) || SecureHash.hashAs(txIdHashParsed.getAlgorithm(), txId.getBytes()).equals(txIdHashParsed)
|
txId -> txId.equals(txIdHashParsed) || SecureHash.hashAs(SecureHashKt.getAlgorithm(txIdHashParsed), txId.getBytes()).equals(txIdHashParsed)
|
||||||
)
|
)
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user