From 51f1e442a34ee40e260832b42e910320abff47b5 Mon Sep 17 00:00:00 2001 From: Viktor Kolomeyko Date: Thu, 27 Jun 2019 11:55:59 +0100 Subject: [PATCH] CORDA-3021: Introduce `SignOnlyCryptoService` and use it whenever possible (#5239) * CORDA-3021: Introduce `SignOnlyCryptoService` and use it whenever possible Also modify `CryptoServiceFactory` to show how sign only implementation can be created. * CORDA-3021: Undo some of my earlier changes Which after discussion with @dimosr and @fowlerrr proven to be contradictory. --- .../internal/cryptoservice/CryptoService.kt | 33 ++++++++++++------- .../node/services/config/ConfigUtilities.kt | 8 ++--- .../keys/BasicHSMKeyManagementService.kt | 5 ++- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/cryptoservice/CryptoService.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/cryptoservice/CryptoService.kt index daf91dbdd8..a71ed3cd3b 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/cryptoservice/CryptoService.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/cryptoservice/CryptoService.kt @@ -7,19 +7,11 @@ import org.bouncycastle.operator.ContentSigner import java.security.KeyPair import java.security.PublicKey +/** + * Unlike [CryptoService] can only perform "read-only" operations but never create new key pairs. + */ @DoNotImplement -interface CryptoService { - - /** - * Generate and store a new [KeyPair]. - * Note that schemeNumberID is Corda specific. Cross-check with the network operator for supported schemeNumberID - * and their corresponding signature schemes. The main reason for using schemeNumberID and not algorithm OIDs is - * because some schemes might not be standardised and thus an official OID might for this scheme not exist yet. - * - * Returns the [PublicKey] of the generated [KeyPair]. - */ - fun generateKeyPair(alias: String, scheme: SignatureScheme): PublicKey - +interface SignOnlyCryptoService { /** Check if this [CryptoService] has a private key entry for the input alias. */ fun containsKey(alias: String): Boolean @@ -52,4 +44,21 @@ interface CryptoService { fun defaultTLSSignatureScheme(): SignatureScheme = X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME } +/** + * Fully-powered crypto service which can sign as well as create new key pairs. + */ +@DoNotImplement +interface CryptoService : SignOnlyCryptoService { + + /** + * Generate and store a new [KeyPair]. + * Note that schemeNumberID is Corda specific. Cross-check with the network operator for supported schemeNumberID + * and their corresponding signature schemes. The main reason for using schemeNumberID and not algorithm OIDs is + * because some schemes might not be standardised and thus an official OID might for this scheme not exist yet. + * + * Returns the [PublicKey] of the generated [KeyPair]. + */ + fun generateKeyPair(alias: String, scheme: SignatureScheme): PublicKey +} + open class CryptoServiceException(message: String?, cause: Throwable? = null) : Exception(message, cause) diff --git a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt index 8815171fae..fc96821714 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt @@ -13,7 +13,7 @@ import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier import net.corda.nodeapi.internal.config.MutualSslConfiguration import net.corda.nodeapi.internal.config.toProperties import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.cryptoservice.CryptoService +import net.corda.nodeapi.internal.cryptoservice.SignOnlyCryptoService import net.corda.nodeapi.internal.cryptoservice.bouncycastle.BCCryptoService import net.corda.nodeapi.internal.installDevNodeCaCertPath import net.corda.nodeapi.internal.loadDevCaTrustStore @@ -73,10 +73,10 @@ object ConfigHelper { * the CA certs in Node resources. Then provision KeyStores into certificates folder under node path. */ // TODO Move this to KeyStoreConfigHelpers. -fun NodeConfiguration.configureWithDevSSLCertificate(cryptoService: CryptoService? = null) = p2pSslOptions.configureDevKeyAndTrustStores(myLegalName, signingCertificateStore, certificatesDirectory, cryptoService) +fun NodeConfiguration.configureWithDevSSLCertificate(cryptoService: SignOnlyCryptoService? = null) = p2pSslOptions.configureDevKeyAndTrustStores(myLegalName, signingCertificateStore, certificatesDirectory, cryptoService) // TODO Move this to KeyStoreConfigHelpers. -fun MutualSslConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500Name, signingCertificateStore: FileBasedCertificateStoreSupplier, certificatesDirectory: Path, cryptoService: CryptoService? = null) { +fun MutualSslConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500Name, signingCertificateStore: FileBasedCertificateStoreSupplier, certificatesDirectory: Path, cryptoService: SignOnlyCryptoService? = null) { val specifiedTrustStore = trustStore.getOptional() val specifiedKeyStore = keyStore.getOptional() @@ -116,4 +116,4 @@ fun MutualSslConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500N else -> throw IllegalArgumentException("CryptoService not supported.") } } -} +} \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/services/keys/BasicHSMKeyManagementService.kt b/node/src/main/kotlin/net/corda/node/services/keys/BasicHSMKeyManagementService.kt index 1dc2cc3187..f3dac99eaf 100644 --- a/node/src/main/kotlin/net/corda/node/services/keys/BasicHSMKeyManagementService.kt +++ b/node/src/main/kotlin/net/corda/node/services/keys/BasicHSMKeyManagementService.kt @@ -9,12 +9,11 @@ import net.corda.core.serialization.serialize import net.corda.core.utilities.MAX_HASH_HEX_SIZE import net.corda.node.services.identity.PersistentIdentityService import net.corda.node.utilities.AppendOnlyPersistentMap -import net.corda.nodeapi.internal.cryptoservice.CryptoService +import net.corda.nodeapi.internal.cryptoservice.SignOnlyCryptoService import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX import org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY import org.bouncycastle.operator.ContentSigner -import org.hibernate.annotations.Type import java.security.KeyPair import java.security.PrivateKey import java.security.PublicKey @@ -30,7 +29,7 @@ import javax.persistence.* * This class needs database transactions to be in-flight during method calls and init. */ class BasicHSMKeyManagementService(cacheFactory: NamedCacheFactory, val identityService: PersistentIdentityService, - private val database: CordaPersistence, private val cryptoService: CryptoService) : SingletonSerializeAsToken(), KeyManagementServiceInternal { + private val database: CordaPersistence, private val cryptoService: SignOnlyCryptoService) : SingletonSerializeAsToken(), KeyManagementServiceInternal { @Entity @Table(name = "${NODE_DATABASE_PREFIX}our_key_pairs") class PersistentKey(