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

LukaJCB / ts-mls / 20624162621

31 Dec 2025 05:43PM UTC coverage: 96.185% (-0.2%) from 96.34%
20624162621

push

github

web-flow
Remove noble/curves dependency for Ed25519 (#187)

1260 of 1407 branches covered (89.55%)

Branch coverage included in aggregate %.

35 of 35 new or added lines in 1 file covered. (100.0%)

15 existing lines in 1 file now uncovered.

7211 of 7400 relevant lines covered (97.45%)

44157.04 hits per line

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

76.56
/src/crypto/implementation/default/makeNobleSignatureImpl.ts
1
import { DependencyError } from "../../../mlsError.js"
1✔
2
import { SignatureAlgorithm, Signature } from "../../signature.js"
3
import { toBufferSource } from "../../../util/byteArray.js"
1✔
4

5
function rawEd25519ToPKCS8(rawKey: Uint8Array): Uint8Array {
179✔
6
  const oid = new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x70])
179✔
7

8
  const innerOctetString = new Uint8Array([0x04, 0x20, ...rawKey])
179✔
9

10
  const privateKeyField = new Uint8Array([0x04, 0x22, ...innerOctetString])
179✔
11
  const algorithmSeq = new Uint8Array([0x30, 0x05, ...oid])
179✔
12

13
  const version = new Uint8Array([0x02, 0x01, 0x00])
179✔
14

15
  const content = new Uint8Array([...version, ...algorithmSeq, ...privateKeyField])
179✔
16

17
  return new Uint8Array([0x30, content.length, ...content])
179✔
18
}
179✔
19

20
export async function makeNobleSignatureImpl(alg: SignatureAlgorithm): Promise<Signature> {
1,477✔
21
  switch (alg) {
1,477✔
22
    case "Ed25519": {
1,477✔
23
      const subtle = globalThis.crypto?.subtle
675✔
24

25
      if (subtle !== undefined) {
675✔
26
        return {
675✔
27
          async sign(signKey, message) {
675✔
28
            const keyData = signKey.length === 32 ? rawEd25519ToPKCS8(signKey) : signKey
6,420✔
29
            const key = await subtle.importKey("pkcs8", toBufferSource(keyData), "Ed25519", false, ["sign"])
6,420✔
30
            const sig = await subtle.sign("Ed25519", key, toBufferSource(message))
6,420✔
31
            return new Uint8Array(sig)
6,420✔
32
          },
6,420✔
33
          async verify(publicKey, message, signature) {
675✔
34
            const key = await subtle.importKey("raw", toBufferSource(publicKey), "Ed25519", false, ["verify"])
15,406✔
35
            return subtle.verify("Ed25519", key, toBufferSource(signature), toBufferSource(message))
15,406✔
36
          },
15,406✔
37
          async keygen() {
675✔
38
            const keyPair = await subtle.generateKey("Ed25519", true, ["sign", "verify"])
1,213✔
39
            const publicKeyBuffer = await subtle.exportKey("raw", keyPair.publicKey)
1,213✔
40
            const privateKeyBuffer = await subtle.exportKey("pkcs8", keyPair.privateKey)
1,213✔
41

42
            const publicKey = new Uint8Array(publicKeyBuffer)
1,213✔
43
            const signKey = new Uint8Array(privateKeyBuffer)
1,213✔
44

45
            return { signKey, publicKey }
1,213✔
46
          },
1,213✔
47
        }
675✔
48
      }
675!
49

UNCOV
50
      try {
×
UNCOV
51
        const { ed25519 } = await import("@noble/curves/ed25519.js")
×
UNCOV
52
        return {
×
UNCOV
53
          async sign(signKey, message) {
×
UNCOV
54
            return ed25519.sign(message, signKey)
×
UNCOV
55
          },
×
UNCOV
56
          async verify(publicKey, message, signature) {
×
UNCOV
57
            return ed25519.verify(signature, message, publicKey)
×
UNCOV
58
          },
×
UNCOV
59
          async keygen() {
×
UNCOV
60
            const signKey = ed25519.utils.randomSecretKey()
×
UNCOV
61
            return { signKey, publicKey: ed25519.getPublicKey(signKey) }
×
UNCOV
62
          },
×
UNCOV
63
        }
×
UNCOV
64
      } catch (err) {
×
65
        throw new DependencyError(
×
66
          "Optional dependency '@noble/curves' is not installed. Please install it to use this feature.",
×
67
        )
×
68
      }
×
69
    }
675✔
70

71
    case "Ed448":
1,477✔
72
      try {
237✔
73
        const { ed448 } = await import("@noble/curves/ed448.js")
237✔
74
        return {
237✔
75
          async sign(signKey, message) {
237✔
76
            return ed448.sign(message, signKey)
1,400✔
77
          },
1,400✔
78
          async verify(publicKey, message, signature) {
237✔
79
            return ed448.verify(signature, message, publicKey)
2,881✔
80
          },
2,881✔
81
          async keygen() {
237✔
82
            const signKey = ed448.utils.randomSecretKey()
232✔
83
            return { signKey, publicKey: ed448.getPublicKey(signKey) }
232✔
84
          },
232✔
85
        }
237✔
86
      } catch (err) {
237!
87
        throw new DependencyError(
×
88
          "Optional dependency '@noble/curves' is not installed. Please install it to use this feature.",
×
89
        )
×
90
      }
×
91

92
    case "P256":
1,477✔
93
      try {
117✔
94
        const { p256 } = await import("@noble/curves/nist.js")
117✔
95
        return {
117✔
96
          async sign(signKey, message) {
117✔
97
            return p256.sign(message, signKey, { prehash: true, format: "der", lowS: false })
696✔
98
          },
696✔
99
          async verify(publicKey, message, signature) {
117✔
100
            return p256.verify(signature, message, publicKey, { prehash: true, format: "der", lowS: false })
1,437✔
101
          },
1,437✔
102
          async keygen() {
117✔
103
            const signKey = p256.utils.randomSecretKey()
115✔
104
            return { signKey, publicKey: p256.getPublicKey(signKey) }
115✔
105
          },
115✔
106
        }
117✔
107
      } catch (err) {
117!
108
        throw new DependencyError(
×
109
          "Optional dependency '@noble/curves' is not installed. Please install it to use this feature.",
×
110
        )
×
111
      }
×
112
    case "P384":
1,477✔
113
      try {
117✔
114
        const { p384 } = await import("@noble/curves/nist.js")
117✔
115
        return {
117✔
116
          async sign(signKey, message) {
117✔
117
            return p384.sign(message, signKey, { prehash: true, format: "der", lowS: false })
696✔
118
          },
696✔
119
          async verify(publicKey, message, signature) {
117✔
120
            return p384.verify(signature, message, publicKey, { prehash: true, format: "der", lowS: false })
1,437✔
121
          },
1,437✔
122
          async keygen() {
117✔
123
            const signKey = p384.utils.randomSecretKey()
115✔
124
            return { signKey, publicKey: p384.getPublicKey(signKey) }
115✔
125
          },
115✔
126
        }
117✔
127
      } catch (err) {
117!
128
        throw new DependencyError(
×
129
          "Optional dependency '@noble/curves' is not installed. Please install it to use this feature.",
×
130
        )
×
131
      }
×
132
    case "P521":
1,477✔
133
      try {
117✔
134
        const { p521 } = await import("@noble/curves/nist.js")
117✔
135
        return {
117✔
136
          async sign(signKey, message) {
117✔
137
            return p521.sign(message, signKey, { prehash: true, format: "der", lowS: false })
696✔
138
          },
696✔
139
          async verify(publicKey, message, signature) {
117✔
140
            return p521.verify(signature, message, publicKey, { prehash: true, format: "der", lowS: false })
1,437✔
141
          },
1,437✔
142
          async keygen() {
117✔
143
            const signKey = p521.utils.randomSecretKey()
115✔
144
            return { signKey, publicKey: p521.getPublicKey(signKey) }
115✔
145
          },
115✔
146
        }
117✔
147
      } catch (err) {
117!
148
        throw new DependencyError(
×
149
          "Optional dependency '@noble/curves' is not installed. Please install it to use this feature.",
×
150
        )
×
151
      }
×
152
    case "ML-DSA-87":
1,477✔
153
      try {
214✔
154
        const { ml_dsa87 } = await import("@noble/post-quantum/ml-dsa.js")
214✔
155
        return {
214✔
156
          async sign(signKey, message) {
214✔
157
            return ml_dsa87.sign(message, signKey)
2,444✔
158
          },
2,444✔
159
          async verify(publicKey, message, signature) {
214✔
160
            return ml_dsa87.verify(signature, message, publicKey)
3,694✔
161
          },
3,694✔
162
          async keygen() {
214✔
163
            const keys = ml_dsa87.keygen(crypto.getRandomValues(new Uint8Array(32)))
464✔
164
            return { signKey: keys.secretKey, publicKey: keys.publicKey }
464✔
165
          },
464✔
166
        }
214✔
167
      } catch (err) {
214!
168
        throw new DependencyError(
×
169
          "Optional dependency '@noble/post-quantum' is not installed. Please install it to use this feature.",
×
170
        )
×
171
      }
×
172
  }
1,477✔
173
}
1,477✔
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

© 2026 Coveralls, Inc