Merge remote-tracking branch 'open/master' into os-merge-1b37cef

This commit is contained in:
Shams Asari
2018-04-05 17:23:03 +01:00
27 changed files with 198 additions and 109 deletions

View File

@ -15,7 +15,6 @@ import net.corda.core.contracts.ContractAttachment
import net.corda.core.crypto.SecureHash
import net.corda.core.internal.isUploaderTrusted
import net.corda.core.serialization.CordaSerializable
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.FileNotFoundException
import java.io.InputStream
@ -111,12 +110,12 @@ class AttachmentsClassLoader(attachments: List<Attachment>, parent: ClassLoader
if (url.protocol != "attachment") return null
val attachment = idsToAttachments[SecureHash.parse(url.host)] ?: return null
val path = url.path?.substring(1) ?: return null // Chop off the leading slash.
try {
return try {
val stream = ByteArrayOutputStream()
attachment.extractFile(path, stream)
return ByteArrayInputStream(stream.toByteArray())
stream.toByteArray().inputStream()
} catch (e: FileNotFoundException) {
return null
null
}
}
}

View File

@ -18,12 +18,14 @@ import net.corda.core.internal.*
import net.corda.core.utilities.days
import net.corda.core.utilities.millis
import org.bouncycastle.asn1.*
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import org.bouncycastle.asn1.x509.*
import org.bouncycastle.asn1.x509.Extension
import org.bouncycastle.cert.X509CertificateHolder
import org.bouncycastle.cert.X509v3CertificateBuilder
import org.bouncycastle.cert.bc.BcX509ExtensionUtils
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
import org.bouncycastle.operator.ContentSigner
@ -159,18 +161,25 @@ $trustedRoot""", e, certPath, e.index)
/**
* Build a partial X.509 certificate ready for signing.
*
* @param certificateType type of the certificate.
* @param issuer name of the issuing entity.
* @param issuerPublicKey public key of the issuing entity.
* @param subject name of the certificate subject.
* @param subjectPublicKey public key of the certificate subject.
* @param validityWindow the time period the certificate is valid for.
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
* @param crlDistPoint CRL distribution point.
* @param crlIssuer X500Name of the CRL issuer.
*/
fun createPartialCertificate(certificateType: CertificateType,
private fun createPartialCertificate(certificateType: CertificateType,
issuer: X500Principal,
issuerPublicKey: PublicKey,
subject: X500Principal,
subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509v3CertificateBuilder {
nameConstraints: NameConstraints? = null,
crlDistPoint: String? = null,
crlIssuer: X500Name? = null): X509v3CertificateBuilder {
val serial = BigInteger.valueOf(random63BitValue())
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(subjectPublicKey.encoded))
@ -181,10 +190,12 @@ $trustedRoot""", e, certPath, e.index)
.addExtension(Extension.basicConstraints, true, BasicConstraints(certificateType.isCA))
.addExtension(Extension.keyUsage, false, certificateType.keyUsage)
.addExtension(Extension.extendedKeyUsage, false, keyPurposes)
.addExtension(Extension.authorityKeyIdentifier, false, JcaX509ExtensionUtils().createAuthorityKeyIdentifier(issuerPublicKey))
if (role != null) {
builder.addExtension(ASN1ObjectIdentifier(CordaOID.X509_EXTENSION_CORDA_ROLE), false, role)
}
addCrlInfo(builder, crlDistPoint, crlIssuer)
if (nameConstraints != null) {
builder.addExtension(Extension.nameConstraints, true, nameConstraints)
}
@ -195,11 +206,15 @@ $trustedRoot""", e, certPath, e.index)
/**
* Create a X509 v3 certificate using the given issuer certificate and key pair.
*
* @param certificateType type of the certificate.
* @param issuerCertificate The Public certificate of the root CA above this used to sign it.
* @param issuerKeyPair The KeyPair of the root CA above this used to sign it.
* @param subject subject of the generated certificate.
* @param subjectPublicKey subject's public key.
* @param validityWindow The certificate's validity window. Default to [DEFAULT_VALIDITY_WINDOW] if not provided.
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
* @param crlDistPoint CRL distribution point.
* @param crlIssuer X500Name of the CRL issuer.
* @return A data class is returned containing the new intermediate CA Cert and its KeyPair for signing downstream certificates.
* Note the generated certificate tree is capped at max depth of 1 below this to be in line with commercially available certificates.
*/
@ -210,7 +225,9 @@ $trustedRoot""", e, certPath, e.index)
subject: X500Principal,
subjectPublicKey: PublicKey,
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
nameConstraints: NameConstraints? = null): X509Certificate {
nameConstraints: NameConstraints? = null,
crlDistPoint: String? = null,
crlIssuer: X500Name? = null): X509Certificate {
val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second, issuerCertificate)
return createCertificate(
certificateType,
@ -219,28 +236,36 @@ $trustedRoot""", e, certPath, e.index)
subject,
subjectPublicKey,
window,
nameConstraints
nameConstraints,
crlDistPoint,
crlIssuer
)
}
/**
* Build and sign an X.509 certificate with the given signer.
*
* @param certificateType type of the certificate.
* @param issuer name of the issuing entity.
* @param issuerSigner content signer to sign the certificate with.
* @param subject name of the certificate subject.
* @param subjectPublicKey public key of the certificate subject.
* @param validityWindow the time period the certificate is valid for.
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
* @param crlDistPoint CRL distribution point.
* @param crlIssuer X500Name of the CRL issuer.
*/
fun createCertificate(certificateType: CertificateType,
issuer: X500Principal,
issuerPublicKey: PublicKey,
issuerSigner: ContentSigner,
subject: X500Principal,
subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509Certificate {
val builder = createPartialCertificate(certificateType, issuer, subject, subjectPublicKey, validityWindow, nameConstraints)
nameConstraints: NameConstraints? = null,
crlDistPoint: String? = null,
crlIssuer: X500Name? = null): X509Certificate {
val builder = createPartialCertificate(certificateType, issuer, issuerPublicKey, subject, subjectPublicKey, validityWindow, nameConstraints, crlDistPoint, crlIssuer)
return builder.build(issuerSigner).run {
require(isValidOn(Date()))
toJca()
@ -250,6 +275,7 @@ $trustedRoot""", e, certPath, e.index)
/**
* Build and sign an X.509 certificate with CA cert private key.
*
* @param certificateType type of the certificate.
* @param issuer name of the issuing entity.
* @param issuerKeyPair the public & private key to sign the certificate with.
* @param subject name of the certificate subject.
@ -263,11 +289,21 @@ $trustedRoot""", e, certPath, e.index)
subject: X500Principal,
subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509Certificate {
nameConstraints: NameConstraints? = null,
crlDistPoint: String? = null,
crlIssuer: X500Name? = null): X509Certificate {
val signatureScheme = Crypto.findSignatureScheme(issuerKeyPair.private)
val provider = Crypto.findProvider(signatureScheme.providerName)
val signer = ContentSignerBuilder.build(signatureScheme, issuerKeyPair.private, provider)
val builder = createPartialCertificate(certificateType, issuer, subject, subjectPublicKey, validityWindow, nameConstraints)
val builder = createPartialCertificate(
certificateType,
issuer,
issuerKeyPair.public,
subject, subjectPublicKey,
validityWindow,
nameConstraints,
crlDistPoint,
crlIssuer)
return builder.build(signer).run {
require(isValidOn(Date()))
require(isSignatureValid(JcaContentVerifierProviderBuilder().build(issuerKeyPair.public)))
@ -312,6 +348,21 @@ $trustedRoot""", e, certPath, e.index)
fun buildCertPath(certificates: List<X509Certificate>): CertPath {
return X509CertificateFactory().generateCertPath(certificates)
}
private fun addCrlInfo(builder: X509v3CertificateBuilder, crlDistPoint: String?, crlIssuer: X500Name?) {
if (crlDistPoint != null) {
val distPointName = DistributionPointName(GeneralNames(GeneralName(GeneralName.uniformResourceIdentifier, crlDistPoint)))
val crlIssuerGeneralNames = crlIssuer?.let {
GeneralNames(GeneralName(crlIssuer))
}
// The second argument is flag that allows you to define what reason of certificate revocation is served by this distribution point see [ReasonFlags].
// The idea is that you have different revocation per revocation reason. Since we won't go into such a granularity, we can skip that parameter.
// The third argument allows you to specify the name of the CRL issuer, it needs to be consistent with the crl (IssuingDistributionPoint) extension and the idp argument.
// If idp == true, set it, if idp == false, leave it null as done here.
val distPoint = DistributionPoint(distPointName, null, crlIssuerGeneralNames)
builder.addExtension(Extension.cRLDistributionPoints, false, CRLDistPoint(arrayOf(distPoint)))
}
}
}
// Assuming cert type to role is 1:1

View File

@ -10,12 +10,8 @@
package net.corda.nodeapi.internal.network
import com.google.common.hash.Hashing
import com.google.common.hash.HashingInputStream
import com.typesafe.config.ConfigFactory
import net.corda.cordform.CordformNode
import net.corda.core.contracts.ContractClassName
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SecureHash.Companion.parse
import net.corda.core.identity.Party
import net.corda.core.internal.*
@ -37,7 +33,6 @@ import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
import net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme
import net.corda.nodeapi.internal.serialization.kryo.kryoMagic
import java.io.File
import java.io.PrintStream
import java.nio.file.Files
import java.nio.file.Path
@ -201,7 +196,7 @@ class NetworkBootstrapper {
private fun generateWhitelist(whitelistFile: Path, excludeWhitelistFile: Path, cordapps: List<String>?): Map<String, List<AttachmentId>> {
val existingWhitelist = if (whitelistFile.exists()) readContractWhitelist(whitelistFile) else emptyMap()
println(if (existingWhitelist.isEmpty()) "No existing whitelist file found." else "Found existing whitelist: ${whitelistFile}")
println(if (existingWhitelist.isEmpty()) "No existing whitelist file found." else "Found existing whitelist: $whitelistFile")
val excludeContracts = if (excludeWhitelistFile.exists()) readExcludeWhitelist(excludeWhitelistFile) else emptyList()
if (excludeContracts.isNotEmpty()) {
@ -209,7 +204,7 @@ class NetworkBootstrapper {
}
val newWhiteList = cordapps?.flatMap { cordappJarPath ->
val jarHash = getJarHash(cordappJarPath)
val jarHash = Paths.get(cordappJarPath).hash
scanJarForContracts(cordappJarPath).map { contract ->
contract to jarHash
}
@ -223,30 +218,26 @@ class NetworkBootstrapper {
contractClassName to (if (newHash == null || newHash in existing) existing else existing + newHash)
}.toMap()
println("CorDapp whitelist " + (if (existingWhitelist.isEmpty()) "generated" else "updated") + " in ${whitelistFile}")
println("CorDapp whitelist " + (if (existingWhitelist.isEmpty()) "generated" else "updated") + " in $whitelistFile")
return merged
}
private fun overwriteWhitelist(whitelistFile: Path, mergedWhiteList: Map<String, List<AttachmentId>>) {
PrintStream(whitelistFile.toFile().outputStream()).use { out ->
mergedWhiteList.forEach { (contract, attachments) ->
out.println("${contract}:${attachments.joinToString(",")}")
out.println("$contract:${attachments.joinToString(",")}")
}
}
}
private fun getJarHash(cordappPath: String): AttachmentId = File(cordappPath).inputStream().use { jar ->
val hs = HashingInputStream(Hashing.sha256(), jar)
hs.readBytes()
SecureHash.SHA256(hs.hash().asBytes())
private fun readContractWhitelist(file: Path): Map<String, List<AttachmentId>> {
return file.readAllLines()
.map { line -> line.split(":") }
.map { (contract, attachmentIds) ->
contract to (attachmentIds.split(",").map(::parse))
}.toMap()
}
private fun readContractWhitelist(file: Path): Map<String, List<AttachmentId>> = file.readAllLines()
.map { line -> line.split(":") }
.map { (contract, attachmentIds) ->
contract to (attachmentIds.split(",").map(::parse))
}.toMap()
private fun readExcludeWhitelist(file: Path): List<String> = file.readAllLines().map(String::trim)
private fun NotaryInfo.prettyPrint(): String = "${identity.name} (${if (validating) "" else "non-"}validating)"

View File

@ -13,6 +13,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.contracts.Attachment
import net.corda.core.contracts.ContractAttachment
import net.corda.core.contracts.ContractClassName
import net.corda.core.internal.readFully
import net.corda.core.serialization.MissingAttachmentsException
import net.corda.nodeapi.internal.serialization.GeneratedAttachment
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
@ -27,7 +28,7 @@ class ContractAttachmentSerializer(factory: SerializerFactory) : CustomSerialize
ContractAttachmentProxy::class.java, factory) {
override fun toProxy(obj: ContractAttachment): ContractAttachmentProxy {
val bytes = try {
obj.attachment.open().readBytes()
obj.attachment.open().readFully()
} catch (e: Exception) {
throw MissingAttachmentsException(listOf(obj.id))
}

View File

@ -46,6 +46,6 @@ object InputStreamSerializer : CustomSerializer.Implements<InputStream>(InputStr
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): InputStream {
val bits = input.readObject(obj, schemas, ByteArray::class.java) as ByteArray
return ByteArrayInputStream(bits)
return bits.inputStream()
}
}

View File

@ -28,6 +28,7 @@ import net.corda.core.crypto.CompositeKey
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.AbstractAttachment
import net.corda.core.internal.readFully
import net.corda.core.serialization.MissingAttachmentsException
import net.corda.core.serialization.SerializationWhitelist
import net.corda.core.serialization.SerializeAsToken
@ -233,7 +234,7 @@ object DefaultKryoCustomizer {
val lazyAttachment = object : AbstractAttachment({
val attachment = attachmentStorage.openAttachment(attachmentHash)
?: throw MissingAttachmentsException(listOf(attachmentHash))
attachment.open().readBytes()
attachment.open().readFully()
}) {
override val id = attachmentHash
}

View File

@ -39,7 +39,6 @@ import net.corda.nodeapi.internal.serialization.serializationContextKey
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import rx.Observable
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.lang.reflect.InvocationTargetException
import java.security.PrivateKey
@ -222,7 +221,7 @@ object InputStreamSerializer : Serializer<InputStream>() {
System.arraycopy(chunk, 0, flattened, offset, chunk.size)
offset += chunk.size
}
return ByteArrayInputStream(flattened)
return flattened.inputStream()
}
}

View File

@ -76,5 +76,5 @@ internal fun Output.substitute(transform: (OutputStream) -> OutputStream) {
}
internal fun Input.substitute(transform: (InputStream) -> InputStream) {
inputStream = transform(SequenceInputStream(ByteArrayInputStream(buffer.copyOfRange(position(), limit())), inputStream))
inputStream = transform(SequenceInputStream(buffer.copyOfRange(position(), limit()).inputStream(), inputStream))
}

View File

@ -12,7 +12,8 @@ package net.corda.nodeapi.internal
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.*
import net.corda.core.contracts.Attachment
import net.corda.core.contracts.Contract
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.declaredField
@ -32,9 +33,9 @@ import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.TestIdentity
import net.corda.testing.internal.MockCordappConfigProvider
import net.corda.testing.internal.kryoSpecific
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.MockCordappConfigProvider
import net.corda.testing.services.MockAttachmentStorage
import org.apache.commons.io.IOUtils
import org.junit.Assert.*
@ -137,8 +138,8 @@ class AttachmentsClassLoaderTests {
fun `test overlapping file exception`() {
val storage = attachments
val att0 = attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some other data")))
val att1 = storage.importAttachment(fakeAttachment("file.txt", "some data").inputStream())
val att2 = storage.importAttachment(fakeAttachment("file.txt", "some other data").inputStream())
assertFailsWith(AttachmentsClassLoader.OverlappingAttachments::class) {
AttachmentsClassLoader(arrayOf(att0, att1, att2).map { storage.openAttachment(it)!! })
@ -149,8 +150,8 @@ class AttachmentsClassLoaderTests {
fun `basic`() {
val storage = attachments
val att0 = attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
val att1 = storage.importAttachment(fakeAttachment("file1.txt", "some data").inputStream())
val att2 = storage.importAttachment(fakeAttachment("file2.txt", "some other data").inputStream())
val cl = AttachmentsClassLoader(arrayOf(att0, att1, att2).map { storage.openAttachment(it)!! })
val txt = IOUtils.toString(cl.getResourceAsStream("file1.txt"), Charsets.UTF_8.name())
@ -161,8 +162,8 @@ class AttachmentsClassLoaderTests {
fun `Check platform independent path handling in attachment jars`() {
val storage = MockAttachmentStorage()
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("/folder1/foldera/file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("\\folder1\\folderb\\file2.txt", "some other data")))
val att1 = storage.importAttachment(fakeAttachment("/folder1/foldera/file1.txt", "some data").inputStream())
val att2 = storage.importAttachment(fakeAttachment("\\folder1\\folderb\\file2.txt", "some other data").inputStream())
val data1a = readAttachment(storage.openAttachment(att1)!!, "/folder1/foldera/file1.txt")
assertArrayEquals("some data".toByteArray(), data1a)
@ -181,8 +182,8 @@ class AttachmentsClassLoaderTests {
fun `loading class AnotherDummyContract`() {
val storage = attachments
val att0 = attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
val att1 = storage.importAttachment(fakeAttachment("file1.txt", "some data").inputStream())
val att2 = storage.importAttachment(fakeAttachment("file2.txt", "some other data").inputStream())
val cl = AttachmentsClassLoader(arrayOf(att0, att1, att2).map { storage.openAttachment(it)!! }, FilteringClassLoader)
val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, cl)
@ -205,8 +206,8 @@ class AttachmentsClassLoaderTests {
val bytes = contract.serialize()
val storage = attachments
val att0 = attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
val att1 = storage.importAttachment(fakeAttachment("file1.txt", "some data").inputStream())
val att2 = storage.importAttachment(fakeAttachment("file2.txt", "some other data").inputStream())
val cl = AttachmentsClassLoader(arrayOf(att0, att1, att2).map { storage.openAttachment(it)!! }, FilteringClassLoader)
@ -231,8 +232,8 @@ class AttachmentsClassLoaderTests {
val bytes = data.serialize(context = context2)
val storage = attachments
val att0 = attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
val att1 = storage.importAttachment(fakeAttachment("file1.txt", "some data").inputStream())
val att2 = storage.importAttachment(fakeAttachment("file2.txt", "some other data").inputStream())
val cl = AttachmentsClassLoader(arrayOf(att0, att1, att2).map { storage.openAttachment(it)!! }, FilteringClassLoader)

View File

@ -30,9 +30,7 @@ import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.TestIdentity
import net.corda.testing.internal.createDevIntermediateCaCertPath
import org.assertj.core.api.Assertions.assertThat
import org.bouncycastle.asn1.x509.BasicConstraints
import org.bouncycastle.asn1.x509.Extension
import org.bouncycastle.asn1.x509.KeyUsage
import org.bouncycastle.asn1.x509.*
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
@ -113,6 +111,28 @@ class X509UtilitiesTest {
}
}
@Test
fun `create valid server certificate chain includes CRL info`() {
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val caCert = X509Utilities.createSelfSignedCACertificate(X500Principal("CN=Test CA Cert,O=R3 Ltd,L=London,C=GB"), caKey)
val caSubjectKeyIdentifier = SubjectKeyIdentifier.getInstance(caCert.toBc().getExtension(Extension.subjectKeyIdentifier).parsedValue)
val keyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val crlDistPoint = "http://test.com"
val serverCert = X509Utilities.createCertificate(
CertificateType.TLS,
caCert,
caKey,
X500Principal("CN=Server Cert,O=R3 Ltd,L=London,C=GB"),
keyPair.public,
crlDistPoint = crlDistPoint)
serverCert.toBc().run {
val certCrlDistPoint = CRLDistPoint.getInstance(getExtension(Extension.cRLDistributionPoints).parsedValue)
assertTrue(certCrlDistPoint.distributionPoints.first().distributionPoint.toString().contains(crlDistPoint))
val certCaAuthorityKeyIdentifier = AuthorityKeyIdentifier.getInstance(getExtension(Extension.authorityKeyIdentifier).parsedValue)
assertTrue(Arrays.equals(caSubjectKeyIdentifier.keyIdentifier, certCaAuthorityKeyIdentifier.keyIdentifier))
}
}
@Test
fun `storing EdDSA key in java keystore`() {
val tmpKeyStore = tempFile("keystore.jks")

View File

@ -53,7 +53,6 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters
import java.io.ByteArrayInputStream
import java.io.IOException
import java.io.NotSerializableException
import java.math.BigDecimal
@ -1093,9 +1092,9 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.InputStreamSerializer)
val bytes = ByteArray(10) { it.toByte() }
val obj = ByteArrayInputStream(bytes)
val obj = bytes.inputStream()
val obj2 = serdes(obj, factory, factory2, expectedEqual = false, expectDeserializedEqual = false)
val obj3 = ByteArrayInputStream(bytes) // Can't use original since the stream pointer has moved.
val obj3 = bytes.inputStream() // Can't use original since the stream pointer has moved.
assertEquals(obj3.available(), obj2.available())
assertEquals(obj3.read(), obj2.read())
}

View File

@ -39,7 +39,6 @@ import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters
import org.slf4j.LoggerFactory
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.time.Instant
import java.util.*
@ -200,7 +199,11 @@ class KryoTests(private val compression: CordaSerializationEncoding?) {
@Test
fun `HashCheckingStream (de)serialize`() {
val rubbish = ByteArray(12345, { (it * it * 0.12345).toByte() })
val readRubbishStream: InputStream = NodeAttachmentService.HashCheckingStream(SecureHash.sha256(rubbish), rubbish.size, ByteArrayInputStream(rubbish)).serialize(factory, context).deserialize(factory, context)
val readRubbishStream: InputStream = NodeAttachmentService.HashCheckingStream(
SecureHash.sha256(rubbish),
rubbish.size,
rubbish.inputStream()
).serialize(factory, context).deserialize(factory, context)
for (i in 0..12344) {
assertEquals(rubbish[i], readRubbishStream.read().toByte())
}