mirror of
https://github.com/corda/corda.git
synced 2024-12-28 00:38:55 +00:00
HSM signing of network parameters (#363)
Add HSM signing of network parameters
This commit is contained in:
parent
af21f6065d
commit
f2f803ecd5
@ -3,6 +3,7 @@ package com.r3.corda.networkmanage.common.persistence
|
||||
import com.r3.corda.networkmanage.common.utils.SignedNetworkMap
|
||||
import com.r3.corda.networkmanage.common.utils.SignedNetworkParameters
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.internal.DigitalSignatureWithCert
|
||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||
|
||||
/**
|
||||
@ -31,26 +32,28 @@ interface NetworkMapStorage {
|
||||
fun saveNetworkMap(signedNetworkMap: SignedNetworkMap)
|
||||
|
||||
/**
|
||||
* Return the signed network parameters object which matches the given hash. The hash is that of the underlying
|
||||
* [NetworkParameters] object and not the `SignedData<NetworkParameters>` object that's returned.
|
||||
* Retrieve the signed with certificate network parameters by their hash. The hash is that of the underlying
|
||||
* [NetworkParameters] object and not the `SignedWithCert<NetworkParameters>` object that's returned.
|
||||
* @return signed network parameters corresponding to the given hash or null if it does not exist (parameters don't exist or they haven't been signed yet)
|
||||
*/
|
||||
fun getSignedNetworkParameters(hash: SecureHash): SignedNetworkParameters?
|
||||
|
||||
/**
|
||||
* Retrieve network map parameters.
|
||||
* @return current network map parameters or null if they don't exist
|
||||
* @return signed current network map parameters or null if they don't exist
|
||||
*/
|
||||
fun getCurrentNetworkParameters(): NetworkParameters?
|
||||
fun getCurrentSignedNetworkParameters(): SignedNetworkParameters?
|
||||
|
||||
/**
|
||||
* Persists given network parameters.
|
||||
* @return hash corresponding to newly create network parameters entry
|
||||
* Persists given network parameters with signature if provided.
|
||||
* @return hash corresponding to newly created network parameters entry
|
||||
*/
|
||||
fun saveNetworkParameters(networkParameters: NetworkParameters): SecureHash
|
||||
fun saveNetworkParameters(networkParameters: NetworkParameters, sig: DigitalSignatureWithCert?): SecureHash
|
||||
|
||||
/**
|
||||
* Retrieves the latest (i.e. most recently inserted) network parameters
|
||||
* Note that they may not have been signed up yet.
|
||||
* @return latest network parameters
|
||||
*/
|
||||
fun getLatestNetworkParameters(): NetworkParameters
|
||||
fun getLatestUnsignedNetworkParameters(): NetworkParameters
|
||||
}
|
@ -3,9 +3,9 @@ package com.r3.corda.networkmanage.common.persistence
|
||||
import com.r3.corda.networkmanage.common.persistence.entity.*
|
||||
import com.r3.corda.networkmanage.common.utils.SignedNetworkMap
|
||||
import com.r3.corda.networkmanage.common.utils.SignedNetworkParameters
|
||||
import com.r3.corda.networkmanage.doorman.signer.LocalSigner
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.sha256
|
||||
import net.corda.core.internal.DigitalSignatureWithCert
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
@ -16,7 +16,7 @@ import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||
/**
|
||||
* Database implementation of the [NetworkMapStorage] interface
|
||||
*/
|
||||
class PersistentNetworkMapStorage(private val database: CordaPersistence, private val localSigner: LocalSigner?) : NetworkMapStorage {
|
||||
class PersistentNetworkMapStorage(private val database: CordaPersistence) : NetworkMapStorage {
|
||||
override fun getCurrentNetworkMap(): SignedNetworkMap? {
|
||||
return database.transaction {
|
||||
getCurrentNetworkMapEntity()?.let {
|
||||
@ -26,11 +26,11 @@ class PersistentNetworkMapStorage(private val database: CordaPersistence, privat
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCurrentNetworkParameters(): NetworkParameters? {
|
||||
override fun getCurrentSignedNetworkParameters(): SignedNetworkParameters? {
|
||||
return database.transaction {
|
||||
getCurrentNetworkMapEntity()?.let {
|
||||
val netParamsHash = it.networkMap.deserialize<NetworkMap>().networkParameterHash
|
||||
getNetworkParametersEntity(netParamsHash.toString())?.networkParameters()
|
||||
getSignedNetworkParameters(netParamsHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,12 +46,8 @@ class PersistentNetworkMapStorage(private val database: CordaPersistence, privat
|
||||
}
|
||||
}
|
||||
|
||||
// TODO The signing cannot occur here as it won't work with an HSM. The signed network parameters needs to be persisted
|
||||
// into the database.
|
||||
override fun getSignedNetworkParameters(hash: SecureHash): SignedNetworkParameters? {
|
||||
val netParamsBytes = getNetworkParametersEntity(hash.toString())?.parametersBytes ?: return null
|
||||
val sigWithCert = localSigner!!.signBytes(netParamsBytes)
|
||||
return SignedNetworkParameters(SerializedBytes(netParamsBytes), sigWithCert)
|
||||
return getNetworkParametersEntity(hash.toString())?.signedParameters()
|
||||
}
|
||||
|
||||
override fun getNodeInfoHashes(certificateStatus: CertificateStatus): List<SecureHash> {
|
||||
@ -69,31 +65,32 @@ class PersistentNetworkMapStorage(private val database: CordaPersistence, privat
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveNetworkParameters(networkParameters: NetworkParameters): SecureHash {
|
||||
override fun saveNetworkParameters(networkParameters: NetworkParameters, sig: DigitalSignatureWithCert?): SecureHash {
|
||||
return database.transaction {
|
||||
val bytes = networkParameters.serialize().bytes
|
||||
val hash = bytes.sha256()
|
||||
session.save(NetworkParametersEntity(
|
||||
session.saveOrUpdate(NetworkParametersEntity(
|
||||
parametersBytes = bytes,
|
||||
parametersHash = hash.toString()
|
||||
parametersHash = hash.toString(),
|
||||
signature = sig?.bytes,
|
||||
certificate = sig?.by?.encoded
|
||||
))
|
||||
hash
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLatestNetworkParameters(): NetworkParameters = getLatestNetworkParametersEntity().networkParameters()
|
||||
override fun getLatestUnsignedNetworkParameters(): NetworkParameters = getLatestNetworkParametersEntity().networkParameters()
|
||||
|
||||
private fun getLatestNetworkParametersEntity(): NetworkParametersEntity {
|
||||
return database.transaction {
|
||||
val builder = session.criteriaBuilder
|
||||
val query = builder.createQuery(NetworkParametersEntity::class.java).run {
|
||||
// TODO a limit of 1 since we only need the first result
|
||||
from(NetworkParametersEntity::class.java).run {
|
||||
orderBy(builder.desc(get<String>(NetworkParametersEntity::version.name)))
|
||||
orderBy(builder.desc(get<String>(NetworkParametersEntity::created.name)))
|
||||
}
|
||||
}
|
||||
// We just want the last signed entry
|
||||
session.createQuery(query).resultList.first()
|
||||
// We just want the last entry
|
||||
session.createQuery(query).setMaxResults(1).resultList.singleOrNull() ?: throw IllegalArgumentException("No network parameters found in network map storage")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,47 @@
|
||||
package com.r3.corda.networkmanage.common.persistence.entity
|
||||
|
||||
import com.r3.corda.networkmanage.common.utils.SignedNetworkParameters
|
||||
import net.corda.core.internal.DigitalSignatureWithCert
|
||||
import net.corda.core.internal.SignedDataWithCert
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||
import org.hibernate.annotations.CreationTimestamp
|
||||
import java.time.Instant
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "network_parameters")
|
||||
@Table(name = "network_parameters", indexes = arrayOf(Index(name = "IDX_NET_PARAMS_HASH", columnList = "hash")))
|
||||
class NetworkParametersEntity(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
val version: Long? = null,
|
||||
|
||||
@Column(name = "hash", length = 64, unique = true)
|
||||
val parametersHash: String,
|
||||
|
||||
@CreationTimestamp
|
||||
val created: Instant = Instant.now(),
|
||||
|
||||
@Lob
|
||||
@Column(name = "bytes")
|
||||
val parametersBytes: ByteArray
|
||||
@Column(name = "parameters_bytes")
|
||||
val parametersBytes: ByteArray,
|
||||
|
||||
// Both of the fields below are nullable, because of the way we sign network map data. NetworkParameters can be
|
||||
// inserted into database without signature. Then signing service will sign them.
|
||||
@Lob
|
||||
@Column(name = "signature")
|
||||
val signature: ByteArray?,
|
||||
|
||||
@Lob
|
||||
@Column(name = "certificate")
|
||||
val certificate: ByteArray?
|
||||
) {
|
||||
fun networkParameters(): NetworkParameters = parametersBytes.deserialize()
|
||||
|
||||
// Return signed network parameters or null if they haven't been signed yet.
|
||||
fun signedParameters(): SignedNetworkParameters? {
|
||||
return if (certificate != null && signature != null) {
|
||||
val sigWithCert = DigitalSignatureWithCert(X509CertificateFactory().generateCertificate(certificate.inputStream()), signature)
|
||||
SignedDataWithCert(SerializedBytes(parametersBytes), sigWithCert)
|
||||
} else null
|
||||
}
|
||||
}
|
@ -5,19 +5,33 @@ import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
||||
import net.corda.core.internal.SignedDataWithCert
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.nodeapi.internal.network.NetworkMap
|
||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||
|
||||
class NetworkMapSigner(private val networkMapStorage: NetworkMapStorage, private val signer: Signer) {
|
||||
/**
|
||||
* Signs the network map.
|
||||
* Signs the network map and latest network parameters if they haven't been signed yet.
|
||||
*/
|
||||
fun signNetworkMap() {
|
||||
// TODO There is no network parameters update process in place yet. We assume that latest parameters are to be used
|
||||
// in current network map.
|
||||
val latestNetworkParameters = networkMapStorage.getLatestUnsignedNetworkParameters()
|
||||
val currentNetworkParameters = networkMapStorage.getCurrentSignedNetworkParameters()
|
||||
if (currentNetworkParameters?.verified() != latestNetworkParameters)
|
||||
signNetworkParameters(latestNetworkParameters)
|
||||
val currentSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
|
||||
val nodeInfoHashes = networkMapStorage.getNodeInfoHashes(CertificateStatus.VALID)
|
||||
val networkParameters = networkMapStorage.getLatestNetworkParameters()
|
||||
val serialisedNetworkMap = NetworkMap(nodeInfoHashes, networkParameters.serialize().hash).serialize()
|
||||
val serialisedNetworkMap = NetworkMap(nodeInfoHashes, latestNetworkParameters.serialize().hash).serialize()
|
||||
if (serialisedNetworkMap != currentSignedNetworkMap?.raw) {
|
||||
val newSignedNetworkMap = SignedDataWithCert(serialisedNetworkMap, signer.signBytes(serialisedNetworkMap.bytes))
|
||||
networkMapStorage.saveNetworkMap(newSignedNetworkMap)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs latest inserted network parameters.
|
||||
*/
|
||||
fun signNetworkParameters(networkParameters: NetworkParameters) {
|
||||
val digitalSignature = signer.signObject(networkParameters).sig
|
||||
networkMapStorage.saveNetworkParameters(networkParameters, digitalSignature)
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import net.corda.core.serialization.serialize
|
||||
*/
|
||||
interface Signer {
|
||||
/**
|
||||
* Signs given bytes. The signing key selction strategy is left to the implementing class.
|
||||
* Signs given bytes. The signing key selection strategy is left to the implementing class.
|
||||
* @return [DigitalSignatureWithCert] that encapsulates the signature and the certificate path used in the signing process.
|
||||
* @throws [AuthenticationException] if fails authentication
|
||||
*/
|
||||
|
@ -52,14 +52,15 @@ class NetworkManagementServer : Closeable {
|
||||
}
|
||||
|
||||
private fun getNetworkMapService(config: NetworkMapConfig, database: CordaPersistence, signer: LocalSigner?, updateNetworkParameters: NetworkParameters?): NodeInfoWebService {
|
||||
val networkMapStorage = PersistentNetworkMapStorage(database, signer)
|
||||
val networkMapStorage = PersistentNetworkMapStorage(database)
|
||||
val nodeInfoStorage = PersistentNodeInfoStorage(database)
|
||||
val localNetworkMapSigner = if (signer != null) NetworkMapSigner(networkMapStorage, signer) else null
|
||||
|
||||
updateNetworkParameters?.let {
|
||||
// Persisting new network parameters
|
||||
val currentNetworkParameters = networkMapStorage.getCurrentNetworkParameters()
|
||||
val currentNetworkParameters = networkMapStorage.getCurrentSignedNetworkParameters()
|
||||
if (currentNetworkParameters == null) {
|
||||
networkMapStorage.saveNetworkParameters(it)
|
||||
localNetworkMapSigner?.signNetworkParameters(it) ?: networkMapStorage.saveNetworkParameters(it, null)
|
||||
} else {
|
||||
throw UnsupportedOperationException("Network parameters already exist. Updating them via the file config is not supported yet.")
|
||||
}
|
||||
@ -67,21 +68,19 @@ class NetworkManagementServer : Closeable {
|
||||
|
||||
// This call will fail if parameter is null in DB.
|
||||
try {
|
||||
val latestParameter = networkMapStorage.getLatestNetworkParameters()
|
||||
val latestParameter = networkMapStorage.getLatestUnsignedNetworkParameters()
|
||||
logger.info("Starting network map service with network parameters : $latestParameter")
|
||||
} catch (e: NoSuchElementException) {
|
||||
logger.error("No network parameter found, please upload new network parameter before starting network map service. The server will now exit.")
|
||||
exitProcess(-1)
|
||||
}
|
||||
|
||||
val networkMapSigner = if (signer != null) NetworkMapSigner(networkMapStorage, signer) else null
|
||||
|
||||
// Thread sign network map in case of change (i.e. a new node info has been added or a node info has been removed).
|
||||
if (networkMapSigner != null) {
|
||||
if (localNetworkMapSigner != null) {
|
||||
val scheduledExecutor = Executors.newScheduledThreadPool(1)
|
||||
val signingThread = Runnable {
|
||||
try {
|
||||
networkMapSigner.signNetworkMap()
|
||||
localNetworkMapSigner.signNetworkMap()
|
||||
} catch (e: Exception) {
|
||||
// Log the error and carry on.
|
||||
logger.error("Error encountered when processing node info changes.", e)
|
||||
@ -141,7 +140,6 @@ class NetworkManagementServer : Closeable {
|
||||
val services = mutableListOf<Any>()
|
||||
val serverStatus = NetworkManagementServerStatus()
|
||||
|
||||
// TODO: move signing to signing server.
|
||||
startNetworkMap?.let { services += getNetworkMapService(it.config, database, it.signer, it.updateNetworkParameters) }
|
||||
doormanServiceParameter?.let { services += getDoormanService(it, database, doormanSigner, serverStatus) }
|
||||
|
||||
|
@ -7,6 +7,7 @@ import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
||||
import com.r3.corda.networkmanage.common.persistence.NodeInfoStorage
|
||||
import com.r3.corda.networkmanage.common.persistence.NodeInfoWithSigned
|
||||
import com.r3.corda.networkmanage.common.utils.SignedNetworkMap
|
||||
import com.r3.corda.networkmanage.common.utils.SignedNetworkParameters
|
||||
import com.r3.corda.networkmanage.doorman.NetworkMapConfig
|
||||
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService.Companion.NETWORK_MAP_PATH
|
||||
import net.corda.core.crypto.SecureHash
|
||||
@ -41,7 +42,7 @@ class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage,
|
||||
|
||||
private val networkMapCache: LoadingCache<Boolean, Pair<SignedNetworkMap?, NetworkParameters?>> = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(config.cacheTimeout, TimeUnit.MILLISECONDS)
|
||||
.build(CacheLoader.from { _ -> Pair(networkMapStorage.getCurrentNetworkMap(), networkMapStorage.getCurrentNetworkParameters()) })
|
||||
.build(CacheLoader.from { _ -> Pair(networkMapStorage.getCurrentNetworkMap(), networkMapStorage.getCurrentSignedNetworkParameters()?.verified()) })
|
||||
|
||||
@POST
|
||||
@Path("publish")
|
||||
|
@ -46,8 +46,7 @@ fun run(parameters: Parameters) {
|
||||
checkNotNull(dataSourceProperties)
|
||||
val database = configureDatabase(dataSourceProperties, databaseConfig)
|
||||
val csrStorage = DBSignedCertificateRequestStorage(database)
|
||||
// TODO Remove the dependency for a local signer to make signing of network parameters work with an HSM
|
||||
val networkMapStorage = PersistentNetworkMapStorage(database, localSigner = null)
|
||||
val networkMapStorage = PersistentNetworkMapStorage(database)
|
||||
val hsmNetworkMapSigningThread = HsmNetworkMapSigner(
|
||||
networkMapStorage,
|
||||
networkMapCertificateName,
|
||||
|
@ -93,11 +93,13 @@
|
||||
</changeSet>
|
||||
<changeSet author="R3.Corda" id="1513267683777-8">
|
||||
<createTable tableName="network_parameters">
|
||||
<column name="version" type="BIGINT">
|
||||
<column name="hash" type="NVARCHAR(64)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="bytes" type="BLOB"/>
|
||||
<column name="hash" type="NVARCHAR(64)"/>
|
||||
<column name="certificate" type="BLOB"/>
|
||||
<column name="created" type="TIMESTAMP"/>
|
||||
<column name="parameters_bytes" type="BLOB"/>
|
||||
<column name="signature" type="BLOB"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="R3.Corda" id="1513267683777-9">
|
||||
@ -120,7 +122,7 @@
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="R3.Corda" id="1513267683777-11">
|
||||
<addPrimaryKey columnNames="version" constraintName="CONSTRAINT_3" tableName="network_parameters"/>
|
||||
<addPrimaryKey columnNames="hash" constraintName="CONSTRAINT_3" tableName="network_parameters"/>
|
||||
</changeSet>
|
||||
<changeSet author="R3.Corda" id="1513267683777-12">
|
||||
<addPrimaryKey columnNames="id" constraintName="CONSTRAINT_7" tableName="certificate_data"/>
|
||||
@ -167,6 +169,11 @@
|
||||
<column name="public_key_hash"/>
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
<changeSet author="R3.Corda" id="network-parameters-idx">
|
||||
<createIndex indexName="IDX_NET_PARAMS_HASH" tableName="network_parameters">
|
||||
<column name="hash"/>
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
<changeSet author="R3.Corda" id="1513267683777-24">
|
||||
<addForeignKeyConstraint baseColumnNames="rev" baseTableName="certificate_signing_request_AUD"
|
||||
constraintName="FK5g5cagcrx7siu8lwtavirunxd"
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.r3.corda.networkmanage.common.persistence
|
||||
|
||||
import com.r3.corda.networkmanage.TestBase
|
||||
import com.r3.corda.networkmanage.doorman.signer.LocalSigner
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.signWithCert
|
||||
import net.corda.nodeapi.internal.createDevNetworkMapCa
|
||||
@ -37,7 +36,7 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
rootCaCert = rootCa.certificate
|
||||
networkMapCa = createDevNetworkMapCa(rootCa)
|
||||
persistence = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(runMigration = true))
|
||||
networkMapStorage = PersistentNetworkMapStorage(persistence, LocalSigner(networkMapCa.keyPair, arrayOf(networkMapCa.certificate, rootCaCert)))
|
||||
networkMapStorage = PersistentNetworkMapStorage(persistence)
|
||||
nodeInfoStorage = PersistentNodeInfoStorage(persistence)
|
||||
requestStorage = PersistentCertificateRequestStorage(persistence)
|
||||
}
|
||||
@ -48,15 +47,16 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `signNetworkMap creates current network map`() {
|
||||
fun `saveNetworkMap and saveNetworkParameters create current network map and parameters`() {
|
||||
// given
|
||||
// Create node info.
|
||||
val signedNodeInfo = createValidSignedNodeInfo("Test")
|
||||
val nodeInfoHash = nodeInfoStorage.putNodeInfo(signedNodeInfo)
|
||||
|
||||
val networkParameters = testNetworkParameters(emptyList())
|
||||
val parametersSignature = networkParameters.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate).sig
|
||||
// Create network parameters
|
||||
val networkParametersHash = networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList()))
|
||||
|
||||
val networkParametersHash = networkMapStorage.saveNetworkParameters(networkParameters, parametersSignature)
|
||||
val networkMap = NetworkMap(listOf(nodeInfoHash), networkParametersHash)
|
||||
val signedNetworkMap = networkMap.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate)
|
||||
|
||||
@ -65,20 +65,26 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
|
||||
// then
|
||||
val persistedSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
|
||||
val persistedSignedParameters = networkMapStorage.getCurrentSignedNetworkParameters()
|
||||
|
||||
assertEquals(networkParameters, persistedSignedParameters?.verifiedNetworkMapCert(rootCaCert))
|
||||
assertEquals(parametersSignature, persistedSignedParameters?.sig)
|
||||
assertEquals(signedNetworkMap.sig, persistedSignedNetworkMap?.sig)
|
||||
assertEquals(signedNetworkMap.verifiedNetworkMapCert(rootCaCert), persistedSignedNetworkMap?.verifiedNetworkMapCert(rootCaCert))
|
||||
assertEquals(signedNetworkMap.verifiedNetworkMapCert(rootCaCert).networkParameterHash, persistedSignedParameters?.raw?.hash)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getLatestNetworkParameters returns last inserted`() {
|
||||
val params1 = testNetworkParameters(emptyList(), minimumPlatformVersion = 1)
|
||||
val params2 = testNetworkParameters(emptyList(), minimumPlatformVersion = 2)
|
||||
// given
|
||||
networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList(), minimumPlatformVersion = 1))
|
||||
networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList(), minimumPlatformVersion = 2))
|
||||
networkMapStorage.saveNetworkParameters(params1, params1.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate).sig)
|
||||
// We may have not signed them yet.
|
||||
networkMapStorage.saveNetworkParameters(params2, null)
|
||||
|
||||
// when
|
||||
val latest = networkMapStorage.getLatestNetworkParameters()
|
||||
|
||||
val latest = networkMapStorage.getLatestUnsignedNetworkParameters()
|
||||
// then
|
||||
assertEquals(2, latest.minimumPlatformVersion)
|
||||
}
|
||||
@ -87,7 +93,8 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
fun `getCurrentNetworkParameters returns current network map parameters`() {
|
||||
// given
|
||||
// Create network parameters
|
||||
val networkParametersHash = networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList()))
|
||||
val testParameters1 = testNetworkParameters(emptyList())
|
||||
val networkParametersHash = networkMapStorage.saveNetworkParameters(testParameters1, testParameters1.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate).sig)
|
||||
// Create empty network map
|
||||
|
||||
// Sign network map making it current network map
|
||||
@ -96,25 +103,16 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
networkMapStorage.saveNetworkMap(signedNetworkMap)
|
||||
|
||||
// Create new network parameters
|
||||
networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList(), minimumPlatformVersion = 2))
|
||||
val testParameters2 = testNetworkParameters(emptyList(), minimumPlatformVersion = 2)
|
||||
networkMapStorage.saveNetworkParameters(testParameters2, testParameters2.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate).sig)
|
||||
|
||||
// when
|
||||
val result = networkMapStorage.getCurrentNetworkParameters()
|
||||
val result = networkMapStorage.getCurrentSignedNetworkParameters()?.verifiedNetworkMapCert(rootCaCert)
|
||||
|
||||
// then
|
||||
assertEquals(1, result?.minimumPlatformVersion)
|
||||
}
|
||||
|
||||
// This test will probably won't be needed when we remove the explicit use of LocalSigner
|
||||
@Test
|
||||
fun `getSignedNetworkParameters uses the local signer to return a signed object`() {
|
||||
val networkParameters = testNetworkParameters(emptyList())
|
||||
val netParamsHash = networkMapStorage.saveNetworkParameters(networkParameters)
|
||||
val signedNetworkParameters = networkMapStorage.getSignedNetworkParameters(netParamsHash)
|
||||
assertThat(signedNetworkParameters?.verifiedNetworkMapCert(rootCaCert)).isEqualTo(networkParameters)
|
||||
assertThat(signedNetworkParameters?.sig?.by).isEqualTo(networkMapCa.certificate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getValidNodeInfoHashes returns only valid and signed node info hashes`() {
|
||||
// given
|
||||
@ -127,7 +125,8 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
val nodeInfoHashB = nodeInfoStorage.putNodeInfo(signedNodeInfoB)
|
||||
|
||||
// Create network parameters
|
||||
val networkParametersHash = networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList()))
|
||||
val testParameters = testNetworkParameters(emptyList())
|
||||
val networkParametersHash = networkMapStorage.saveNetworkParameters(testParameters, testParameters.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate).sig)
|
||||
val networkMap = NetworkMap(listOf(nodeInfoHashA), networkParametersHash)
|
||||
val signedNetworkMap = networkMap.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate)
|
||||
|
||||
|
@ -6,9 +6,7 @@ import com.r3.corda.networkmanage.common.utils.hashString
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||
@ -33,7 +31,6 @@ class PersistentNodeInfoStorageTest : TestBase() {
|
||||
private lateinit var requestStorage: CertificationRequestStorage
|
||||
private lateinit var nodeInfoStorage: PersistentNodeInfoStorage
|
||||
private lateinit var persistence: CordaPersistence
|
||||
|
||||
private lateinit var rootCaCert: X509Certificate
|
||||
private lateinit var intermediateCa: CertificateAndKeyPair
|
||||
|
||||
|
@ -8,6 +8,7 @@ import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.sha256
|
||||
import net.corda.core.internal.DigitalSignatureWithCert
|
||||
import net.corda.core.internal.SignedDataWithCert
|
||||
import net.corda.core.internal.signWithCert
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.nodeapi.internal.createDevNetworkMapCa
|
||||
@ -16,10 +17,10 @@ import net.corda.nodeapi.internal.network.NetworkMap
|
||||
import net.corda.nodeapi.internal.network.verifiedNetworkMapCert
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
||||
import java.security.cert.X509Certificate
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.security.cert.X509Certificate
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class NetworkMapSignerTest : TestBase() {
|
||||
@ -41,18 +42,24 @@ class NetworkMapSignerTest : TestBase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `signNetworkMap builds and signs network map`() {
|
||||
fun `signNetworkMap builds and signs network map and network parameters`() {
|
||||
// given
|
||||
val signedNodeInfoHashes = listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256())
|
||||
val networkParameters = testNetworkParameters(emptyList())
|
||||
val networkMap = NetworkMap(signedNodeInfoHashes, SecureHash.randomSHA256())
|
||||
val currentParameters = testNetworkParameters(emptyList(), minimumPlatformVersion = 1)
|
||||
val latestNetworkParameters = testNetworkParameters(emptyList(), minimumPlatformVersion = 2)
|
||||
val networkMap = NetworkMap(signedNodeInfoHashes, currentParameters.serialize().hash)
|
||||
val signedNetworkMap = networkMap.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate)
|
||||
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(signedNetworkMap)
|
||||
whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(signedNodeInfoHashes)
|
||||
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkParameters)
|
||||
whenever(networkMapStorage.getLatestUnsignedNetworkParameters()).thenReturn(latestNetworkParameters)
|
||||
whenever(networkMapStorage.getCurrentSignedNetworkParameters()).thenReturn(currentParameters.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate))
|
||||
whenever(signer.signBytes(any())).then {
|
||||
DigitalSignatureWithCert(networkMapCa.certificate, Crypto.doSign(networkMapCa.keyPair.private, it.arguments[0] as ByteArray))
|
||||
}
|
||||
whenever(signer.signObject(latestNetworkParameters)).then {
|
||||
val serialised = latestNetworkParameters.serialize()
|
||||
SignedDataWithCert(serialised, signer.signBytes(serialised.bytes))
|
||||
}
|
||||
|
||||
// when
|
||||
networkMapSigner.signNetworkMap()
|
||||
@ -60,11 +67,12 @@ class NetworkMapSignerTest : TestBase() {
|
||||
// then
|
||||
// Verify networkMapStorage calls
|
||||
verify(networkMapStorage).getNodeInfoHashes(any())
|
||||
verify(networkMapStorage).getLatestNetworkParameters()
|
||||
verify(networkMapStorage).getLatestUnsignedNetworkParameters()
|
||||
verify(networkMapStorage).getCurrentSignedNetworkParameters()
|
||||
argumentCaptor<SignedNetworkMap>().apply {
|
||||
verify(networkMapStorage).saveNetworkMap(capture())
|
||||
val capturedNetworkMap = firstValue.verifiedNetworkMapCert(rootCaCert)
|
||||
assertEquals(networkParameters.serialize().hash, capturedNetworkMap.networkParameterHash)
|
||||
assertEquals(latestNetworkParameters.serialize().hash, capturedNetworkMap.networkParameterHash)
|
||||
assertEquals(signedNodeInfoHashes.size, capturedNetworkMap.nodeInfoHashes.size)
|
||||
assertThat(capturedNetworkMap.nodeInfoHashes).containsAll(signedNodeInfoHashes)
|
||||
}
|
||||
@ -79,7 +87,8 @@ class NetworkMapSignerTest : TestBase() {
|
||||
val signedNetworkMap = networkMap.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate)
|
||||
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(signedNetworkMap)
|
||||
whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(emptyList())
|
||||
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkParameters)
|
||||
whenever(networkMapStorage.getLatestUnsignedNetworkParameters()).thenReturn(networkParameters)
|
||||
whenever(networkMapStorage.getCurrentSignedNetworkParameters()).thenReturn(networkParameters.signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate))
|
||||
|
||||
// when
|
||||
networkMapSigner.signNetworkMap()
|
||||
@ -95,17 +104,21 @@ class NetworkMapSignerTest : TestBase() {
|
||||
val networkParameters = testNetworkParameters(emptyList())
|
||||
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(null)
|
||||
whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(emptyList())
|
||||
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkParameters)
|
||||
whenever(networkMapStorage.getLatestUnsignedNetworkParameters()).thenReturn(networkParameters)
|
||||
whenever(signer.signBytes(any())).then {
|
||||
DigitalSignatureWithCert(networkMapCa.certificate, Crypto.doSign(networkMapCa.keyPair.private, it.arguments[0] as ByteArray))
|
||||
}
|
||||
whenever(signer.signObject(networkParameters)).then {
|
||||
val serialised = networkParameters.serialize()
|
||||
SignedDataWithCert(serialised, signer.signBytes(serialised.bytes))
|
||||
}
|
||||
// when
|
||||
networkMapSigner.signNetworkMap()
|
||||
|
||||
// then
|
||||
// Verify networkMapStorage calls
|
||||
verify(networkMapStorage).getNodeInfoHashes(any())
|
||||
verify(networkMapStorage).getLatestNetworkParameters()
|
||||
verify(networkMapStorage).getLatestUnsignedNetworkParameters()
|
||||
argumentCaptor<SignedNetworkMap>().apply {
|
||||
verify(networkMapStorage).saveNetworkMap(capture())
|
||||
val networkMap = firstValue.verifiedNetworkMapCert(rootCaCert)
|
||||
|
@ -56,7 +56,7 @@ class NodeInfoWebServiceTest {
|
||||
@Test
|
||||
fun `submit nodeInfo`() {
|
||||
val networkMapStorage: NetworkMapStorage = mock {
|
||||
on { getCurrentNetworkParameters() }.thenReturn(testNetworkParameters(emptyList()))
|
||||
on { getCurrentSignedNetworkParameters() }.thenReturn(testNetworkParameters(emptyList()).signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate))
|
||||
}
|
||||
// Create node info.
|
||||
val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"))
|
||||
@ -72,7 +72,7 @@ class NodeInfoWebServiceTest {
|
||||
@Test
|
||||
fun `submit old nodeInfo`() {
|
||||
val networkMapStorage: NetworkMapStorage = mock {
|
||||
on { getCurrentNetworkParameters() }.thenReturn(testNetworkParameters(emptyList(), minimumPlatformVersion = 2))
|
||||
on { getCurrentSignedNetworkParameters() }.thenReturn(testNetworkParameters(emptyList(), minimumPlatformVersion = 2).signWithCert(networkMapCa.keyPair.private, networkMapCa.certificate))
|
||||
}
|
||||
// Create node info.
|
||||
val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"), platformVersion = 1)
|
||||
@ -88,7 +88,7 @@ class NodeInfoWebServiceTest {
|
||||
@Test
|
||||
fun `submit nodeInfo when no network parameters`() {
|
||||
val networkMapStorage: NetworkMapStorage = mock {
|
||||
on { getCurrentNetworkParameters() }.thenReturn(null)
|
||||
on { getCurrentSignedNetworkParameters() }.thenReturn(null)
|
||||
}
|
||||
// Create node info.
|
||||
val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"), platformVersion = 1)
|
||||
@ -155,7 +155,6 @@ class NodeInfoWebServiceTest {
|
||||
verify(networkMapStorage, times(1)).getSignedNetworkParameters(networkParametersHash)
|
||||
assertThat(netParamsResponse.verified()).isEqualTo(networkParameters)
|
||||
assertThat(netParamsResponse.sig.by).isEqualTo(networkMapCa.certificate)
|
||||
|
||||
assertThatExceptionOfType(IOException::class.java)
|
||||
.isThrownBy { it.doGet<SignedNetworkParameters>("network-parameters/${randomSHA256()}") }
|
||||
.withMessageContaining("404")
|
||||
|
@ -41,9 +41,9 @@ import javax.ws.rs.core.MediaType
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class RegistrationWebServiceTest : TestBase() {
|
||||
private lateinit var webServer: NetworkManagementWebServer
|
||||
private lateinit var rootCaCert: X509Certificate
|
||||
private lateinit var intermediateCa: CertificateAndKeyPair
|
||||
private lateinit var webServer: NetworkManagementWebServer
|
||||
|
||||
@Before
|
||||
fun init() {
|
||||
|
Loading…
Reference in New Issue
Block a user