CORDA-4100: Updates to DigestAlgorithm interface (#6849)

Updated DigestAlgorithm interface to separate componentHash and computeNonce hashing functions.
This commit is contained in:
Edoardo Ierina 2021-02-01 10:52:47 +00:00 committed by GitHub
parent ade302be73
commit d7c9f20019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 9 deletions

View File

@ -1850,13 +1850,15 @@ public final class net.corda.core.crypto.CryptoUtils extends java.lang.Object
public static final boolean verify(java.security.PublicKey, byte[], byte[])
##
public interface net.corda.core.crypto.DigestAlgorithm
@NotNull
public abstract byte[] componentDigest(byte[])
@NotNull
public abstract byte[] digest(byte[])
@NotNull
public abstract String getAlgorithm()
public abstract int getDigestLength()
@NotNull
public abstract byte[] preImageResistantDigest(byte[])
public abstract byte[] nonceDigest(byte[])
##
@CordaSerializable
public class net.corda.core.crypto.DigitalSignature extends net.corda.core.utilities.OpaqueBytes

View File

@ -25,8 +25,16 @@ interface DigestAlgorithm {
fun digest(bytes: ByteArray): ByteArray
/**
* Computes the digest of the [ByteArray] which is resistant to pre-image attacks.
* Computes the digest of the [ByteArray] which is resistant to pre-image attacks. Only used to calculate the hash of the leaves of the
* ComponentGroup Merkle tree, starting from its serialized components.
* Default implementation provides double hashing, but can it be changed to single hashing or something else for better performance.
*/
fun preImageResistantDigest(bytes: ByteArray): ByteArray = digest(digest(bytes))
fun componentDigest(bytes: ByteArray): ByteArray = digest(digest(bytes))
/**
* Computes the digest of the [ByteArray] which is resistant to pre-image attacks. Only used to calculate the nonces for the leaves of
* the ComponentGroup Merkle tree.
* Default implementation provides double hashing, but can it be changed to single hashing or something else for better performance.
*/
fun nonceDigest(bytes: ByteArray): ByteArray = digest(digest(bytes))
}

View File

@ -91,7 +91,7 @@ data class DigestService(val hashAlgorithm: String) {
* otherwise it's defined by DigestAlgorithm.preImageResistantDigest(nonce || serializedComponent). */
fun componentHash(nonce: SecureHash, opaqueBytes: OpaqueBytes): SecureHash {
val data = nonce.bytes + opaqueBytes.bytes
return SecureHash.preImageResistantHashAs(hashAlgorithm, data)
return SecureHash.componentHashAs(hashAlgorithm, data)
}
/**
@ -113,7 +113,7 @@ data class DigestService(val hashAlgorithm: String) {
*/
fun computeNonce(privacySalt: PrivacySalt, groupIndex: Int, internalIndex: Int) : SecureHash {
val data = (privacySalt.bytes + ByteBuffer.allocate(NONCE_SIZE).putInt(groupIndex).putInt(internalIndex).array())
return SecureHash.preImageResistantHashAs(hashAlgorithm, data)
return SecureHash.nonceHashAs(hashAlgorithm, data)
}
}

View File

@ -216,13 +216,31 @@ sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
* @param bytes The [ByteArray] to hash.
*/
@JvmStatic
fun preImageResistantHashAs(algorithm: String, bytes: ByteArray): SecureHash {
fun componentHashAs(algorithm: String, bytes: ByteArray): SecureHash {
return if (algorithm == SHA2_256) {
sha256Twice(bytes)
} else {
val digest = digestFor(algorithm).get()
val firstHash = digest.preImageResistantDigest(bytes)
HASH(algorithm, digest.digest(firstHash))
val hash = digest.componentDigest(bytes)
HASH(algorithm, hash)
}
}
/**
* Computes the digest of the [ByteArray] which is resistant to pre-image attacks.
* It computes the hash of the hash for SHA2-256 and other algorithms loaded via JCA [MessageDigest].
* For custom algorithms the strategy can be modified via [DigestAlgorithm].
* @param algorithm The [MessageDigest] algorithm to use.
* @param bytes The [ByteArray] to hash.
*/
@JvmStatic
fun nonceHashAs(algorithm: String, bytes: ByteArray): SecureHash {
return if (algorithm == SHA2_256) {
sha256Twice(bytes)
} else {
val digest = digestFor(algorithm).get()
val hash = digest.nonceDigest(bytes)
HASH(algorithm, hash)
}
}

View File

@ -318,7 +318,11 @@ class WireTransaction(componentGroups: List<ComponentGroup>, val privacySalt: Pr
* nothing about the rest.
*/
internal val availableComponentNonces: Map<Int, List<SecureHash>> by lazy {
componentGroups.associate { it.groupIndex to it.components.mapIndexed { internalIndex, internalIt -> digestService.componentHash(internalIt, privacySalt, it.groupIndex, internalIndex) } }
if(digestService.hashAlgorithm == SecureHash.SHA2_256) {
componentGroups.associate { it.groupIndex to it.components.mapIndexed { internalIndex, internalIt -> digestService.componentHash(internalIt, privacySalt, it.groupIndex, internalIndex) } }
} else {
componentGroups.associate { it.groupIndex to it.components.mapIndexed { internalIndex, _ -> digestService.computeNonce(privacySalt, it.groupIndex, internalIndex) } }
}
}
/**