Composite Signature OID fix and crypto comments clean up (#1393)

This commit is contained in:
Konstantinos Chalkias 2017-09-04 10:44:22 +01:00 committed by GitHub
parent 0bbee4a92b
commit 7ec5bd789e
11 changed files with 29 additions and 38 deletions

View File

@ -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.

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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())

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -11,4 +11,3 @@ import net.corda.core.serialization.CordaSerializable
*/
@CordaSerializable
data class SignableData(val txId: SecureHash, val signatureMetadata: SignatureMetadata)

View File

@ -29,4 +29,5 @@ data class SignatureScheme(
val signatureName: String,
val algSpec: AlgorithmParameterSpec?,
val keySize: Int?,
val desc: String)
val desc: String
)

View File

@ -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 {