mirror of
https://github.com/corda/corda.git
synced 2024-12-20 21:43:14 +00:00
Add PartyAndCertificate class
Add PartyAndCertificate class for pairing proof of a party's identity with the party.
This commit is contained in:
parent
b6dbd6bbb5
commit
0e1e4042dc
@ -18,6 +18,15 @@ abstract class AbstractParty(val owningKey: PublicKey) {
|
||||
override fun hashCode(): Int = owningKey.hashCode()
|
||||
abstract fun nameOrNull(): X500Name?
|
||||
|
||||
/**
|
||||
* Build a reference to something being stored or issued by a party e.g. in a vault or (more likely) on their normal
|
||||
* ledger.
|
||||
*/
|
||||
abstract fun ref(bytes: OpaqueBytes): PartyAndReference
|
||||
|
||||
/**
|
||||
* Build a reference to something being stored or issued by a party e.g. in a vault or (more likely) on their normal
|
||||
* ledger.
|
||||
*/
|
||||
fun ref(vararg bytes: Byte) = ref(OpaqueBytes.of(*bytes))
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package net.corda.core.identity
|
||||
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
/**
|
||||
* A full party plus the X.509 certificate and path linking the party back to a trust root.
|
||||
*/
|
||||
class PartyAndCertificate(name: X500Name, owningKey: PublicKey,
|
||||
val certificate: X509CertificateHolder,
|
||||
val certPath: CertPath) : Party(name, owningKey)
|
@ -3,7 +3,7 @@
|
||||
package net.corda.core.utilities
|
||||
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import java.math.BigInteger
|
||||
import java.security.KeyPair
|
||||
@ -21,36 +21,52 @@ val DUMMY_KEY_2: KeyPair by lazy { generateKeyPair() }
|
||||
|
||||
val DUMMY_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(20)) }
|
||||
/** Dummy notary identity for tests and simulations */
|
||||
val DUMMY_NOTARY: Party get() = Party(X500Name("CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"), DUMMY_NOTARY_KEY.public)
|
||||
val DUMMY_NOTARY: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"), DUMMY_NOTARY_KEY.public)
|
||||
|
||||
val DUMMY_MAP_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(30)) }
|
||||
/** Dummy network map service identity for tests and simulations */
|
||||
val DUMMY_MAP: Party get() = Party(X500Name("CN=Network Map Service,O=R3,OU=corda,L=Amsterdam,C=NL"), DUMMY_MAP_KEY.public)
|
||||
val DUMMY_MAP: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Network Map Service,O=R3,OU=corda,L=Amsterdam,C=NL"), DUMMY_MAP_KEY.public)
|
||||
|
||||
val DUMMY_BANK_A_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(40)) }
|
||||
/** Dummy bank identity for tests and simulations */
|
||||
val DUMMY_BANK_A: Party get() = Party(X500Name("CN=Bank A,O=Bank A,L=London,C=UK"), DUMMY_BANK_A_KEY.public)
|
||||
val DUMMY_BANK_A: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Bank A,O=Bank A,L=London,C=UK"), DUMMY_BANK_A_KEY.public)
|
||||
|
||||
val DUMMY_BANK_B_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(50)) }
|
||||
/** Dummy bank identity for tests and simulations */
|
||||
val DUMMY_BANK_B: Party get() = Party(X500Name("CN=Bank B,O=Bank B,L=New York,C=US"), DUMMY_BANK_B_KEY.public)
|
||||
val DUMMY_BANK_B: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Bank B,O=Bank B,L=New York,C=US"), DUMMY_BANK_B_KEY.public)
|
||||
|
||||
val DUMMY_BANK_C_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(60)) }
|
||||
/** Dummy bank identity for tests and simulations */
|
||||
val DUMMY_BANK_C: Party get() = Party(X500Name("CN=Bank C,O=Bank C,L=Tokyo,C=JP"), DUMMY_BANK_C_KEY.public)
|
||||
val DUMMY_BANK_C: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Bank C,O=Bank C,L=Tokyo,C=JP"), DUMMY_BANK_C_KEY.public)
|
||||
|
||||
val ALICE_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(70)) }
|
||||
/** Dummy individual identity for tests and simulations */
|
||||
val ALICE: Party get() = Party(X500Name("CN=Alice Corp,O=Alice Corp,L=London,C=UK"), ALICE_KEY.public)
|
||||
val ALICE: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Alice Corp,O=Alice Corp,L=London,C=UK"), ALICE_KEY.public)
|
||||
|
||||
val BOB_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(80)) }
|
||||
/** Dummy individual identity for tests and simulations */
|
||||
val BOB: Party get() = Party(X500Name("CN=Bob Plc,O=Bob Plc,L=London,C=UK"), BOB_KEY.public)
|
||||
val BOB: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Bob Plc,O=Bob Plc,L=London,C=UK"), BOB_KEY.public)
|
||||
|
||||
val CHARLIE_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(90)) }
|
||||
/** Dummy individual identity for tests and simulations */
|
||||
val CHARLIE: Party get() = Party(X500Name("CN=Charlie Ltd,O=Charlie Ltd,L=London,C=UK"), CHARLIE_KEY.public)
|
||||
val CHARLIE: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Charlie Ltd,O=Charlie Ltd,L=London,C=UK"), CHARLIE_KEY.public)
|
||||
|
||||
val DUMMY_REGULATOR_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(100)) }
|
||||
/** Dummy regulator for tests and simulations */
|
||||
val DUMMY_REGULATOR: Party get() = Party(X500Name("CN=Regulator A,OU=Corda,O=AMF,L=Paris,C=FR"), DUMMY_REGULATOR_KEY.public)
|
||||
val DUMMY_REGULATOR: PartyAndCertificate get() = getTestPartyAndCertificate(X500Name("CN=Regulator A,OU=Corda,O=AMF,L=Paris,C=FR"), DUMMY_REGULATOR_KEY.public)
|
||||
|
||||
val DUMMY_CA_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(110)) }
|
||||
val DUMMY_CA: CertificateAndKeyPair by lazy {
|
||||
// TODO: Should be identity scheme
|
||||
val cert = X509Utilities.createSelfSignedCACertificate(X500Name("CN=Dummy CA,OU=Corda,O=R3 Ltd,L=London,C=UK"), DUMMY_CA_KEY)
|
||||
CertificateAndKeyPair(cert, DUMMY_CA_KEY)
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a test party with a nonsense certificate authority for testing purposes.
|
||||
*/
|
||||
fun getTestPartyAndCertificate(name: X500Name, publicKey: PublicKey): PartyAndCertificate {
|
||||
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, DUMMY_CA.certificate, DUMMY_CA.keyPair, name, publicKey)
|
||||
val certPath = X509Utilities.createCertificatePath(DUMMY_CA.certificate, cert, revocationEnabled = false)
|
||||
return PartyAndCertificate(name, publicKey, cert, certPath)
|
||||
}
|
@ -3,11 +3,12 @@ package net.corda.node.utilities
|
||||
import co.paralleluniverse.strands.Strand
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.parsePublicKeyBase58
|
||||
import net.corda.core.crypto.toBase58String
|
||||
import net.corda.node.utilities.StrandLocalTransactionManager.Boundary
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.h2.jdbc.JdbcBlob
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.transactions.TransactionInterface
|
||||
import org.jetbrains.exposed.sql.transactions.TransactionManager
|
||||
@ -16,8 +17,12 @@ import rx.Subscriber
|
||||
import rx.subjects.PublishSubject
|
||||
import rx.subjects.Subject
|
||||
import rx.subjects.UnicastSubject
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.Closeable
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509Certificate
|
||||
import java.sql.Connection
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
@ -264,15 +269,25 @@ fun <T : Any> rx.Observable<T>.wrapWithDatabaseTransaction(db: Database? = null)
|
||||
|
||||
// Composite columns for use with below Exposed helpers.
|
||||
data class PartyColumns(val name: Column<String>, val owningKey: Column<PublicKey>)
|
||||
data class PartyAndCertificateColumns(val name: Column<String>, val owningKey: Column<PublicKey>,
|
||||
val certificate: Column<X509CertificateHolder>, val certPath: Column<CertPath>)
|
||||
data class StateRefColumns(val txId: Column<SecureHash>, val index: Column<Int>)
|
||||
data class TxnNoteColumns(val txId: Column<SecureHash>, val note: Column<String>)
|
||||
|
||||
/**
|
||||
* [Table] column helpers for use with Exposed, as per [varchar] etc.
|
||||
*/
|
||||
fun Table.certificate(name: String) = this.registerColumn<X509CertificateHolder>(name, X509CertificateColumnType)
|
||||
fun Table.certificatePath(name: String) = this.registerColumn<CertPath>(name, CertPathColumnType)
|
||||
fun Table.publicKey(name: String) = this.registerColumn<PublicKey>(name, PublicKeyColumnType)
|
||||
fun Table.secureHash(name: String) = this.registerColumn<SecureHash>(name, SecureHashColumnType)
|
||||
fun Table.party(nameColumnName: String, keyColumnName: String) = PartyColumns(this.varchar(nameColumnName, length = 255), this.publicKey(keyColumnName))
|
||||
fun Table.party(nameColumnName: String,
|
||||
keyColumnName: String) = PartyColumns(this.varchar(nameColumnName, length = 255), this.publicKey(keyColumnName))
|
||||
fun Table.partyAndCertificate(nameColumnName: String,
|
||||
keyColumnName: String,
|
||||
certificateColumnName: String,
|
||||
pathColumnName: String) = PartyAndCertificateColumns(this.varchar(nameColumnName, length = 255), this.publicKey(keyColumnName),
|
||||
this.certificate(certificateColumnName), this.certificatePath(pathColumnName))
|
||||
fun Table.uuidString(name: String) = this.registerColumn<UUID>(name, UUIDStringColumnType)
|
||||
fun Table.localDate(name: String) = this.registerColumn<LocalDate>(name, LocalDateColumnType)
|
||||
fun Table.localDateTime(name: String) = this.registerColumn<LocalDateTime>(name, LocalDateTimeColumnType)
|
||||
@ -280,6 +295,35 @@ fun Table.instant(name: String) = this.registerColumn<Instant>(name, InstantColu
|
||||
fun Table.stateRef(txIdColumnName: String, indexColumnName: String) = StateRefColumns(this.secureHash(txIdColumnName), this.integer(indexColumnName))
|
||||
fun Table.txnNote(txIdColumnName: String, txnNoteColumnName: String) = TxnNoteColumns(this.secureHash(txIdColumnName), this.text(txnNoteColumnName))
|
||||
|
||||
/**
|
||||
* [ColumnType] for marshalling to/from database on behalf of [X509CertificateHolder].
|
||||
*/
|
||||
object X509CertificateColumnType : ColumnType() {
|
||||
override fun sqlType(): String = "BLOB"
|
||||
|
||||
override fun valueFromDB(value: Any): Any {
|
||||
val blob = value as JdbcBlob
|
||||
return X509CertificateHolder(blob.getBytes(0, blob.length().toInt()))
|
||||
}
|
||||
|
||||
override fun notNullValueToDB(value: Any): Any = (value as X509CertificateHolder).encoded
|
||||
}
|
||||
|
||||
/**
|
||||
* [ColumnType] for marshalling to/from database on behalf of [CertPath].
|
||||
*/
|
||||
object CertPathColumnType : ColumnType() {
|
||||
private val factory = CertificateFactory.getInstance("X.509")
|
||||
override fun sqlType(): String = "BLOB"
|
||||
|
||||
override fun valueFromDB(value: Any): Any {
|
||||
val blob = value as JdbcBlob
|
||||
return factory.generateCertPath(ByteArrayInputStream(blob.getBytes(0, blob.length().toInt())))
|
||||
}
|
||||
|
||||
override fun notNullValueToDB(value: Any): Any = (value as CertPath).encoded
|
||||
}
|
||||
|
||||
/**
|
||||
* [ColumnType] for marshalling to/from database on behalf of [PublicKey].
|
||||
*/
|
||||
|
@ -24,13 +24,13 @@ class InMemoryIdentityServiceTests {
|
||||
val service = InMemoryIdentityService()
|
||||
assertNull(service.getAllIdentities().firstOrNull())
|
||||
service.registerIdentity(ALICE)
|
||||
var expected = setOf(ALICE)
|
||||
var expected = setOf<Party>(ALICE)
|
||||
var actual = service.getAllIdentities().toHashSet()
|
||||
assertEquals(expected, actual)
|
||||
|
||||
// Add a second party and check we get both back
|
||||
service.registerIdentity(BOB)
|
||||
expected = setOf(ALICE, BOB)
|
||||
expected = setOf<Party>(ALICE, BOB)
|
||||
actual = service.getAllIdentities().toHashSet()
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -1,24 +1,26 @@
|
||||
package net.corda.testing.node
|
||||
|
||||
import co.paralleluniverse.common.util.VisibleForTesting
|
||||
import net.corda.core.crypto.DummyPublicKey
|
||||
import net.corda.core.crypto.entropyToKeyPair
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.utilities.getTestPartyAndCertificate
|
||||
import net.corda.node.services.network.InMemoryNetworkMapCache
|
||||
import net.corda.testing.MOCK_VERSION_INFO
|
||||
import net.corda.testing.getTestX509Name
|
||||
import rx.Observable
|
||||
import rx.subjects.PublishSubject
|
||||
import java.math.BigInteger
|
||||
|
||||
/**
|
||||
* Network map cache with no backing map service.
|
||||
*/
|
||||
class MockNetworkMapCache : InMemoryNetworkMapCache() {
|
||||
private companion object {
|
||||
val BANK_C = Party(getTestX509Name("Bank C"), DummyPublicKey("Bank C"))
|
||||
val BANK_D = Party(getTestX509Name("Bank D"), DummyPublicKey("Bank D"))
|
||||
val BANK_C = getTestPartyAndCertificate(getTestX509Name("Bank C"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
|
||||
val BANK_D = getTestPartyAndCertificate(getTestX509Name("Bank D"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
|
||||
}
|
||||
|
||||
override val changed: Observable<NetworkMapCache.MapChange> = PublishSubject.create<NetworkMapCache.MapChange>()
|
||||
|
Loading…
Reference in New Issue
Block a user