• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

input-output-hk / atala-prism-building-blocks / 8722405814

17 Apr 2024 01:02PM UTC coverage: 31.005% (-0.6%) from 31.633%
8722405814

Pull #966

patlo-iog
chore: resolve conflict

Signed-off-by: Pat Losoponkul <pat.losoponkul@iohk.io>
Pull Request #966: feat: key management for Ed25519 and X25519

109 of 386 new or added lines in 22 files covered. (28.24%)

386 existing lines in 101 files now uncovered.

4478 of 14443 relevant lines covered (31.0%)

0.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.6
/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/KmpApollo.scala
1
package io.iohk.atala.shared.crypto
2

3
import io.iohk.atala.prism.apollo.derivation
4
import io.iohk.atala.prism.apollo.derivation.MnemonicHelper
5
import io.iohk.atala.prism.apollo.secp256k1.Secp256k1Lib
6
import io.iohk.atala.prism.apollo.securerandom.SecureRandom
7
import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey
8
import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey
9
import io.iohk.atala.prism.apollo.utils.KMMEdKeyPair
10
import io.iohk.atala.prism.apollo.utils.KMMEdPrivateKey
11
import io.iohk.atala.prism.apollo.utils.KMMEdPublicKey
12
import io.iohk.atala.prism.apollo.utils.KMMX25519KeyPair
13
import io.iohk.atala.prism.apollo.utils.KMMX25519PrivateKey
14
import io.iohk.atala.prism.apollo.utils.KMMX25519PublicKey
15
import zio.*
16

17
import scala.jdk.CollectionConverters.*
18
import scala.util.{Try, Success, Failure}
19

20
final case class KmpSecp256k1PublicKey(publicKey: KMMECSecp256k1PublicKey) extends Secp256k1PublicKey {
21

1✔
22
  override def getECPoint: ECPoint = {
1✔
23
    val point = publicKey.getCurvePoint()
1✔
24
    ECPoint(point.getX(), point.getY())
25
  }
26

1✔
27
  override def getEncoded: Array[Byte] = publicKey.getCompressed()
28

1✔
29
  override def getEncodedCompressed: Array[Byte] = getEncoded
30

×
31
  override def getEncodedUncompressed: Array[Byte] =
×
32
    KmpSecp256k1KeyOps.secpLib.uncompressPublicKey(getEncodedCompressed)
33

1✔
34
  override def verify(data: Array[Byte], signature: Array[Byte]): Try[Unit] =
×
35
    Try(publicKey.verify(signature, data))
1✔
36
      .flatMap(isValid => if (isValid) Success(()) else Failure(Exception("The signature verification does not match")))
37
}
38

39
final case class KmpSecp256k1PrivateKey(privateKey: KMMECSecp256k1PrivateKey) extends Secp256k1PrivateKey {
1✔
40
  override def sign(data: Array[Byte]): Array[Byte] = privateKey.sign(data)
41

1✔
42
  override def toPublicKey: Secp256k1PublicKey = KmpSecp256k1PublicKey(privateKey.getPublicKey())
43

1✔
44
  override def getEncoded: Array[Byte] = privateKey.getEncoded()
45
}
46

47
object KmpSecp256k1KeyOps extends Secp256k1KeyOps {
1✔
48
  private[crypto] val secpLib: Secp256k1Lib = Secp256k1Lib()
1✔
49
  private[crypto] val secureRandom: SecureRandom = SecureRandom()
50

1✔
51
  override def publicKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PublicKey] =
1✔
52
    Try {
1✔
53
      val publicKey = KMMECSecp256k1PublicKey.Companion.secp256k1FromBytes(bytes)
1✔
54
      val point = publicKey.getCurvePoint()
1✔
55
      val isOnCurve = KMMECSecp256k1PublicKey.Companion.isPointOnSecp256k1Curve(point)
1✔
56
      if (isOnCurve) KmpSecp256k1PublicKey(publicKey)
×
57
      else throw new Exception("The public key is not on the secp256k1 curve")
58
    }
59

1✔
60
  override def publicKeyFromCoordinate(x: Array[Byte], y: Array[Byte]): Try[Secp256k1PublicKey] =
1✔
61
    Try {
1✔
62
      val pk = KMMECSecp256k1PublicKey.Companion.secp256k1FromByteCoordinates(x, y)
1✔
63
      val point = pk.getCurvePoint()
1✔
64
      val isOnCurve = KMMECSecp256k1PublicKey.Companion.isPointOnSecp256k1Curve(point)
1✔
NEW
65
      if (isOnCurve) KmpSecp256k1PublicKey(pk)
×
66
      else throw Exception("The point is not on the secp256k1 curve")
67
    }
68

1✔
UNCOV
69
  override def privateKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PrivateKey] =
×
70
    Try(KMMECSecp256k1PrivateKey.Companion.secp256k1FromByteArray(bytes)).map(KmpSecp256k1PrivateKey(_))
71

1✔
72
  override def generateKeyPair: Secp256k1KeyPair = {
1✔
73
    val randBytes = secureRandom.nextBytes(32)
1✔
74
    val privateKey = KMMECSecp256k1PrivateKey(randBytes)
1✔
75
    val publicKey = privateKey.getPublicKey
76
    Secp256k1KeyPair(
77
      KmpSecp256k1PublicKey(publicKey),
78
      KmpSecp256k1PrivateKey(privateKey)
79
    )
80
  }
81

1✔
82
  def randomBip32Seed: UIO[(Array[Byte], Seq[String])] =
