Fix toHexByteArray

Add tests.
This commit is contained in:
Raffaele Mignone 2020-06-24 21:56:07 +02:00
parent df4f48122f
commit fc07abc894
Signed by: norangebit
GPG Key ID: F5255658CB220573
13 changed files with 303 additions and 5 deletions

View File

@ -15,8 +15,11 @@ repositories {
dependencies { dependencies {
implementation(kotlin("stdlib-jdk8")) implementation(kotlin("stdlib-jdk8"))
testCompile("junit", "junit", "4.12")
implementation ("cafe.cryptography:ed25519-elisabeth:0.1.0") implementation ("cafe.cryptography:ed25519-elisabeth:0.1.0")
testCompile("junit", "junit", "4.12")
testImplementation ("org.amshove.kluent:kluent:1.61")
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.9.1") detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.9.1")
} }

View File

@ -1,6 +1,5 @@
package it.unisannio.assd.tkn package it.unisannio.assd.tkn
import java.math.BigInteger
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
@ -21,7 +20,15 @@ fun ByteArray.toHexString(): String {
return builder.toString() return builder.toString()
} }
fun String.toHexByteArray(): ByteArray = BigInteger(this, 16).toByteArray() fun String.toHexByteArray(): ByteArray {
val b = ByteArray(this.length / 2)
for (i in b.indices) {
val index = i * 2
val v: Int = this.substring(index, index + 2).toInt(16)
b[i] = v.toByte()
}
return b
}
fun ByteBuffer.read(n: Int): ByteArray { fun ByteBuffer.read(n: Int): ByteArray {
val bytes = ByteArray(n) val bytes = ByteArray(n)

View File

@ -4,6 +4,7 @@ import cafe.cryptography.ed25519.Ed25519PrivateKey
import cafe.cryptography.ed25519.Ed25519PublicKey import cafe.cryptography.ed25519.Ed25519PublicKey
import it.unisannio.assd.tkn.Const import it.unisannio.assd.tkn.Const
import it.unisannio.assd.tkn.toHexByteArray import it.unisannio.assd.tkn.toHexByteArray
import it.unisannio.assd.tkn.toHexString
import java.security.MessageDigest import java.security.MessageDigest
import java.security.SecureRandom import java.security.SecureRandom
@ -32,6 +33,8 @@ class ReportAuthorizationKey private constructor(private val key: Ed25519Private
fun toByteArray(): ByteArray = key.toByteArray() fun toByteArray(): ByteArray = key.toByteArray()
fun toHexString() = toByteArray().toHexString()
companion object { companion object {
fun createFromByteArray(bytes: ByteArray): ReportAuthorizationKey = fun createFromByteArray(bytes: ByteArray): ReportAuthorizationKey =
ReportAuthorizationKey( ReportAuthorizationKey(

View File

@ -3,6 +3,7 @@ package it.unisannio.assd.tkn.key
import cafe.cryptography.ed25519.Ed25519PrivateKey import cafe.cryptography.ed25519.Ed25519PrivateKey
import cafe.cryptography.ed25519.Ed25519PublicKey import cafe.cryptography.ed25519.Ed25519PublicKey
import cafe.cryptography.ed25519.Ed25519Signature import cafe.cryptography.ed25519.Ed25519Signature
import it.unisannio.assd.tkn.toHexByteArray
import it.unisannio.assd.tkn.toHexString import it.unisannio.assd.tkn.toHexString
class ReportVerificationKey private constructor(private val key: Ed25519PublicKey) { class ReportVerificationKey private constructor(private val key: Ed25519PublicKey) {
@ -32,5 +33,10 @@ class ReportVerificationKey private constructor(private val key: Ed25519PublicKe
ReportVerificationKey( ReportVerificationKey(
Ed25519PublicKey.fromByteArray(bytes) Ed25519PublicKey.fromByteArray(bytes)
) )
fun createFromHexString(hexString: String): ReportVerificationKey =
ReportVerificationKey(
Ed25519PublicKey.fromByteArray(hexString.toHexByteArray())
)
} }
} }

View File

@ -3,6 +3,7 @@ package it.unisannio.assd.tkn.key
import it.unisannio.assd.tkn.Const import it.unisannio.assd.tkn.Const
import it.unisannio.assd.tkn.report.Memo import it.unisannio.assd.tkn.report.Memo
import it.unisannio.assd.tkn.report.Report import it.unisannio.assd.tkn.report.Report
import it.unisannio.assd.tkn.toHexByteArray
import it.unisannio.assd.tkn.toHexString import it.unisannio.assd.tkn.toHexString
import it.unisannio.assd.tkn.toLeByteArray import it.unisannio.assd.tkn.toLeByteArray
import java.security.MessageDigest import java.security.MessageDigest
@ -71,5 +72,11 @@ class TemporaryContactKey private constructor(
bytes, bytes,
index index
) )
fun createFromHexString(hexString: String, index: Short): TemporaryContactKey =
TemporaryContactKey(
hexString.toHexByteArray(),
index
)
} }
} }

View File

@ -2,7 +2,7 @@ package it.unisannio.assd.tkn.key
import it.unisannio.assd.tkn.toHexString import it.unisannio.assd.tkn.toHexString
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.* import java.util.UUID
class TemporaryContactNumber( class TemporaryContactNumber(
private val number: ByteArray, private val number: ByteArray,

View File

@ -8,7 +8,7 @@ import java.nio.ByteOrder
class SignedReport private constructor( class SignedReport private constructor(
val report: Report, val report: Report,
private val sign: ByteArray val sign: ByteArray
) { ) {
fun verify(): Boolean = report.getVerificationKey() fun verify(): Boolean = report.getVerificationKey()
.verify(report.toByteArray(), sign) .verify(report.toByteArray(), sign)

View File

@ -0,0 +1,20 @@
package it.unisannio.assd.tkn
/**
* These data were derived from the TCN project test vector.
* For more information see https://github.com/TCNCoalition/TCN#reporting.
*/
object TestConst {
const val PRIVATE_KEY_STRING_HEX = "577cfdae21fee71579211ab02c418ee0948bacab613cf69d0a4a5ae5a1557dbb"
const val PUBLIC_KEY_STRING_HEX = "fd8deb9d91a13e144ca5b0ce14e289532e040fe0bf922c6e3dadb1e4e2333c78"
const val TCK_0 = "aeca765f744b47faf1fc297bfcaf802fc6c9a8f2e2c9f2d65a7bdc7f42359164"
const val TCK_1 = "df535b90ac99bec8be3a8add45ce77897b1e7cb1906b5cff1097d3cb142fd9d0"
const val TCN_1 = "f4350a4a33e30f2f568898fbe4c4cf34"
const val TCN_2 = "135eeaa6482b8852fea3544edf6eabf0"
const val TCN_3 = "d713ce68cf4127bcebde6874c4991e4b"
const val MESSAGE = "test message"
const val REPORT_MESSAGE = "fd8deb9d91a13e144ca5b0ce14e289532e040fe0bf922c6e3dadb1e4e2333c78df535b90ac99" +
"bec8be3a8add45ce77897b1e7cb1906b5cff1097d3cb142fd9d002000a00000c73796d70746f6d2064617461"
const val REPORT_SIGN = "31078ec5367b67a8c793b740626d81ba904789363137b5a313419c0f50b180d8226ecc984bf073ff" +
"89cbd9c88fea06bda1f0f368b0e7e88bbe68f15574482904"
}

View File

@ -0,0 +1,56 @@
package it.unisannio.assd.tkn.key
import cafe.cryptography.ed25519.Ed25519PrivateKey
import it.unisannio.assd.tkn.TestConst.MESSAGE
import it.unisannio.assd.tkn.TestConst.PRIVATE_KEY_STRING_HEX
import it.unisannio.assd.tkn.TestConst.PUBLIC_KEY_STRING_HEX
import it.unisannio.assd.tkn.TestConst.TCK_0
import it.unisannio.assd.tkn.toHexByteArray
import org.amshove.kluent.`should be equal to`
import org.junit.Test
class ReportAuthorizationKeyTest {
@Test
fun createFromByteArray() {
val keyBytes = PRIVATE_KEY_STRING_HEX.toHexByteArray()
val rak = ReportAuthorizationKey.createFromByteArray(keyBytes)
rak.toHexString() `should be equal to` PRIVATE_KEY_STRING_HEX
}
@Test
fun createFromHexString() {
val rak = ReportAuthorizationKey.createFromHexString(PRIVATE_KEY_STRING_HEX)
rak.toHexString() `should be equal to` PRIVATE_KEY_STRING_HEX
}
@Test
fun deriveVerificationKey() {
val rak = ReportAuthorizationKey.createFromHexString(PRIVATE_KEY_STRING_HEX)
rak.deriveVerificationKey()
.toHexString() `should be equal to` PUBLIC_KEY_STRING_HEX
}
@Test
fun deriveTck0() {
val rak = ReportAuthorizationKey.createFromHexString(PRIVATE_KEY_STRING_HEX)
rak.baseTemporaryContactKey()
.toHexString() `should be equal to` TCK_0
}
@Test
fun sign() {
val rak = ReportAuthorizationKey.createFromHexString(PRIVATE_KEY_STRING_HEX)
val rvk = rak.deriveVerificationKey()
val privateKey = Ed25519PrivateKey.fromByteArray(PRIVATE_KEY_STRING_HEX.toHexByteArray())
val publicKey = privateKey.derivePublic()
val message = MESSAGE.toByteArray()
rak.sign(message, rvk) `should be equal to` privateKey.expand().sign(message, publicKey).toByteArray()
}
}

View File

@ -0,0 +1,74 @@
package it.unisannio.assd.tkn.key
import it.unisannio.assd.tkn.TestConst
import it.unisannio.assd.tkn.toHexByteArray
import org.amshove.kluent.`should be equal to`
import org.junit.Test
class ReportVerificationKeyTest {
@Test
fun createFromByteArray() {
val rvk = ReportVerificationKey
.createFromByteArray(TestConst.PUBLIC_KEY_STRING_HEX.toHexByteArray())
println(rvk.toHexString())
rvk.toHexString() `should be equal to` TestConst.PUBLIC_KEY_STRING_HEX
}
@Test
fun createFromAuthorizationKey() {
val rak = ReportAuthorizationKey
.createFromHexString(TestConst.PRIVATE_KEY_STRING_HEX)
ReportVerificationKey
.createFromAuthorizationKey(rak)
.toHexString() `should be equal to` TestConst.PUBLIC_KEY_STRING_HEX
}
@Test
fun createFromHexString() {
val rvk = ReportVerificationKey
.createFromHexString(TestConst.PUBLIC_KEY_STRING_HEX)
rvk.toHexString() `should be equal to` TestConst.PUBLIC_KEY_STRING_HEX
}
@Test
fun verify() {
val rvk = ReportVerificationKey
.createFromHexString(TestConst.PUBLIC_KEY_STRING_HEX)
rvk.verify(
TestConst.REPORT_MESSAGE.toHexByteArray(),
TestConst.REPORT_SIGN.toHexByteArray()
) `should be equal to` true
}
@Test
fun verifyFalse() {
val rvk = ReportVerificationKey
.createFromHexString(TestConst.PUBLIC_KEY_STRING_HEX)
rvk.verify(
"not original message".toByteArray(),
TestConst.REPORT_SIGN.toHexByteArray()
) `should be equal to` false
}
@Test
fun contactNumbersBetween() {
val rak = ReportAuthorizationKey
.createFromHexString(TestConst.PRIVATE_KEY_STRING_HEX)
val rvk = ReportVerificationKey
.createFromHexString(TestConst.PUBLIC_KEY_STRING_HEX)
rvk.contactNumbersBetween(
rak.baseTemporaryContactKey(),
1,
4
).map {
it.toHexString()
} `should be equal to` listOf(TestConst.TCN_1, TestConst.TCN_2, TestConst.TCN_3)
}
}

View File

@ -0,0 +1,55 @@
package it.unisannio.assd.tkn.key
import it.unisannio.assd.tkn.TestConst
import it.unisannio.assd.tkn.toHexByteArray
import org.amshove.kluent.`should be equal to`
import org.junit.Test
class TemporaryContactKeyTest {
@Test
fun createFromByteArray() {
val tck0 = TemporaryContactKey
.createFromByteArray(TestConst.TCK_0.toHexByteArray(), 0)
tck0.toHexString() `should be equal to` TestConst.TCK_0
}
@Test
fun createFromHexString() {
val tck0 = TemporaryContactKey
.createFromHexString(TestConst.TCK_0, 0)
tck0.toHexString() `should be equal to` TestConst.TCK_0
}
@Test
fun nextTemporaryKey() {
val tck0 = TemporaryContactKey
.createFromHexString(TestConst.TCK_0, 0)
val rvk = ReportVerificationKey
.createFromHexString(TestConst.PUBLIC_KEY_STRING_HEX)
tck0.nextTemporaryContactKey(rvk)
.toHexString() `should be equal to` TestConst.TCK_1
}
@Test
fun derivateTemporaryContactNumber() {
val tck1 = TemporaryContactKey
.createFromHexString(TestConst.TCK_1, 1)
tck1.deriveTemporaryContactNumber()
.toHexString() `should be equal to` TestConst.TCN_1
}
@Test
fun generateReport() {
val tck1 = TemporaryContactKey
.createFromHexString(TestConst.TCK_1, 1)
val rvk = ReportVerificationKey
.createFromHexString(TestConst.PUBLIC_KEY_STRING_HEX)
tck1.generateReport(rvk, 10, "symptom data")
.toHexString() `should be equal to` TestConst.REPORT_MESSAGE
}
}

View File

@ -0,0 +1,41 @@
package it.unisannio.assd.tkn.report
import it.unisannio.assd.tkn.TestConst
import it.unisannio.assd.tkn.key.ReportAuthorizationKey
import it.unisannio.assd.tkn.toHexByteArray
import it.unisannio.assd.tkn.toHexString
import org.amshove.kluent.`should be equal to`
import org.junit.Test
class ReportTest {
@Test
fun readReportFromByteArray() {
val report = Report.readReportFromByteArray(
TestConst.REPORT_MESSAGE.toHexByteArray()
)
report.toHexString() `should be equal to` TestConst.REPORT_MESSAGE
}
@Test
fun signWith() {
val report = Report.readReportFromByteArray(
TestConst.REPORT_MESSAGE.toHexByteArray()
)
val rak = ReportAuthorizationKey
.createFromHexString(TestConst.PRIVATE_KEY_STRING_HEX)
report.signWith(rak).sign
.toHexString() `should be equal to` TestConst.REPORT_SIGN
}
@Test
fun getVerificationKey() {
val report = Report.readReportFromByteArray(
TestConst.REPORT_MESSAGE.toHexByteArray()
)
report.getVerificationKey()
.toHexString() `should be equal to` TestConst.PUBLIC_KEY_STRING_HEX
}
}

View File

@ -0,0 +1,26 @@
package it.unisannio.assd.tkn.report
import it.unisannio.assd.tkn.TestConst
import it.unisannio.assd.tkn.toHexByteArray
import org.amshove.kluent.`should be equal to`
import org.junit.Test
class SignedReportTest {
@Test
fun readFromByteArray() {
val report = TestConst.REPORT_MESSAGE + TestConst.REPORT_SIGN
SignedReport.readFromByteArray(
report.toHexByteArray()
).toHexString() `should be equal to` report
}
@Test
fun verify() {
val report = TestConst.REPORT_MESSAGE + TestConst.REPORT_SIGN
SignedReport.readFromByteArray(
report.toHexByteArray()
).verify() `should be equal to` true
}
}