Skip to content

Commit

Permalink
Merge pull request #2 from radixdlt/fix/BigInteger
Browse files Browse the repository at this point in the history
When converting BigInteger to byte array, we always retain private ke…
  • Loading branch information
raf-rdx authored Jan 10, 2023
2 parents effc1b7 + 801c56a commit 982d278
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/main/kotlin/com/radixdlt/model/ECKeyPair.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,24 @@ class PrivateKey(val key: BigInteger, val curveType: EllipticCurveType) {
return true
}

/**
* Since BigInteger by design does not retain leading zeros, for any bytearray with leading zero elements,
* they will be cut off when converting to BigInteger.
* When accessing key and converting to byteArray we need to use that method which ensures that key
* will be always 32 bytes and leading zeros will be added in front if missing
*/
fun keyByteArray(): ByteArray {
return key.toBytesPadded(PRIVATE_KEY_SIZE)
}

fun toHexString(): String {
return key.toBytesPadded(PRIVATE_KEY_SIZE).toHexString()
return keyByteArray().toHexString()
}

override fun hashCode(): Int {
var result = key.hashCode()
result = 31 * result + curveType.hashCode()
return result
}
}

Expand All @@ -48,6 +64,12 @@ class PublicKey(val key: BigInteger, val curveType: EllipticCurveType) {

return true
}

override fun hashCode(): Int {
var result = key.hashCode()
result = 31 * result + curveType.hashCode()
return result
}
}

data class ECKeyPair(val privateKey: PrivateKey, val publicKey: PublicKey)
Expand Down
54 changes: 54 additions & 0 deletions src/test/kotlin/com/radixdlt/slip10/PrivateKeyTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.radixdlt.slip10

import com.radixdlt.crypto.ec.EllipticCurveType
import com.radixdlt.model.PRIVATE_KEY_SIZE
import com.radixdlt.model.PrivateKey
import org.junit.jupiter.api.Test
import kotlin.random.Random
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class PrivateKeyTest {

@Test
fun `when leading byte is zero, verify key byte array has correct size and zero is not cut off`() {
val bytes = ByteArray(PRIVATE_KEY_SIZE)
Random.nextBytes(bytes, 1, bytes.size)
val privateKey = PrivateKey(bytes, EllipticCurveType.Ed25519)
assertEquals(privateKey.keyByteArray().size, PRIVATE_KEY_SIZE)
}

@Test
fun `when only last byte is not zero, verify key byte array has correct size and number is retained`() {
val bytes = ByteArray(PRIVATE_KEY_SIZE)
Random.nextBytes(bytes, bytes.size-1, bytes.size)
val privateKey = PrivateKey(bytes, EllipticCurveType.Ed25519)
assertEquals(privateKey.keyByteArray().size, PRIVATE_KEY_SIZE)
}

@Test
fun `when byte array is 33 bytes but has leading 0, verify zero is cut off and private key is exactly 32 bytes`() {
val bytes = ByteArray(PRIVATE_KEY_SIZE+1)
Random.nextBytes(bytes, 1, bytes.size)
val privateKey = PrivateKey(bytes, EllipticCurveType.Ed25519)
assertEquals(privateKey.keyByteArray().size, PRIVATE_KEY_SIZE)
}

@Test
fun `when byte array is 32 bytes but has only 1, verify the same is returned from keyByteArray`() {
val byteArray =
byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
val privateKey = PrivateKey(byteArray, EllipticCurveType.Ed25519)
assertTrue(privateKey.keyByteArray().contentEquals(byteArray))
}

@Test
fun `when byte array is only one byte (1), verify that output is also one but has 32 bytes length`() {
val byteArray =
byteArrayOf(1)
val outputByteArray =
byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
val privateKey = PrivateKey(byteArray, EllipticCurveType.Ed25519)
assertTrue(privateKey.keyByteArray().contentEquals(outputByteArray))
}
}

0 comments on commit 982d278

Please sign in to comment.