mirror of
https://github.com/corda/corda.git
synced 2025-01-30 08:04:16 +00:00
Merged andrius-crypto-refactor into master
This commit is contained in:
commit
ac57c5cf86
@ -1,9 +1,6 @@
|
||||
package com.r3corda.core.crypto
|
||||
|
||||
import com.google.common.io.BaseEncoding
|
||||
import com.r3corda.core.serialization.OpaqueBytes
|
||||
import com.r3corda.core.serialization.SerializedBytes
|
||||
import com.r3corda.core.serialization.deserialize
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine
|
||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
@ -22,45 +19,6 @@ fun newSecureRandom(): SecureRandom {
|
||||
}
|
||||
}
|
||||
|
||||
// "sealed" here means there can't be any subclasses other than the ones defined here.
|
||||
sealed class SecureHash(bits: ByteArray) : OpaqueBytes(bits) {
|
||||
class SHA256(bits: ByteArray) : SecureHash(bits) {
|
||||
init {
|
||||
require(bits.size == 32)
|
||||
}
|
||||
|
||||
override val signatureAlgorithmName: String get() = "SHA256withECDSA"
|
||||
}
|
||||
|
||||
override fun toString() = BaseEncoding.base16().encode(bits)
|
||||
|
||||
fun prefixChars(prefixLen: Int = 6) = toString().substring(0, prefixLen)
|
||||
|
||||
// Like static methods in Java, except the 'companion' is a singleton that can have state.
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun parse(str: String) = BaseEncoding.base16().decode(str.toUpperCase()).let {
|
||||
when (it.size) {
|
||||
32 -> SHA256(it)
|
||||
else -> throw IllegalArgumentException("Provided string is ${it.size} bytes not 32 bytes in hex: $str")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic fun sha256(bits: ByteArray) = SHA256(MessageDigest.getInstance("SHA-256").digest(bits))
|
||||
@JvmStatic fun sha256Twice(bits: ByteArray) = sha256(sha256(bits).bits)
|
||||
@JvmStatic fun sha256(str: String) = sha256(str.toByteArray())
|
||||
|
||||
@JvmStatic fun randomSHA256() = sha256(newSecureRandom().generateSeed(32))
|
||||
}
|
||||
|
||||
abstract val signatureAlgorithmName: String
|
||||
|
||||
// In future, maybe SHA3, truncated hashes etc.
|
||||
}
|
||||
|
||||
fun ByteArray.sha256(): SecureHash.SHA256 = SecureHash.sha256(this)
|
||||
fun OpaqueBytes.sha256(): SecureHash.SHA256 = SecureHash.sha256(this.bits)
|
||||
|
||||
/**
|
||||
* A wrapper around a digital signature. The covering field is a generic tag usable by whatever is interpreting the
|
||||
* signature. It isn't used currently, but experience from Bitcoin suggests such a feature is useful, especially when
|
||||
@ -76,40 +34,6 @@ open class DigitalSignature(bits: ByteArray) : OpaqueBytes(bits) {
|
||||
class LegallyIdentifiable(val signer: Party, bits: ByteArray) : WithKey(signer.owningKey, bits)
|
||||
}
|
||||
|
||||
/**
|
||||
* A serialized piece of data and its signature. Enforces signature validity in order to deserialize the data
|
||||
* contained within.
|
||||
*
|
||||
* @param raw the raw serialized data.
|
||||
* @param sig the (unverified) signature for the data.
|
||||
*/
|
||||
open class SignedData<T : Any>(val raw: SerializedBytes<T>, val sig: DigitalSignature.WithKey) {
|
||||
/**
|
||||
* Return the deserialized data if the signature can be verified.
|
||||
*
|
||||
* @throws IllegalArgumentException if the data is invalid (only used if verifyData() is overloaded).
|
||||
* @throws SignatureException if the signature is invalid.
|
||||
*/
|
||||
@Throws(SignatureException::class)
|
||||
fun verified(): T {
|
||||
sig.by.verifyWithECDSA(raw.bits, sig)
|
||||
val data = raw.deserialize()
|
||||
verifyData(data)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the wrapped data after the signature has been verified and the data deserialised. Provided as an extension
|
||||
* point for subclasses.
|
||||
*
|
||||
* @throws IllegalArgumentException if the data is invalid.
|
||||
*/
|
||||
@Throws(IllegalArgumentException::class)
|
||||
open protected fun verifyData(data: T) {
|
||||
// By default we accept anything
|
||||
}
|
||||
}
|
||||
|
||||
object NullPublicKey : PublicKey, Comparable<PublicKey> {
|
||||
override fun getAlgorithm() = "NULL"
|
||||
override fun getEncoded() = byteArrayOf(0)
|
||||
@ -179,6 +103,7 @@ fun Iterable<PublicKey>.toStringsShort(): String = map { it.toStringShort() }.to
|
||||
|
||||
// Allow Kotlin destructuring: val (private, public) = keyPair
|
||||
operator fun KeyPair.component1() = this.private
|
||||
|
||||
operator fun KeyPair.component2() = this.public
|
||||
|
||||
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */
|
||||
|
44
core/src/main/kotlin/com/r3corda/core/crypto/SecureHash.kt
Normal file
44
core/src/main/kotlin/com/r3corda/core/crypto/SecureHash.kt
Normal file
@ -0,0 +1,44 @@
|
||||
package com.r3corda.core.crypto
|
||||
|
||||
import com.google.common.io.BaseEncoding
|
||||
import com.r3corda.core.serialization.OpaqueBytes
|
||||
import java.security.MessageDigest
|
||||
|
||||
/**
|
||||
* Container for a cryptographically secure hash value.
|
||||
* Provides utilities for generating a cryptographic hash using different algorithms (currently only SHA-256 supported).
|
||||
*/
|
||||
sealed class SecureHash(bits: ByteArray) : OpaqueBytes(bits) {
|
||||
/** SHA-256 is part of the SHA-2 hash function family. Generated hash is fixed size, 256-bits (32-bytes) */
|
||||
class SHA256(bits: ByteArray) : SecureHash(bits) {
|
||||
init {
|
||||
require(bits.size == 32)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = BaseEncoding.base16().encode(bits)
|
||||
|
||||
fun prefixChars(prefixLen: Int = 6) = toString().substring(0, prefixLen)
|
||||
|
||||
// Like static methods in Java, except the 'companion' is a singleton that can have state.
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun parse(str: String) = BaseEncoding.base16().decode(str.toUpperCase()).let {
|
||||
when (it.size) {
|
||||
32 -> SHA256(it)
|
||||
else -> throw IllegalArgumentException("Provided string is ${it.size} bytes not 32 bytes in hex: $str")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic fun sha256(bits: ByteArray) = SHA256(MessageDigest.getInstance("SHA-256").digest(bits))
|
||||
@JvmStatic fun sha256Twice(bits: ByteArray) = sha256(sha256(bits).bits)
|
||||
@JvmStatic fun sha256(str: String) = sha256(str.toByteArray())
|
||||
|
||||
@JvmStatic fun randomSHA256() = sha256(newSecureRandom().generateSeed(32))
|
||||
}
|
||||
|
||||
// In future, maybe SHA3, truncated hashes etc.
|
||||
}
|
||||
|
||||
fun ByteArray.sha256(): SecureHash.SHA256 = SecureHash.sha256(this)
|
||||
fun OpaqueBytes.sha256(): SecureHash.SHA256 = SecureHash.sha256(this.bits)
|
39
core/src/main/kotlin/com/r3corda/core/crypto/SignedData.kt
Normal file
39
core/src/main/kotlin/com/r3corda/core/crypto/SignedData.kt
Normal file
@ -0,0 +1,39 @@
|
||||
package com.r3corda.core.crypto
|
||||
|
||||
import com.r3corda.core.serialization.SerializedBytes
|
||||
import com.r3corda.core.serialization.deserialize
|
||||
import java.security.SignatureException
|
||||
|
||||
/**
|
||||
* A serialized piece of data and its signature. Enforces signature validity in order to deserialize the data
|
||||
* contained within.
|
||||
*
|
||||
* @param raw the raw serialized data.
|
||||
* @param sig the (unverified) signature for the data.
|
||||
*/
|
||||
open class SignedData<T : Any>(val raw: SerializedBytes<T>, val sig: DigitalSignature.WithKey) {
|
||||
/**
|
||||
* Return the deserialized data if the signature can be verified.
|
||||
*
|
||||
* @throws IllegalArgumentException if the data is invalid (only used if verifyData() is overloaded).
|
||||
* @throws SignatureException if the signature is invalid.
|
||||
*/
|
||||
@Throws(SignatureException::class)
|
||||
fun verified(): T {
|
||||
sig.by.verifyWithECDSA(raw.bits, sig)
|
||||
val data = raw.deserialize()
|
||||
verifyData(data)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the wrapped data after the signature has been verified and the data deserialised. Provided as an extension
|
||||
* point for subclasses.
|
||||
*
|
||||
* @throws IllegalArgumentException if the data is invalid.
|
||||
*/
|
||||
@Throws(IllegalArgumentException::class)
|
||||
open protected fun verifyData(data: T) {
|
||||
// By default we accept anything
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user