Added commonName extension method to X500Name and helper class for x509 cert factories

This commit is contained in:
Shams Asari 2016-12-08 16:33:01 +00:00
parent 57975c6e91
commit 9d98673c66
6 changed files with 35 additions and 32 deletions

View File

@ -430,14 +430,8 @@ object X509Utilities {
fun loadCertificateFromPEMFile(filename: Path): X509Certificate {
val reader = PemReader(FileReader(filename.toFile()))
val pemObject = reader.readPemObject()
val certFact = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME)
val inputStream = ByteArrayInputStream(pemObject.content)
try {
val cert = certFact.generateCertificate(inputStream) as X509Certificate
cert.checkValidity()
return cert
} finally {
inputStream.close()
return CertificateStream(pemObject.content.inputStream()).nextCertificate().apply {
checkValidity()
}
}
@ -609,3 +603,11 @@ object X509Utilities {
return keyStore
}
}
val X500Name.commonName: String get() = getRDNs(BCStyle.CN).first().first.value.toString()
class CertificateStream(val input: InputStream) {
private val certificateFactory = CertificateFactory.getInstance("X.509")
fun nextCertificate(): X509Certificate = certificateFactory.generateCertificate(input) as X509Certificate
}

View File

@ -8,7 +8,6 @@ import net.corda.core.serialization.DeserializeAsKotlinObjectDef
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import java.time.Instant
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
@ -184,7 +183,6 @@ interface Message {
interface ReceivedMessage : Message {
/** The authenticated sender. */
val peer: X500Name
val peerLegalName: String get() = peer.getRDNs(BCStyle.CN).first().first.value.toString()
}
/** A singleton that's useful for validating topic strings */

View File

@ -2,7 +2,6 @@ package net.corda.core.crypto
import net.corda.core.div
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import org.bouncycastle.asn1.x509.GeneralName
import org.junit.Rule
import org.junit.Test
@ -249,8 +248,7 @@ class X509UtilitiesTest {
val peerChain = clientSocket.session.peerCertificates
val peerX500Principal = (peerChain[0] as X509Certificate).subjectX500Principal
val x500name = X500Name(peerX500Principal.name)
val cn = x500name.getRDNs(BCStyle.CN).first().first.value.toString()
assertEquals("Mega Corp.", cn)
assertEquals("Mega Corp.", x500name.commonName)
val output = DataOutputStream(clientSocket.outputStream)

View File

@ -8,6 +8,7 @@ import com.esotericsoftware.kryo.io.Output
import com.google.common.annotations.VisibleForTesting
import com.google.common.collect.HashMultimap
import net.corda.core.ErrorOr
import net.corda.core.crypto.commonName
import net.corda.core.messaging.RPCOps
import net.corda.core.messaging.RPCReturnsObservables
import net.corda.core.serialization.SerializedBytes
@ -16,14 +17,12 @@ import net.corda.core.serialization.serialize
import net.corda.core.utilities.debug
import net.corda.node.services.RPCUserService
import net.corda.node.services.User
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.messaging.ArtemisMessagingComponent.Companion.NODE_USER
import net.corda.node.utilities.AffinityExecutor
import org.apache.activemq.artemis.api.core.Message
import org.apache.activemq.artemis.api.core.client.ClientConsumer
import org.apache.activemq.artemis.api.core.client.ClientMessage
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import rx.Notification
import rx.Observable
import rx.Subscription
@ -168,7 +167,7 @@ abstract class RPCDispatcher(val ops: RPCOps, val userService: RPCUserService, v
val rpcUser = userService.getUser(validatedUser)
if (rpcUser != null) {
return rpcUser
} else if (X500Name(validatedUser).getRDNs(BCStyle.CN).first().first.value.toString() == nodeLegalName) {
} else if (X500Name(validatedUser).commonName == nodeLegalName) {
return nodeUser
} else {
throw IllegalArgumentException("Validated user '$validatedUser' is not an RPC user nor the NODE user")

View File

@ -12,6 +12,7 @@ import kotlinx.support.jdk8.collections.removeIf
import net.corda.core.ThreadBox
import net.corda.core.abbreviate
import net.corda.core.crypto.Party
import net.corda.core.crypto.commonName
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowStateMachine
import net.corda.core.flows.StateMachineRunId
@ -220,7 +221,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
// isn't required to be unique
// TODO For now have the doorman block signups with identical names, and names with characters that
// are used in X.500 name textual serialisation
val otherParty = serviceHub.networkMapCache.getNodeByLegalName(message.peerLegalName)?.legalIdentity
val otherParty = serviceHub.networkMapCache.getNodeByLegalName(message.peer.commonName)?.legalIdentity
if (otherParty != null) {
onSessionInit(sessionMessage, otherParty)
} else {

View File

@ -1,12 +1,13 @@
package net.corda.node.utilities.certsigning
import net.corda.core.crypto.CertificateStream
import org.apache.commons.io.IOUtils
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import java.io.IOException
import java.net.HttpURLConnection
import java.net.HttpURLConnection.*
import java.net.URL
import java.security.cert.Certificate
import java.security.cert.CertificateFactory
import java.util.*
import java.util.zip.ZipInputStream
@ -24,18 +25,17 @@ class HTTPCertificateSigningService(val server: URL) : CertificateSigningService
conn.requestMethod = "GET"
return when (conn.responseCode) {
HttpURLConnection.HTTP_OK -> conn.inputStream.use {
ZipInputStream(it).use {
val certificates = ArrayList<Certificate>()
while (it.nextEntry != null) {
certificates.add(CertificateFactory.getInstance("X.509").generateCertificate(it))
}
certificates.toTypedArray()
HTTP_OK -> ZipInputStream(conn.inputStream).use {
val certificates = ArrayList<Certificate>()
val stream = CertificateStream(it)
while (it.nextEntry != null) {
certificates.add(stream.nextCertificate())
}
certificates.toTypedArray()
}
HttpURLConnection.HTTP_NO_CONTENT -> null
HttpURLConnection.HTTP_UNAUTHORIZED -> throw IOException("Certificate signing request has been rejected, please contact Corda network administrator for more information.")
else -> throw IOException("Unexpected response code ${conn.responseCode} - ${IOUtils.toString(conn.errorStream)}")
HTTP_NO_CONTENT -> null
HTTP_UNAUTHORIZED -> throw IOException("Certificate signing request has been rejected: ${conn.errorMessage}")
else -> throwUnexpectedResponseCode(conn)
}
}
@ -49,10 +49,15 @@ class HTTPCertificateSigningService(val server: URL) : CertificateSigningService
conn.outputStream.write(request.encoded)
return when (conn.responseCode) {
HttpURLConnection.HTTP_OK -> IOUtils.toString(conn.inputStream)
HttpURLConnection.HTTP_FORBIDDEN -> throw IOException("Client version $clientVersion is forbidden from accessing permissioning server, please upgrade to newer version.")
else -> throw IOException("Unexpected response code ${conn.responseCode} - ${IOUtils.toString(conn.errorStream)}")
HTTP_OK -> IOUtils.toString(conn.inputStream)
HTTP_FORBIDDEN -> throw IOException("Client version $clientVersion is forbidden from accessing permissioning server, please upgrade to newer version.")
else -> throwUnexpectedResponseCode(conn)
}
}
private fun throwUnexpectedResponseCode(connection: HttpURLConnection): Nothing {
throw IOException("Unexpected response code ${connection.responseCode} - ${connection.errorMessage}")
}
private val HttpURLConnection.errorMessage: String get() = IOUtils.toString(errorStream)
}