mirror of
https://github.com/corda/corda.git
synced 2025-02-20 17:33:15 +00:00
Extract methods and classes from CryptoUtilities. Keep one utils file.
This commit is contained in:
parent
a1122c0804
commit
66890d845a
@ -1,216 +0,0 @@
|
||||
@file:JvmName("CryptoUtilities")
|
||||
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine
|
||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
import net.i2p.crypto.eddsa.KeyPairGenerator
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec
|
||||
import java.math.BigInteger
|
||||
import java.security.InvalidKeyException
|
||||
import java.security.KeyPair
|
||||
import java.security.PrivateKey
|
||||
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]
|
||||
// should be renamed to match.
|
||||
/** A wrapper around a digital signature. */
|
||||
@CordaSerializable
|
||||
open class DigitalSignature(bits: ByteArray) : OpaqueBytes(bits) {
|
||||
/** A digital signature that identifies who the public key is owned by. */
|
||||
open class WithKey(val by: PublicKey, bits: ByteArray) : DigitalSignature(bits) {
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect).
|
||||
*/
|
||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||
fun verifyWithECDSA(content: ByteArray) = by.verifyWithECDSA(content, this)
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect).
|
||||
*/
|
||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||
fun verifyWithECDSA(content: OpaqueBytes) = by.verifyWithECDSA(content.bytes, this)
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature. In comparison to [verifyWithECDSA] doesn't throw an
|
||||
* exception, making it more suitable where a boolean is required, but normally you should use the function
|
||||
* which throws, as it avoids the risk of failing to test the result.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged).
|
||||
* @return whether the signature is correct for this key.
|
||||
*/
|
||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||
fun isValidForECDSA(content: ByteArray) = by.isValidForECDSA(content, this)
|
||||
}
|
||||
|
||||
// TODO: consider removing this as whoever needs to identify the signer should be able to derive it from the public key
|
||||
class LegallyIdentifiable(val signer: Party, bits: ByteArray) : WithKey(signer.owningKey, bits)
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
object NullPublicKey : PublicKey, Comparable<PublicKey> {
|
||||
override fun getAlgorithm() = "NULL"
|
||||
override fun getEncoded() = byteArrayOf(0)
|
||||
override fun getFormat() = "NULL"
|
||||
override fun compareTo(other: PublicKey): Int = if (other == NullPublicKey) 0 else -1
|
||||
override fun toString() = "NULL_KEY"
|
||||
}
|
||||
|
||||
|
||||
// TODO: Clean up this duplication between Null and Dummy public key
|
||||
@CordaSerializable
|
||||
class DummyPublicKey(val s: String) : PublicKey, Comparable<PublicKey> {
|
||||
override fun getAlgorithm() = "DUMMY"
|
||||
override fun getEncoded() = s.toByteArray()
|
||||
override fun getFormat() = "ASN.1"
|
||||
override fun compareTo(other: PublicKey): Int = BigInteger(encoded).compareTo(BigInteger(other.encoded))
|
||||
override fun equals(other: Any?) = other is DummyPublicKey && other.s == s
|
||||
override fun hashCode(): Int = s.hashCode()
|
||||
override fun toString() = "PUBKEY[$s]"
|
||||
}
|
||||
|
||||
/** A signature with a key and value of zero. Useful when you want a signature object that you know won't ever be used. */
|
||||
@CordaSerializable
|
||||
object NullSignature : DigitalSignature.WithKey(NullPublicKey, ByteArray(32))
|
||||
|
||||
/** Utility to simplify the act of signing a byte array */
|
||||
fun PrivateKey.signWithECDSA(bytes: ByteArray): DigitalSignature {
|
||||
val signer = EdDSAEngine()
|
||||
signer.initSign(this)
|
||||
signer.update(bytes)
|
||||
val sig = signer.sign()
|
||||
return DigitalSignature(sig)
|
||||
}
|
||||
|
||||
fun PrivateKey.signWithECDSA(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey {
|
||||
return DigitalSignature.WithKey(publicKey, signWithECDSA(bytesToSign).bytes)
|
||||
}
|
||||
|
||||
val ed25519Curve: EdDSANamedCurveSpec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
|
||||
|
||||
// TODO We use for both CompositeKeys and EdDSAPublicKey custom Kryo serializers and deserializers. We need to specify encoding.
|
||||
// TODO: follow the crypto-conditions ASN.1 spec, some changes are needed to be compatible with the condition
|
||||
// structure, e.g. mapping a PublicKey to a condition with the specific feature (ED25519).
|
||||
fun parsePublicKeyBase58(base58String: String): PublicKey = Base58.decode(base58String).deserialize<PublicKey>()
|
||||
fun PublicKey.toBase58String(): String = Base58.encode(this.serialize().bytes)
|
||||
|
||||
fun KeyPair.signWithECDSA(bytesToSign: ByteArray) = private.signWithECDSA(bytesToSign, public)
|
||||
fun KeyPair.signWithECDSA(bytesToSign: OpaqueBytes) = private.signWithECDSA(bytesToSign.bytes, public)
|
||||
fun KeyPair.signWithECDSA(bytesToSign: OpaqueBytes, party: Party) = signWithECDSA(bytesToSign.bytes, party)
|
||||
// TODO This case will need more careful thinking, as party owningKey can be a CompositeKey. One way of doing that is
|
||||
// implementation of CompositeSignature.
|
||||
@Throws(InvalidKeyException::class)
|
||||
fun KeyPair.signWithECDSA(bytesToSign: ByteArray, party: Party): DigitalSignature.LegallyIdentifiable {
|
||||
val sig = signWithECDSA(bytesToSign)
|
||||
val sigKey = when (party.owningKey) { // Quick workaround when we have CompositeKey as Party owningKey.
|
||||
is CompositeKey -> throw InvalidKeyException("Signing for parties with CompositeKey not supported.")
|
||||
else -> party.owningKey
|
||||
}
|
||||
sigKey.verifyWithECDSA(bytesToSign, sig)
|
||||
return DigitalSignature.LegallyIdentifiable(party, sig.bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect).
|
||||
*/
|
||||
// TODO: SignatureException should be used only for a damaged signature, as per `java.security.Signature.verify()`,
|
||||
// we should use another exception (perhaps IllegalArgumentException) for indicating the signature is valid but does
|
||||
// not match.
|
||||
@Throws(IllegalStateException::class, SignatureException::class)
|
||||
fun PublicKey.verifyWithECDSA(content: ByteArray, signature: DigitalSignature) {
|
||||
if (!isValidForECDSA(content, signature))
|
||||
throw SignatureException("Signature did not match")
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature. In comparison to [verifyWithECDSA] if the key and signature
|
||||
* do not match it returns false rather than throwing an exception. Normally you should use the function which throws,
|
||||
* as it avoids the risk of failing to test the result, but this is for uses such as [java.security.Signature.verify]
|
||||
* implementations.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged).
|
||||
* @return whether the signature is correct for this key.
|
||||
*/
|
||||
@Throws(IllegalStateException::class, SignatureException::class)
|
||||
fun PublicKey.isValidForECDSA(content: ByteArray, signature: DigitalSignature) : Boolean {
|
||||
val pubKey = when (this) {
|
||||
is CompositeKey -> throw IllegalStateException("Verification of CompositeKey signatures currently not supported.") // TODO CompositeSignature verification.
|
||||
else -> this
|
||||
}
|
||||
val verifier = EdDSAEngine()
|
||||
verifier.initVerify(pubKey)
|
||||
verifier.update(content)
|
||||
return verifier.verify(signature.bytes)
|
||||
}
|
||||
|
||||
/** Render a public key to a string, using a short form if it's an elliptic curve public key */
|
||||
fun PublicKey.toStringShort(): String {
|
||||
return (this as? EdDSAPublicKey)?.let { key ->
|
||||
"DL" + Base58.encode(key.abyte) // DL -> Distributed Ledger
|
||||
} ?: toString()
|
||||
}
|
||||
|
||||
val PublicKey.keys: Set<PublicKey> get() {
|
||||
return if (this is CompositeKey) this.leavesKeys
|
||||
else 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
|
||||
}
|
||||
|
||||
/** 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 */
|
||||
fun Iterable<DigitalSignature.WithKey>.byKeys() = map { it.by }.toSet()
|
||||
|
||||
// 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 */
|
||||
fun generateKeyPair(): KeyPair = KeyPairGenerator().generateKeyPair()
|
||||
|
||||
/**
|
||||
* Returns a key pair derived from the given private key entropy. This is useful for unit tests and other cases where
|
||||
* you want hard-coded private keys.
|
||||
*/
|
||||
fun entropyToKeyPair(entropy: BigInteger): KeyPair {
|
||||
val params = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
|
||||
val bytes = entropy.toByteArray().copyOf(params.curve.field.getb() / 8)
|
||||
val priv = EdDSAPrivateKeySpec(bytes, params)
|
||||
val pub = EdDSAPublicKeySpec(priv.a, params)
|
||||
val key = KeyPair(EdDSAPublicKey(pub), EdDSAPrivateKey(priv))
|
||||
return key
|
||||
}
|
@ -1,7 +1,163 @@
|
||||
@file:JvmName("CryptoUtils")
|
||||
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine
|
||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
import net.i2p.crypto.eddsa.KeyPairGenerator
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec
|
||||
import java.math.BigInteger
|
||||
import java.security.*
|
||||
|
||||
@CordaSerializable
|
||||
object NullPublicKey : PublicKey, Comparable<PublicKey> {
|
||||
override fun getAlgorithm() = "NULL"
|
||||
override fun getEncoded() = byteArrayOf(0)
|
||||
override fun getFormat() = "NULL"
|
||||
override fun compareTo(other: PublicKey): Int = if (other == NullPublicKey) 0 else -1
|
||||
override fun toString() = "NULL_KEY"
|
||||
}
|
||||
|
||||
// TODO: Clean up this duplication between Null and Dummy public key
|
||||
@CordaSerializable
|
||||
class DummyPublicKey(val s: String) : PublicKey, Comparable<PublicKey> {
|
||||
override fun getAlgorithm() = "DUMMY"
|
||||
override fun getEncoded() = s.toByteArray()
|
||||
override fun getFormat() = "ASN.1"
|
||||
override fun compareTo(other: PublicKey): Int = BigInteger(encoded).compareTo(BigInteger(other.encoded))
|
||||
override fun equals(other: Any?) = other is DummyPublicKey && other.s == s
|
||||
override fun hashCode(): Int = s.hashCode()
|
||||
override fun toString() = "PUBKEY[$s]"
|
||||
}
|
||||
|
||||
/** A signature with a key and value of zero. Useful when you want a signature object that you know won't ever be used. */
|
||||
@CordaSerializable
|
||||
object NullSignature : DigitalSignature.WithKey(NullPublicKey, ByteArray(32))
|
||||
|
||||
/** Utility to simplify the act of signing a byte array */
|
||||
fun PrivateKey.signWithECDSA(bytes: ByteArray): DigitalSignature {
|
||||
val signer = EdDSAEngine()
|
||||
signer.initSign(this)
|
||||
signer.update(bytes)
|
||||
val sig = signer.sign()
|
||||
return DigitalSignature(sig)
|
||||
}
|
||||
|
||||
fun PrivateKey.signWithECDSA(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey {
|
||||
return DigitalSignature.WithKey(publicKey, signWithECDSA(bytesToSign).bytes)
|
||||
}
|
||||
|
||||
val ed25519Curve: EdDSANamedCurveSpec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
|
||||
|
||||
fun KeyPair.signWithECDSA(bytesToSign: ByteArray) = private.signWithECDSA(bytesToSign, public)
|
||||
fun KeyPair.signWithECDSA(bytesToSign: OpaqueBytes) = private.signWithECDSA(bytesToSign.bytes, public)
|
||||
fun KeyPair.signWithECDSA(bytesToSign: OpaqueBytes, party: Party) = signWithECDSA(bytesToSign.bytes, party)
|
||||
// TODO This case will need more careful thinking, as party owningKey can be a CompositeKey. One way of doing that is
|
||||
// implementation of CompositeSignature.
|
||||
@Throws(InvalidKeyException::class)
|
||||
fun KeyPair.signWithECDSA(bytesToSign: ByteArray, party: Party): DigitalSignature.LegallyIdentifiable {
|
||||
val sig = signWithECDSA(bytesToSign)
|
||||
val sigKey = when (party.owningKey) { // Quick workaround when we have CompositeKey as Party owningKey.
|
||||
is CompositeKey -> throw InvalidKeyException("Signing for parties with CompositeKey not supported.")
|
||||
else -> party.owningKey
|
||||
}
|
||||
sigKey.verifyWithECDSA(bytesToSign, sig)
|
||||
return DigitalSignature.LegallyIdentifiable(party, sig.bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect).
|
||||
*/
|
||||
// TODO: SignatureException should be used only for a damaged signature, as per `java.security.Signature.verify()`,
|
||||
// we should use another exception (perhaps IllegalArgumentException) for indicating the signature is valid but does
|
||||
// not match.
|
||||
@Throws(IllegalStateException::class, SignatureException::class)
|
||||
fun PublicKey.verifyWithECDSA(content: ByteArray, signature: DigitalSignature) {
|
||||
if (!isValidForECDSA(content, signature))
|
||||
throw SignatureException("Signature did not match")
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature. In comparison to [verifyWithECDSA] if the key and signature
|
||||
* do not match it returns false rather than throwing an exception. Normally you should use the function which throws,
|
||||
* as it avoids the risk of failing to test the result, but this is for uses such as [java.security.Signature.verify]
|
||||
* implementations.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged).
|
||||
* @return whether the signature is correct for this key.
|
||||
*/
|
||||
@Throws(IllegalStateException::class, SignatureException::class)
|
||||
fun PublicKey.isValidForECDSA(content: ByteArray, signature: DigitalSignature) : Boolean {
|
||||
val pubKey = when (this) {
|
||||
is CompositeKey -> throw IllegalStateException("Verification of CompositeKey signatures currently not supported.") // TODO CompositeSignature verification.
|
||||
else -> this
|
||||
}
|
||||
val verifier = EdDSAEngine()
|
||||
verifier.initVerify(pubKey)
|
||||
verifier.update(content)
|
||||
return verifier.verify(signature.bytes)
|
||||
}
|
||||
|
||||
/** Render a public key to a string, using a short form if it's an elliptic curve public key */
|
||||
fun PublicKey.toStringShort(): String {
|
||||
return (this as? EdDSAPublicKey)?.let { key ->
|
||||
"DL" + key.abyte.toBase58() // DL -> Distributed Ledger
|
||||
} ?: toString()
|
||||
}
|
||||
|
||||
val PublicKey.keys: Set<PublicKey> get() {
|
||||
return if (this is CompositeKey) this.leavesKeys
|
||||
else 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
|
||||
}
|
||||
|
||||
/** 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 */
|
||||
fun Iterable<DigitalSignature.WithKey>.byKeys() = map { it.by }.toSet()
|
||||
|
||||
// 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 */
|
||||
fun generateKeyPair(): KeyPair = KeyPairGenerator().generateKeyPair()
|
||||
|
||||
/**
|
||||
* Returns a key pair derived from the given private key entropy. This is useful for unit tests and other cases where
|
||||
* you want hard-coded private keys.
|
||||
*/
|
||||
fun entropyToKeyPair(entropy: BigInteger): KeyPair {
|
||||
val params = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
|
||||
val bytes = entropy.toByteArray().copyOf(params.curve.field.getb() / 8)
|
||||
val priv = EdDSAPrivateKeySpec(bytes, params)
|
||||
val pub = EdDSAPublicKeySpec(priv.a, params)
|
||||
val key = KeyPair(EdDSAPublicKey(pub), EdDSAPrivateKey(priv))
|
||||
return key
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for signing.
|
||||
* @param clearData the data/message to be signed in [ByteArray] form (usually the Merkle root).
|
||||
@ -15,8 +171,8 @@ fun PrivateKey.sign(clearData: ByteArray): ByteArray = Crypto.doSign(this, clear
|
||||
|
||||
/**
|
||||
* Helper function for signing.
|
||||
* @param metaDataFull tha attached MetaData object.
|
||||
* @return a [DSWithMetaDataFull] object.
|
||||
* @param metaData tha attached MetaData object.
|
||||
* @return a [TransactionSignature] object.
|
||||
* @throws IllegalArgumentException if the signature scheme is not supported for this private key.
|
||||
* @throws InvalidKeyException if the private key is invalid.
|
||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||
@ -65,7 +221,7 @@ fun PublicKey.verify(transactionSignature: TransactionSignature): Boolean {
|
||||
|
||||
/**
|
||||
* Helper function for the signers to verify their own signature.
|
||||
* @param signature the signature on a message.
|
||||
* @param signatureData the signature on a message.
|
||||
* @param clearData the clear data/message that was signed (usually the Merkle root).
|
||||
* @throws InvalidKeyException if the key is invalid.
|
||||
* @throws SignatureException if this signatureData object is not initialized properly,
|
||||
@ -85,7 +241,7 @@ fun KeyPair.verify(signatureData: ByteArray, clearData: ByteArray): Boolean = Cr
|
||||
* which should never happen and suggests an unusual JVM or non-standard Java library.
|
||||
*/
|
||||
@Throws(NoSuchAlgorithmException::class)
|
||||
fun safeRandomBytes(numOfBytes: Int): ByteArray {
|
||||
fun secureRandomBytes(numOfBytes: Int): ByteArray {
|
||||
return newSecureRandom().generateSeed(numOfBytes)
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,51 @@
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
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]
|
||||
// should be renamed to match.
|
||||
/** A wrapper around a digital signature. */
|
||||
@CordaSerializable
|
||||
open class DigitalSignature(bits: ByteArray) : OpaqueBytes(bits) {
|
||||
/** A digital signature that identifies who the public key is owned by. */
|
||||
open class WithKey(val by: PublicKey, bits: ByteArray) : DigitalSignature(bits) {
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect).
|
||||
*/
|
||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||
fun verifyWithECDSA(content: ByteArray) = by.verifyWithECDSA(content, this)
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect).
|
||||
*/
|
||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||
fun verifyWithECDSA(content: OpaqueBytes) = by.verifyWithECDSA(content.bytes, this)
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature. In comparison to [verifyWithECDSA] doesn't throw an
|
||||
* exception, making it more suitable where a boolean is required, but normally you should use the function
|
||||
* which throws, as it avoids the risk of failing to test the result.
|
||||
*
|
||||
* @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the
|
||||
* signature).
|
||||
* @throws SignatureException if the signature is invalid (i.e. damaged).
|
||||
* @return whether the signature is correct for this key.
|
||||
*/
|
||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||
fun isValidForECDSA(content: ByteArray) = by.isValidForECDSA(content, this)
|
||||
}
|
||||
|
||||
// TODO: consider removing this as whoever needs to identify the signer should be able to derive it from the public key
|
||||
class LegallyIdentifiable(val signer: Party, bits: ByteArray) : WithKey(signer.owningKey, bits)
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
@file:JvmName("EncodingUtils")
|
||||
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import java.nio.charset.Charset
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
import javax.xml.bind.DatatypeConverter
|
||||
|
||||
|
||||
// This file includes useful encoding methods and extension functions for the most common encoding/decoding operations.
|
||||
|
||||
// [ByteArray] encoders
|
||||
@ -56,5 +60,8 @@ fun String.hexToBase58(): String = hexToByteArray().toBase58()
|
||||
/** Encoding changer. Hex-[String] to Base64-[String], i.e. "48656C6C6F20576F726C64" -> "SGVsbG8gV29ybGQ=" */
|
||||
fun String.hexToBase64(): String = hexToByteArray().toBase64()
|
||||
|
||||
// Helper vars.
|
||||
private val HEX_ALPHABET = "0123456789ABCDEF".toCharArray()
|
||||
// TODO We use for both CompositeKeys and EdDSAPublicKey custom Kryo serializers and deserializers. We need to specify encoding.
|
||||
// TODO: follow the crypto-conditions ASN.1 spec, some changes are needed to be compatible with the condition
|
||||
// structure, e.g. mapping a PublicKey to a condition with the specific feature (ED25519).
|
||||
fun parsePublicKeyBase58(base58String: String): PublicKey = base58String.base58ToByteArray().deserialize<PublicKey>()
|
||||
fun PublicKey.toBase58String(): String = this.serialize().bytes.toBase58()
|
||||
|
Loading…
x
Reference in New Issue
Block a user