mirror of
https://github.com/corda/corda.git
synced 2024-12-23 14:52:29 +00:00
Composite Signature OID fix and crypto comments clean up (#1393)
This commit is contained in:
parent
0bbee4a92b
commit
7ec5bd789e
@ -12,7 +12,7 @@ import java.util.*
|
||||
|
||||
/**
|
||||
* A tree data structure that enables the representation of composite public keys.
|
||||
* Notice that with that implementation CompositeKey extends PublicKey. Leaves are represented by single public keys.
|
||||
* Notice that with that implementation CompositeKey extends [PublicKey]. Leaves are represented by single public keys.
|
||||
*
|
||||
* For complex scenarios, such as *"Both Alice and Bob need to sign to consume a state S"*, we can represent
|
||||
* the requirement by creating a tree with a root [CompositeKey], and Alice and Bob as children.
|
||||
@ -159,7 +159,7 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes single PublicKey and checks if CompositeKey requirements hold for that key.
|
||||
* Takes single [PublicKey] and checks if [CompositeKey] requirements hold for that key.
|
||||
*/
|
||||
fun isFulfilledBy(key: PublicKey) = isFulfilledBy(setOf(key))
|
||||
|
||||
@ -205,7 +205,7 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of all leaf keys of that CompositeKey.
|
||||
* Set of all leaf keys of that [CompositeKey].
|
||||
*/
|
||||
val leafKeys: Set<PublicKey>
|
||||
get() = children.flatMap { it.node.keys }.toSet() // Uses PublicKey.keys extension.
|
||||
|
@ -26,7 +26,7 @@ class CompositeKeyFactory : KeyFactorySpi() {
|
||||
|
||||
@Throws(InvalidKeySpecException::class)
|
||||
override fun <T : KeySpec> engineGetKeySpec(key: Key, keySpec: Class<T>): T {
|
||||
// Only support [X509EncodedKeySpec].
|
||||
// Only support X509EncodedKeySpec.
|
||||
throw InvalidKeySpecException("Not implemented yet $key $keySpec")
|
||||
}
|
||||
|
||||
|
@ -21,14 +21,16 @@ class CordaSecurityProvider : Provider(PROVIDER_NAME, 0.1, "$PROVIDER_NAME secur
|
||||
val compositeKeyOID = CordaObjectIdentifier.COMPOSITE_KEY.id
|
||||
put("Alg.Alias.KeyFactory.$compositeKeyOID", CompositeKey.KEY_ALGORITHM)
|
||||
put("Alg.Alias.KeyFactory.OID.$compositeKeyOID", CompositeKey.KEY_ALGORITHM)
|
||||
put("Alg.Alias.Signature.$compositeKeyOID", CompositeSignature.SIGNATURE_ALGORITHM)
|
||||
put("Alg.Alias.Signature.OID.$compositeKeyOID", CompositeSignature.SIGNATURE_ALGORITHM)
|
||||
|
||||
val compositeSignatureOID = CordaObjectIdentifier.COMPOSITE_SIGNATURE.id
|
||||
put("Alg.Alias.Signature.$compositeSignatureOID", CompositeSignature.SIGNATURE_ALGORITHM)
|
||||
put("Alg.Alias.Signature.OID.$compositeSignatureOID", CompositeSignature.SIGNATURE_ALGORITHM)
|
||||
}
|
||||
}
|
||||
|
||||
object CordaObjectIdentifier {
|
||||
// UUID-based OID
|
||||
// TODO: Register for an OID space and issue our own shorter OID
|
||||
// TODO: Register for an OID space and issue our own shorter OID.
|
||||
@JvmField val COMPOSITE_KEY = ASN1ObjectIdentifier("2.25.30086077608615255153862931087626791002")
|
||||
@JvmField val COMPOSITE_SIGNATURE = ASN1ObjectIdentifier("2.25.30086077608615255153862931087626791003")
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ object Crypto {
|
||||
private val providerMap: Map<String, Provider> = mapOf(
|
||||
BouncyCastleProvider.PROVIDER_NAME to getBouncyCastleProvider(),
|
||||
CordaSecurityProvider.PROVIDER_NAME to CordaSecurityProvider(),
|
||||
"BCPQC" to BouncyCastlePQCProvider()) // unfortunately, provider's name is not final in BouncyCastlePQCProvider, so we explicitly set it.
|
||||
"BCPQC" to BouncyCastlePQCProvider()) // Unfortunately, provider's name is not final in BouncyCastlePQCProvider, so we explicitly set it.
|
||||
|
||||
private fun getBouncyCastleProvider() = BouncyCastleProvider().apply {
|
||||
putAll(EdDSASecurityProvider())
|
||||
|
@ -17,13 +17,9 @@ import java.security.*
|
||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||
*/
|
||||
@Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class)
|
||||
fun PrivateKey.sign(bytesToSign: ByteArray): DigitalSignature {
|
||||
return DigitalSignature(Crypto.doSign(this, bytesToSign))
|
||||
}
|
||||
fun PrivateKey.sign(bytesToSign: ByteArray): DigitalSignature = DigitalSignature(Crypto.doSign(this, bytesToSign))
|
||||
|
||||
fun PrivateKey.sign(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey {
|
||||
return DigitalSignature.WithKey(publicKey, this.sign(bytesToSign).bytes)
|
||||
}
|
||||
fun PrivateKey.sign(bytesToSign: ByteArray, publicKey: PublicKey) = DigitalSignature.WithKey(publicKey, this.sign(bytesToSign).bytes)
|
||||
|
||||
/**
|
||||
* Helper function to sign with a key pair.
|
||||
@ -81,32 +77,27 @@ fun PublicKey.isValid(content: ByteArray, signature: DigitalSignature) : Boolean
|
||||
/** Render a public key to its hash (in Base58) of its serialised form using the DL prefix. */
|
||||
fun PublicKey.toStringShort(): String = "DL" + this.toSHA256Bytes().toBase58()
|
||||
|
||||
val PublicKey.keys: Set<PublicKey> get() {
|
||||
return if (this is CompositeKey) this.leafKeys
|
||||
else setOf(this)
|
||||
}
|
||||
val PublicKey.keys: Set<PublicKey> get() = (this as? CompositeKey)?.leafKeys ?: setOf(this)
|
||||
|
||||
fun PublicKey.isFulfilledBy(otherKey: PublicKey): Boolean = isFulfilledBy(setOf(otherKey))
|
||||
fun PublicKey.isFulfilledBy(otherKeys: Iterable<PublicKey>): Boolean {
|
||||
return if (this is CompositeKey) this.isFulfilledBy(otherKeys)
|
||||
else this in otherKeys
|
||||
}
|
||||
fun PublicKey.isFulfilledBy(otherKeys: Iterable<PublicKey>): Boolean = (this as? CompositeKey)?.isFulfilledBy(otherKeys) ?: (this in otherKeys)
|
||||
|
||||
/** Checks whether any of the given [keys] matches a leaf on the CompositeKey tree or a single PublicKey */
|
||||
/** Checks whether any of the given [keys] matches a leaf on the [CompositeKey] tree or a single [PublicKey]. */
|
||||
fun PublicKey.containsAny(otherKeys: Iterable<PublicKey>): Boolean {
|
||||
return if (this is CompositeKey) keys.intersect(otherKeys).isNotEmpty()
|
||||
else this in otherKeys
|
||||
}
|
||||
|
||||
/** Returns the set of all [PublicKey]s of the signatures */
|
||||
/** Returns the set of all [PublicKey]s of the signatures. */
|
||||
fun Iterable<TransactionSignature>.byKeys() = map { it.by }.toSet()
|
||||
|
||||
// Allow Kotlin destructuring: val (private, public) = keyPair
|
||||
// Allow Kotlin destructuring:
|
||||
// val (private, public) = keyPair
|
||||
operator fun KeyPair.component1(): PrivateKey = this.private
|
||||
|
||||
operator fun KeyPair.component2(): PublicKey = this.public
|
||||
|
||||
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */
|
||||
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future. */
|
||||
fun generateKeyPair(): KeyPair = Crypto.generateKeyPair()
|
||||
|
||||
/**
|
||||
@ -147,13 +138,11 @@ fun KeyPair.verify(signatureData: ByteArray, clearData: ByteArray): Boolean = Cr
|
||||
* @param numOfBytes how many random bytes to output.
|
||||
* @return a random [ByteArray].
|
||||
* @throws NoSuchAlgorithmException thrown if "NativePRNGNonBlocking" is not supported on the JVM
|
||||
* or if no strong SecureRandom implementations are available or if Security.getProperty("securerandom.strongAlgorithms") is null or empty,
|
||||
* or if no strong [SecureRandom] implementations are available or if Security.getProperty("securerandom.strongAlgorithms") is null or empty,
|
||||
* which should never happen and suggests an unusual JVM or non-standard Java library.
|
||||
*/
|
||||
@Throws(NoSuchAlgorithmException::class)
|
||||
fun secureRandomBytes(numOfBytes: Int): ByteArray {
|
||||
return newSecureRandom().generateSeed(numOfBytes)
|
||||
}
|
||||
fun secureRandomBytes(numOfBytes: Int): ByteArray = newSecureRandom().generateSeed(numOfBytes)
|
||||
|
||||
/**
|
||||
* Get an instance of [SecureRandom] to avoid blocking, due to waiting for additional entropy, when possible.
|
||||
|
@ -6,8 +6,8 @@ import java.security.InvalidKeyException
|
||||
import java.security.PublicKey
|
||||
import java.security.SignatureException
|
||||
|
||||
// TODO: Is there a use-case for bare [DigitalSignature], or is everything a [DigitalSignature.WithKey]? If there's no
|
||||
// actual use-case, we should merge the with key version into the parent class. In that case [CompositeSignatureWithKeys]
|
||||
// TODO: Is there a use-case for bare DigitalSignature, or is everything a DigitalSignature.WithKey? If there's no
|
||||
// actual use-case, we should merge the with key version into the parent class. In that case CompositeSignatureWithKeys
|
||||
// should be renamed to match.
|
||||
/** A wrapper around a digital signature. */
|
||||
@CordaSerializable
|
||||
|
@ -3,7 +3,7 @@ package net.corda.core.crypto
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Creation and verification of a Merkle Tree for a Wire Transaction.
|
||||
* Creation and verification of a Merkle tree for a [WireTransaction].
|
||||
*
|
||||
* See: https://en.wikipedia.org/wiki/Merkle_tree
|
||||
*
|
||||
@ -49,7 +49,7 @@ sealed class MerkleTree {
|
||||
*/
|
||||
private tailrec fun buildMerkleTree(lastNodesList: List<MerkleTree>): MerkleTree {
|
||||
if (lastNodesList.size == 1) {
|
||||
return lastNodesList[0] //Root reached.
|
||||
return lastNodesList[0] // Root reached.
|
||||
} else {
|
||||
val newLevelHashes: MutableList<MerkleTree> = ArrayList()
|
||||
val n = lastNodesList.size
|
||||
|
@ -12,7 +12,7 @@ import java.security.MessageDigest
|
||||
*/
|
||||
@CordaSerializable
|
||||
sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(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) {
|
||||
init {
|
||||
require(bytes.size == 32)
|
||||
|
@ -11,4 +11,3 @@ import net.corda.core.serialization.CordaSerializable
|
||||
*/
|
||||
@CordaSerializable
|
||||
data class SignableData(val txId: SecureHash, val signatureMetadata: SignatureMetadata)
|
||||
|
||||
|
@ -29,4 +29,5 @@ data class SignatureScheme(
|
||||
val signatureName: String,
|
||||
val algSpec: AlgorithmParameterSpec?,
|
||||
val keySize: Int?,
|
||||
val desc: String)
|
||||
val desc: String
|
||||
)
|
||||
|
@ -230,7 +230,7 @@ class FilteredTransaction private constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs verification of Partial Merkle Branch against [id].
|
||||
* Runs verification of partial Merkle branch against [id].
|
||||
*/
|
||||
@Throws(MerkleTreeException::class)
|
||||
fun verify(): Boolean {
|
||||
|
Loading…
Reference in New Issue
Block a user