1✔
83
    ZIO.attemptBlocking {
1✔
84
      val words = MnemonicHelper.Companion.createRandomMnemonics()
1✔
85
      val seed = MnemonicHelper.Companion.createSeed(words, "")
1✔
86
      seed -> words.asScala.toList
87
    }.orDie
88

1✔
89
  def deriveKeyPair(seed: Array[Byte])(path: DerivationPath*): UIO[Secp256k1KeyPair] =
1✔
90
    ZIO.attemptBlocking {
91
      val pathStr = path
1✔
92
        .foldLeft(derivation.DerivationPath.empty()) { case (path, p) =>
93
          p match {
1✔
94
            case DerivationPath.Hardened(i) => path.derive(derivation.DerivationAxis.hardened(i))
×
95
            case DerivationPath.Normal(i)   => path.derive(derivation.DerivationAxis.normal(i))
96
          }
97
        }
1✔
98
        .toString()
1✔
99
      val hdKey = derivation.HDKey(seed, 0, 0).derive(pathStr)
1✔
100
      val privateKey = hdKey.getKMMSecp256k1PrivateKey()
1✔
101
      val publicKey = privateKey.getPublicKey()
102

103
      Secp256k1KeyPair(
104
        KmpSecp256k1PublicKey(publicKey),
105
        KmpSecp256k1PrivateKey(privateKey)
106
      )
107
    }.orDie
108

109
}
110

NEW
111
final case class KmpEd25519PublicKey(publicKey: KMMEdPublicKey) extends Ed25519PublicKey {
×
NEW
112
  override def getEncoded: Array[Byte] = publicKey.getRaw()
×
NEW
113
  override def verify(data: Array[Byte], signature: Array[Byte]): Try[Unit] =
×
NEW
114
    Try(publicKey.verify(data, signature))
×
115
      .flatMap(isValid => if (isValid) Success(()) else Failure(Exception("The signature verification does not match")))
116
}
117

NEW
118
final case class KmpEd25519PrivateKey(privateKey: KMMEdPrivateKey) extends Ed25519PrivateKey {
×
NEW
119
  override def getEncoded: Array[Byte] = privateKey.getRaw()
×
NEW
120
  override def sign(data: Array[Byte]): Array[Byte] = privateKey.sign(data)
×
121
  override def toPublicKey: Ed25519PublicKey = KmpEd25519PublicKey(privateKey.publicKey())
122
}
123

124
object KmpEd25519KeyOps extends Ed25519KeyOps {
NEW
125

×
NEW
126
  override def publicKeyFromEncoded(bytes: Array[Byte]): Try[Ed25519PublicKey] =
×
NEW
127
    Try {
×
NEW
128
      if bytes.length != 32 then throw Exception("Invalid public key length")
×
129
      KmpEd25519PublicKey(KMMEdPublicKey(bytes))
130
    }
NEW
131

×
NEW
132
  override def privateKeyFromEncoded(bytes: Array[Byte]): Try[Ed25519PrivateKey] =
×
NEW
133
    Try {
×
NEW
134
      if bytes.length != 32 then throw Exception("Invalid private key length")
×
135
      KmpEd25519PrivateKey(KMMEdPrivateKey(bytes))
136
    }
NEW
137

×
NEW
138
  override def generateKeyPair: Ed25519KeyPair = {
×
139
    val keyPair = KMMEdKeyPair.Companion.generateKeyPair()
NEW
140
    Ed25519KeyPair(
×
NEW
141
      KmpEd25519PublicKey(keyPair.getPublicKey()),
×
142
      KmpEd25519PrivateKey(keyPair.getPrivateKey())
143
    )
144
  }
145

146
}
147

NEW
148
final case class KmpX25519PublicKey(publicKey: KMMX25519PublicKey) extends X25519PublicKey {
×
149
  override def getEncoded: Array[Byte] = publicKey.getRaw()
150
}
151

NEW
152
final case class KmpX25519PrivateKey(privateKey: KMMX25519PrivateKey) extends X25519PrivateKey {
×
NEW
153
  override def getEncoded: Array[Byte] = privateKey.getRaw()
×
154
  override def toPublicKey: X25519PublicKey = KmpX25519PublicKey(privateKey.publicKey())
155
}
156

NEW
157
object KmpX25519KeyOps extends X25519KeyOps {
×
NEW
158
  override def publicKeyFromEncoded(bytes: Array[Byte]): Try[X25519PublicKey] =
×
NEW
159
    Try {
×
NEW
160
      if bytes.length != 32 then throw Exception("Invalid public key length")
×
161
      KmpX25519PublicKey(KMMX25519PublicKey(bytes))
162
    }
NEW
163

×
NEW
164
  override def privateKeyFromEncoded(bytes: Array[Byte]): Try[X25519PrivateKey] =
×
NEW
165
    Try {
×
NEW
166
      if bytes.length != 32 then throw Exception("Invalid private key length")
×
167
      KmpX25519PrivateKey(KMMX25519PrivateKey(bytes))
168
    }
NEW
169

×
NEW
170
  override def generateKeyPair: X25519KeyPair = {
×
171
    val keyPair = KMMX25519KeyPair.Companion.generateKeyPair()
NEW
172
    X25519KeyPair(
×
NEW
173
      KmpX25519PublicKey(keyPair.getPublicKey()),
×
174
      KmpX25519PrivateKey(keyPair.getPrivateKey())
175
    )
176
  }
177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc