Doorman db entity attributes which are hashes are of type SecureHash where possible. (#695)

Also made use of InputStream.readObject extension method.
This commit is contained in:
Shams Asari 2018-04-07 17:26:09 +01:00 committed by GitHub
parent 00a22c91df
commit 11af3992db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 43 additions and 50 deletions

8
.idea/compiler.xml generated
View File

@ -28,12 +28,14 @@
<module name="business-network-demo_integrationTest" target="1.8" />
<module name="business-network-demo_main" target="1.8" />
<module name="business-network-demo_test" target="1.8" />
<module name="canonicalizer_main" target="1.8" />
<module name="canonicalizer_test" target="1.8" />
<module name="capsule-crr-submission_main" target="1.8" />
<module name="capsule-crr-submission_test" target="1.8" />
<module name="capsule-hsm-cert-generator_main" target="1.8" />
<module name="capsule-hsm-cert-generator_test" target="1.8" />
<module name="capsule-hsm_main" target="1.8" />
<module name="capsule-hsm_test" target="1.8" />
<module name="canonicalizer_main" target="1.8" />
<module name="canonicalizer_test" target="1.8" />
<module name="client_main" target="1.8" />
<module name="client_test" target="1.8" />
<module name="confidential-identities_main" target="1.8" />
@ -184,4 +186,4 @@
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_STRING" value="-parameters" />
</component>
</project>
</project>

View File

@ -13,11 +13,11 @@ package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.common.persistence.entity.CertificateDataEntity
import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity
import com.r3.corda.networkmanage.common.utils.getCertRole
import com.r3.corda.networkmanage.common.utils.hashString
import net.corda.core.crypto.Crypto.toSupportedPublicKey
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.CertRole
import net.corda.core.internal.hash
import net.corda.nodeapi.internal.crypto.x509Certificates
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseTransaction
@ -70,7 +70,7 @@ class PersistentCertificateSigningRequestStorage(private val database: CordaPers
val requestEntity = CertificateSigningRequestEntity(
requestId = requestId,
legalName = legalNameOrRejectMessage as? CordaX500Name,
publicKeyHash = toSupportedPublicKey(request.subjectPublicKeyInfo).hashString(),
publicKeyHash = toSupportedPublicKey(request.subjectPublicKeyInfo).hash,
request = request,
remark = legalNameOrRejectMessage as? String,
modifiedBy = CertificateSigningRequestStorage.DOORMAN_SIGNATURE,
@ -136,7 +136,7 @@ class PersistentCertificateSigningRequestStorage(private val database: CordaPers
session.createQuery(
"select a.certificateData.certPath from ${CertificateSigningRequestEntity::class.java.name} a " +
"where a.publicKeyHash = :publicKeyHash and a.status = 'DONE' and a.certificateData.certificateStatus = 'VALID'", CertPath::class.java)
.setParameter("publicKeyHash", publicKey.hashString())
.setParameter("publicKeyHash", publicKey.hash.toString())
.uniqueResult()
}
}
@ -175,7 +175,7 @@ class PersistentCertificateSigningRequestStorage(private val database: CordaPers
// What if we approved something by mistake.
nonRejectedRequestExists(CertificateSigningRequestEntity::legalName.name, legalName) -> throw RequestValidationException(legalName.toString(), "Duplicate legal name")
//TODO Consider following scenario: There is a CSR that is signed but the certificate itself has expired or was revoked
nonRejectedRequestExists(CertificateSigningRequestEntity::publicKeyHash.name, toSupportedPublicKey(request.subjectPublicKeyInfo).hashString()) -> throw RequestValidationException(legalName.toString(), "Duplicate public key")
nonRejectedRequestExists(CertificateSigningRequestEntity::publicKeyHash.name, toSupportedPublicKey(request.subjectPublicKeyInfo).hash) -> throw RequestValidationException(legalName.toString(), "Duplicate public key")
else -> legalName
}
}

View File

@ -14,12 +14,12 @@ import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRe
import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity
import com.r3.corda.networkmanage.common.persistence.entity.ParametersUpdateEntity
import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus
import com.r3.corda.networkmanage.common.utils.hashString
import com.r3.corda.networkmanage.common.utils.logger
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.internal.CertRole
import net.corda.core.internal.CertRole.NODE_CA
import net.corda.core.internal.hash
import net.corda.nodeapi.internal.NodeInfoAndSigned
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.crypto.x509Certificates
@ -67,7 +67,7 @@ class PersistentNodeInfoStorage(private val database: CordaPersistence) : NodeIn
session.saveOrUpdate(NodeInfoEntity(
nodeInfoHash = nodeInfoHash.toString(),
publicKeyHash = nodeInfo.legalIdentities[0].owningKey.hashString(),
publicKeyHash = nodeInfo.legalIdentities[0].owningKey.hash,
certificateSigningRequest = request,
signedNodeInfo = signedNodeInfo,
isCurrent = true,
@ -101,7 +101,7 @@ class PersistentNodeInfoStorage(private val database: CordaPersistence) : NodeIn
return database.transaction {
val nodeInfoEntity = session.fromQuery<NodeInfoEntity>(
"n where n.publicKeyHash = :publicKeyHash and isCurrent = true")
.setParameter("publicKeyHash", publicKey.hashString())
.setParameter("publicKeyHash", publicKey.hash)
.singleResult
val parametersUpdateEntity = session.fromQuery<ParametersUpdateEntity>(
"u where u.networkParameters.hash = :acceptedParametersHash").
@ -116,7 +116,7 @@ class PersistentNodeInfoStorage(private val database: CordaPersistence) : NodeIn
private fun DatabaseTransaction.getSignedRequestByPublicHash(publicKeyHash: SecureHash): CertificateSigningRequestEntity? {
return uniqueEntityWhere { builder, path ->
val publicKeyEq = builder.equal(path.get<String>(CertificateSigningRequestEntity::publicKeyHash.name), publicKeyHash.toString())
val publicKeyEq = builder.equal(path.get<String>(CertificateSigningRequestEntity::publicKeyHash.name), publicKeyHash)
val statusEq = builder.equal(path.get<RequestStatus>(CertificateSigningRequestEntity::status.name), RequestStatus.DONE)
builder.and(publicKeyEq, statusEq)
}

View File

@ -1,6 +1,8 @@
package com.r3.corda.networkmanage.common.persistence.entity
import com.r3.corda.networkmanage.common.utils.buildCertPath
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.node.NetworkParameters
import net.corda.core.serialization.SerializationFactory
import net.corda.core.serialization.serialize
@ -13,7 +15,6 @@ import java.security.cert.CertPath
import java.security.cert.X509CRL
import java.security.cert.X509Certificate
import javax.persistence.AttributeConverter
import net.corda.core.identity.CordaX500Name
class PKCS10CertificationRequestConverter : AttributeConverter<PKCS10CertificationRequest, ByteArray> {
override fun convertToEntityAttribute(dbData: ByteArray?): PKCS10CertificationRequest? = dbData?.let(::PKCS10CertificationRequest)
@ -45,7 +46,11 @@ class NetworkMapConverter : CordaSerializationConverter<NetworkMap>(NetworkMap::
class SignedNodeInfoConverter : CordaSerializationConverter<SignedNodeInfo>(SignedNodeInfo::class.java)
sealed class CordaSerializationConverter<T : Any>(private val clazz: Class<T>) : AttributeConverter<T, ByteArray> {
class CordaX500NameAttributeConverter : ToStringConverter<CordaX500Name>(CordaX500Name.Companion::parse)
class SecureHashAttributeConverter : ToStringConverter<SecureHash>(SecureHash.Companion::parse)
abstract class CordaSerializationConverter<T : Any>(private val clazz: Class<T>) : AttributeConverter<T, ByteArray> {
override fun convertToEntityAttribute(dbData: ByteArray?): T? {
return dbData?.let {
val serializationFactory = SerializationFactory.defaultFactory
@ -56,14 +61,7 @@ sealed class CordaSerializationConverter<T : Any>(private val clazz: Class<T>) :
override fun convertToDatabaseColumn(attribute: T?): ByteArray? = attribute?.serialize()?.bytes
}
class CordaX500NameAttributeConverter : AttributeConverter<CordaX500Name, String> {
override fun convertToDatabaseColumn(attribute: CordaX500Name?): String? = attribute?.toString()
override fun convertToEntityAttribute(dbData: String?): CordaX500Name? = dbData?.let { CordaX500Name.parse(it) }
abstract class ToStringConverter<T : Any>(private val parser: (String) -> T) : AttributeConverter<T, String> {
override fun convertToDatabaseColumn(attribute: T?): String? = attribute?.toString()
override fun convertToEntityAttribute(dbData: String?): T? = dbData?.let { parser(it) }
}
// TODO Use SecureHash in entities
//class SecureHashAttributeConverter : AttributeConverter<SecureHash, String> {
// override fun convertToDatabaseColumn(attribute: SecureHash?): String? = attribute?.toString()
// override fun convertToEntityAttribute(dbData: String?): SecureHash? = dbData?.let { SecureHash.parse(it) }
//}

View File

@ -38,7 +38,8 @@ data class CertificateSigningRequestEntity(
val legalName: CordaX500Name?,
@Column(name = "public_key_hash", length = 64, nullable = false)
val publicKeyHash: String,
@Convert(converter = SecureHashAttributeConverter::class)
val publicKeyHash: SecureHash,
// Setting [columnDefinition] is a work around for a hibernate problem when using SQL database.
// TODO: Remove this when we find out the cause of the problem.
@ -75,7 +76,7 @@ data class CertificateSigningRequestEntity(
return CertificateSigningRequest(
requestId = requestId,
legalName = legalName,
publicKeyHash = SecureHash.parse(publicKeyHash),
publicKeyHash = publicKeyHash,
status = status,
request = request,
remark = remark,

View File

@ -24,6 +24,7 @@ import javax.persistence.*
class NetworkParametersEntity(
@Id
@Column(name = "hash", length = 64, nullable = false)
// AttributeConverters can't be used on @Id attributes, otherwise this would be SecureHash
val hash: String,
@Column(nullable = false)

View File

@ -10,6 +10,7 @@
package com.r3.corda.networkmanage.common.persistence.entity
import net.corda.core.crypto.SecureHash
import net.corda.nodeapi.internal.SignedNodeInfo
import java.io.Serializable
import java.time.Instant
@ -21,10 +22,12 @@ data class NodeInfoEntity(
// Hash of serialized [NodeInfo] without signatures.
@Id
@Column(name = "node_info_hash", length = 64)
// AttributeConverters can't be used on @Id attributes, otherwise this would be SecureHash
val nodeInfoHash: String,
@Column(name = "public_key_hash", length = 64)
val publicKeyHash: String,
@Convert(converter = SecureHashAttributeConverter::class)
val publicKeyHash: SecureHash,
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "cert_signing_request", nullable = false)

View File

@ -46,12 +46,6 @@ data class CertPathAndKey(val certPath: List<X509Certificate>, val key: PrivateK
fun toKeyPair(): KeyPair = KeyPair(certPath[0].publicKey, key)
}
// TODO: replace this with Crypto.hash when its available.
/**
* Returns SHA256 hash of this public key
*/
fun PublicKey.hashString() = encoded.sha256().toString()
inline fun <reified T : Any> parseConfig(file: Path): T {
val config = ConfigFactory.parseFile(file.toFile(), ConfigParseOptions.defaults().setAllowMissing(true)).resolve()
logger.info(config.root().render(ConfigRenderOptions.defaults()))

View File

@ -2,7 +2,7 @@ package com.r3.corda.networkmanage.doorman.webservice
import com.r3.corda.networkmanage.doorman.signer.CrrHandler
import com.r3.corda.networkmanage.doorman.webservice.CertificateRevocationRequestWebService.Companion.CRR_PATH
import net.corda.core.serialization.deserialize
import net.corda.core.internal.readObject
import net.corda.core.utilities.contextLogger
import net.corda.nodeapi.internal.network.CertificateRevocationRequest
import java.io.InputStream
@ -28,7 +28,7 @@ class CertificateRevocationRequestWebService(private val crrHandler: CrrHandler)
@Produces(MediaType.TEXT_PLAIN)
fun submitRequest(input: InputStream): Response {
return try {
val request = input.readBytes().deserialize<CertificateRevocationRequest>()
val request = input.readObject<CertificateRevocationRequest>()
val requestId = crrHandler.saveRevocationRequest(request)
ok(requestId)
} catch (e: Exception) {

View File

@ -22,9 +22,9 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SignedData
import net.corda.core.crypto.sha256
import net.corda.core.internal.CertRole
import net.corda.core.internal.readObject
import net.corda.core.node.NetworkParameters
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.debug
@ -84,7 +84,7 @@ class NetworkMapWebService(private val nodeInfoStorage: NodeInfoStorage,
@Path("publish")
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
fun registerNode(input: InputStream): Response {
val signedNodeInfo = input.readBytes().deserialize<SignedNodeInfo>()
val signedNodeInfo = input.readObject<SignedNodeInfo>()
var nodeInfo: NodeInfo? = null
return try {
// Store the NodeInfo
@ -111,7 +111,7 @@ class NetworkMapWebService(private val nodeInfoStorage: NodeInfoStorage,
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
fun ackNetworkParameters(input: InputStream): Response {
return try {
val signedParametersHash = input.readBytes().deserialize<SignedData<SecureHash>>()
val signedParametersHash = input.readObject<SignedData<SecureHash>>()
val hash = signedParametersHash.verified()
networkMapStorage.getSignedNetworkParameters(hash) ?: throw IllegalArgumentException("No network parameters with hash $hash")
logger.debug { "Received ack-parameters with $hash from ${signedParametersHash.sig.by}" }

View File

@ -12,6 +12,7 @@ package com.r3.corda.networkmanage.doorman.webservice
import com.r3.corda.networkmanage.common.persistence.CertificateResponse
import com.r3.corda.networkmanage.doorman.signer.CsrHandler
import net.corda.core.internal.readFully
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
@ -45,7 +46,7 @@ class RegistrationWebService(private val csrHandler: CsrHandler, private val cli
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.TEXT_PLAIN)
fun submitRequest(input: InputStream): Response {
val csr = input.use { JcaPKCS10CertificationRequest(it.readBytes()) }
val csr = JcaPKCS10CertificationRequest(input.readFully())
if (!csr.isSignatureValid()) {
return status(Response.Status.BAD_REQUEST).entity("Invalid CSR signature").build()
}

View File

@ -12,7 +12,6 @@ package com.r3.corda.networkmanage.hsm.authentication
import CryptoServerJCE.CryptoServerProvider
import com.r3.corda.networkmanage.common.signer.AuthenticationException
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.nio.file.Path
import kotlin.reflect.full.memberProperties
@ -155,9 +154,6 @@ fun createProvider(config: CryptoServerProviderConfig): CryptoServerProvider {
writer.write("${property.name} = ${property.get(config)}\n")
}
writer.close()
val cfg = ByteArrayInputStream(cfgBuffer.toByteArray())
cfgBuffer.close()
val provider = CryptoServerProvider(cfg)
cfg.close()
return provider
val cfg = cfgBuffer.toByteArray().inputStream()
return CryptoServerProvider(cfg)
}

View File

@ -14,9 +14,7 @@ import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity
import com.r3.corda.networkmanage.common.persistence.entity.ParametersUpdateEntity
import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus
import com.r3.corda.networkmanage.common.utils.hashString
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.serialization.serialize
import net.corda.core.utilities.days
import net.corda.nodeapi.internal.createDevNetworkMapCa

View File

@ -12,12 +12,11 @@ package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity
import com.r3.corda.networkmanage.common.utils.hashString
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.CertRole
import net.corda.core.internal.hash
import net.corda.core.serialization.serialize
import net.corda.core.utilities.days
import net.corda.nodeapi.internal.NodeInfoAndSigned
@ -86,14 +85,14 @@ class PersistentNodeInfoStorageTest : TestBase() {
requestStorage.markRequestTicketCreated(requestId)
requestStorage.approveRequest(requestId, CertificateSigningRequestStorage.DOORMAN_SIGNATURE)
assertNull(nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString())))
assertNull(nodeInfoStorage.getCertificatePath(keyPair.public.hash))
requestStorage.putCertificatePath(
requestId,
X509Utilities.buildCertPath(nodeCaCert, doormanCertAndKeyPair.certificate, rootCaCert),
CertificateSigningRequestStorage.DOORMAN_SIGNATURE)
val storedCertPath = nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString()))
val storedCertPath = nodeInfoStorage.getCertificatePath(keyPair.public.hash)
assertNotNull(storedCertPath)
assertEquals(nodeCaCert, storedCertPath!!.certificates.first())