@matter/general 0.16.0-alpha.0-20251111-11cc8c3bd → 0.16.0-alpha.0-20251112-dba1973d5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/codec/DerCodec.d.ts +6 -1
- package/dist/cjs/codec/DerCodec.d.ts.map +1 -1
- package/dist/cjs/codec/DerCodec.js +13 -2
- package/dist/cjs/codec/DerCodec.js.map +1 -1
- package/dist/cjs/crypto/Crypto.d.ts +3 -3
- package/dist/cjs/crypto/Crypto.d.ts.map +1 -1
- package/dist/cjs/crypto/Crypto.js.map +1 -1
- package/dist/cjs/crypto/CryptoError.d.ts +5 -0
- package/dist/cjs/crypto/CryptoError.d.ts.map +1 -1
- package/dist/cjs/crypto/CryptoError.js +4 -1
- package/dist/cjs/crypto/CryptoError.js.map +1 -1
- package/dist/cjs/crypto/EcdsaSignature.d.ts +43 -0
- package/dist/cjs/crypto/EcdsaSignature.d.ts.map +1 -0
- package/dist/cjs/crypto/EcdsaSignature.js +74 -0
- package/dist/cjs/crypto/EcdsaSignature.js.map +6 -0
- package/dist/cjs/crypto/NodeJsStyleCrypto.d.ts +4 -3
- package/dist/cjs/crypto/NodeJsStyleCrypto.d.ts.map +1 -1
- package/dist/cjs/crypto/NodeJsStyleCrypto.js +14 -11
- package/dist/cjs/crypto/NodeJsStyleCrypto.js.map +1 -1
- package/dist/cjs/crypto/StandardCrypto.d.ts +4 -3
- package/dist/cjs/crypto/StandardCrypto.d.ts.map +1 -1
- package/dist/cjs/crypto/StandardCrypto.js +5 -21
- package/dist/cjs/crypto/StandardCrypto.js.map +1 -1
- package/dist/cjs/crypto/index.d.ts +1 -0
- package/dist/cjs/crypto/index.d.ts.map +1 -1
- package/dist/cjs/crypto/index.js +1 -0
- package/dist/cjs/crypto/index.js.map +1 -1
- package/dist/esm/codec/DerCodec.d.ts +6 -1
- package/dist/esm/codec/DerCodec.d.ts.map +1 -1
- package/dist/esm/codec/DerCodec.js +13 -2
- package/dist/esm/codec/DerCodec.js.map +1 -1
- package/dist/esm/crypto/Crypto.d.ts +3 -3
- package/dist/esm/crypto/Crypto.d.ts.map +1 -1
- package/dist/esm/crypto/Crypto.js.map +1 -1
- package/dist/esm/crypto/CryptoError.d.ts +5 -0
- package/dist/esm/crypto/CryptoError.d.ts.map +1 -1
- package/dist/esm/crypto/CryptoError.js +4 -1
- package/dist/esm/crypto/CryptoError.js.map +1 -1
- package/dist/esm/crypto/EcdsaSignature.d.ts +43 -0
- package/dist/esm/crypto/EcdsaSignature.d.ts.map +1 -0
- package/dist/esm/crypto/EcdsaSignature.js +54 -0
- package/dist/esm/crypto/EcdsaSignature.js.map +6 -0
- package/dist/esm/crypto/NodeJsStyleCrypto.d.ts +4 -3
- package/dist/esm/crypto/NodeJsStyleCrypto.d.ts.map +1 -1
- package/dist/esm/crypto/NodeJsStyleCrypto.js +14 -11
- package/dist/esm/crypto/NodeJsStyleCrypto.js.map +1 -1
- package/dist/esm/crypto/StandardCrypto.d.ts +4 -3
- package/dist/esm/crypto/StandardCrypto.d.ts.map +1 -1
- package/dist/esm/crypto/StandardCrypto.js +5 -21
- package/dist/esm/crypto/StandardCrypto.js.map +1 -1
- package/dist/esm/crypto/index.d.ts +1 -0
- package/dist/esm/crypto/index.d.ts.map +1 -1
- package/dist/esm/crypto/index.js +1 -0
- package/dist/esm/crypto/index.js.map +1 -1
- package/package.json +2 -2
- package/src/codec/DerCodec.ts +19 -3
- package/src/crypto/Crypto.ts +3 -12
- package/src/crypto/CryptoError.ts +5 -0
- package/src/crypto/EcdsaSignature.ts +83 -0
- package/src/crypto/NodeJsStyleCrypto.ts +14 -12
- package/src/crypto/StandardCrypto.ts +6 -28
- package/src/crypto/index.ts +1 -0
package/src/crypto/Crypto.ts
CHANGED
|
@@ -13,6 +13,7 @@ import * as mod from "@noble/curves/abstract/modular.js";
|
|
|
13
13
|
import { p256 } from "@noble/curves/nist.js";
|
|
14
14
|
import * as utils from "@noble/curves/utils.js";
|
|
15
15
|
import { Entropy } from "../util/Entropy.js";
|
|
16
|
+
import { EcdsaSignature } from "./EcdsaSignature.js";
|
|
16
17
|
import type { PrivateKey, PublicKey } from "./Key.js";
|
|
17
18
|
|
|
18
19
|
export const ec = {
|
|
@@ -27,7 +28,6 @@ export const CRYPTO_EC_CURVE = "prime256v1";
|
|
|
27
28
|
export const CRYPTO_EC_KEY_BYTES = 32;
|
|
28
29
|
export const CRYPTO_AUTH_TAG_LENGTH = 16;
|
|
29
30
|
export const CRYPTO_SYMMETRIC_KEY_LENGTH = 16;
|
|
30
|
-
export type CryptoDsaEncoding = "ieee-p1363" | "der";
|
|
31
31
|
|
|
32
32
|
const logger = Logger.get("Crypto");
|
|
33
33
|
|
|
@@ -83,21 +83,12 @@ export abstract class Crypto extends Entropy {
|
|
|
83
83
|
/**
|
|
84
84
|
* Create an ECDSA signature.
|
|
85
85
|
*/
|
|
86
|
-
abstract signEcdsa(
|
|
87
|
-
privateKey: JsonWebKey,
|
|
88
|
-
data: Bytes | Bytes[],
|
|
89
|
-
dsaEncoding?: CryptoDsaEncoding,
|
|
90
|
-
): MaybePromise<Bytes>;
|
|
86
|
+
abstract signEcdsa(privateKey: JsonWebKey, data: Bytes | Bytes[]): MaybePromise<EcdsaSignature>;
|
|
91
87
|
|
|
92
88
|
/**
|
|
93
89
|
* Authenticate an ECDSA signature.
|
|
94
90
|
*/
|
|
95
|
-
abstract verifyEcdsa(
|
|
96
|
-
publicKey: JsonWebKey,
|
|
97
|
-
data: Bytes,
|
|
98
|
-
signature: Bytes,
|
|
99
|
-
dsaEncoding?: CryptoDsaEncoding,
|
|
100
|
-
): MaybePromise<void>;
|
|
91
|
+
abstract verifyEcdsa(publicKey: JsonWebKey, data: Bytes, signature: EcdsaSignature): MaybePromise<void>;
|
|
101
92
|
|
|
102
93
|
/**
|
|
103
94
|
* Create a general-purpose EC key.
|
|
@@ -30,3 +30,8 @@ export class CryptoDecryptError extends CryptoError {}
|
|
|
30
30
|
* Thrown when cryptographic key parameters are invalid.
|
|
31
31
|
*/
|
|
32
32
|
export class KeyInputError extends CryptoInputError {}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Thrown when verification fails because of an invalid signature format.
|
|
36
|
+
*/
|
|
37
|
+
export class SignatureEncodingError extends CryptoVerifyError {}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { DerCodec, DerError, DerRawUint } from "#codec/DerCodec.js";
|
|
8
|
+
import { Bytes } from "#util/Bytes.js";
|
|
9
|
+
import { SignatureEncodingError } from "./CryptoError.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* An ECDSA signature.
|
|
13
|
+
*
|
|
14
|
+
* Input and output may be IEEE-P1363 or DER encoded. Matter helpfully mixes and matches so we validate input to ensure
|
|
15
|
+
* the correct encoding is specified. Extraction to bytes must explicitly use {@link bytes} or {@link der} to specify
|
|
16
|
+
* the desired format.
|
|
17
|
+
*
|
|
18
|
+
* Currently we only support 256-bit curves.
|
|
19
|
+
*/
|
|
20
|
+
export class EcdsaSignature {
|
|
21
|
+
#bytes: Bytes;
|
|
22
|
+
|
|
23
|
+
constructor(bytes: Bytes, encoding = "ieee-p1363") {
|
|
24
|
+
if (encoding === "der") {
|
|
25
|
+
try {
|
|
26
|
+
const decoded = DerCodec.decode(bytes);
|
|
27
|
+
|
|
28
|
+
const r = DerCodec.decodeBigUint(decoded?._elements?.[0], 32);
|
|
29
|
+
const s = DerCodec.decodeBigUint(decoded?._elements?.[1], 32);
|
|
30
|
+
|
|
31
|
+
this.#bytes = Bytes.concat(r, s);
|
|
32
|
+
} catch (cause) {
|
|
33
|
+
DerError.accept(cause);
|
|
34
|
+
|
|
35
|
+
throw new SignatureEncodingError("Could not decode DER signature", { cause });
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
// Change this if/when we support more curves
|
|
39
|
+
if (bytes.byteLength !== 64) {
|
|
40
|
+
throw new SignatureEncodingError("Invalid IEEE P1364 signature length");
|
|
41
|
+
}
|
|
42
|
+
this.#bytes = bytes;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Access signature in IEEE P1363 format.
|
|
48
|
+
*/
|
|
49
|
+
get bytes() {
|
|
50
|
+
return this.#bytes;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Access signature in DER format.
|
|
55
|
+
*/
|
|
56
|
+
get der() {
|
|
57
|
+
const bytes = Bytes.of(this.#bytes);
|
|
58
|
+
const bytesPerComponent = bytes.length / 2;
|
|
59
|
+
|
|
60
|
+
return DerCodec.encode({
|
|
61
|
+
r: DerRawUint(bytes.slice(0, bytesPerComponent)),
|
|
62
|
+
s: DerRawUint(bytes.slice(bytesPerComponent)),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export namespace EcdsaSignature {
|
|
68
|
+
/**
|
|
69
|
+
* IEEE P1363 encoding.
|
|
70
|
+
*
|
|
71
|
+
* This is a simple concatenation of the raw R and S elements
|
|
72
|
+
*/
|
|
73
|
+
export const IEEE_P1363 = "ieee-p1363";
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* DER encoding.
|
|
77
|
+
*
|
|
78
|
+
* This encodes R and S elements in a sequence of separate integers.
|
|
79
|
+
*/
|
|
80
|
+
export const DER = "der";
|
|
81
|
+
|
|
82
|
+
export type Encoding = typeof IEEE_P1363 | typeof DER;
|
|
83
|
+
}
|
|
@@ -17,9 +17,9 @@ import {
|
|
|
17
17
|
CRYPTO_ENCRYPT_ALGORITHM,
|
|
18
18
|
CRYPTO_HASH_ALGORITHM,
|
|
19
19
|
CRYPTO_SYMMETRIC_KEY_LENGTH,
|
|
20
|
-
CryptoDsaEncoding,
|
|
21
20
|
} from "./Crypto.js";
|
|
22
21
|
import { CryptoDecryptError, CryptoVerifyError } from "./CryptoError.js";
|
|
22
|
+
import { EcdsaSignature } from "./EcdsaSignature.js";
|
|
23
23
|
import { PrivateKey, PublicKey } from "./Key.js";
|
|
24
24
|
|
|
25
25
|
// Note that this is a type-only import, not a runtime dependency.
|
|
@@ -179,24 +179,26 @@ export class NodeJsStyleCrypto extends Crypto {
|
|
|
179
179
|
return Bytes.of(hmac.digest());
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
signEcdsa(privateKey: JsonWebKey, data: Bytes | Bytes[]
|
|
182
|
+
signEcdsa(privateKey: JsonWebKey, data: Bytes | Bytes[]) {
|
|
183
183
|
const signer = this.#crypto.createSign(CRYPTO_HASH_ALGORITHM);
|
|
184
184
|
if (Array.isArray(data)) {
|
|
185
185
|
data.forEach(chunk => signer.update(Bytes.of(chunk)));
|
|
186
186
|
} else {
|
|
187
187
|
signer.update(Bytes.of(data));
|
|
188
188
|
}
|
|
189
|
-
return
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
189
|
+
return new EcdsaSignature(
|
|
190
|
+
Bytes.of(
|
|
191
|
+
signer.sign({
|
|
192
|
+
key: privateKey as any,
|
|
193
|
+
format: "jwk",
|
|
194
|
+
type: "pkcs8",
|
|
195
|
+
dsaEncoding: "ieee-p1363",
|
|
196
|
+
}),
|
|
197
|
+
),
|
|
196
198
|
);
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
verifyEcdsa(publicKey: JsonWebKey, data: Bytes, signature:
|
|
201
|
+
verifyEcdsa(publicKey: JsonWebKey, data: Bytes, signature: EcdsaSignature) {
|
|
200
202
|
const verifier = this.#crypto.createVerify(CRYPTO_HASH_ALGORITHM);
|
|
201
203
|
verifier.update(Bytes.of(data));
|
|
202
204
|
const success = verifier.verify(
|
|
@@ -204,9 +206,9 @@ export class NodeJsStyleCrypto extends Crypto {
|
|
|
204
206
|
key: publicKey as any,
|
|
205
207
|
format: "jwk",
|
|
206
208
|
type: "spki",
|
|
207
|
-
dsaEncoding,
|
|
209
|
+
dsaEncoding: "ieee-p1363",
|
|
208
210
|
},
|
|
209
|
-
Bytes.of(signature),
|
|
211
|
+
Bytes.of(signature.bytes),
|
|
210
212
|
);
|
|
211
213
|
if (!success) throw new CryptoVerifyError("Signature verification failed");
|
|
212
214
|
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* SPDX-License-Identifier: Apache-2.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { DerBigUint, DerCodec, DerError } from "#codec/DerCodec.js";
|
|
9
8
|
import { Environment } from "#environment/Environment.js";
|
|
10
9
|
import { ImplementationError, NotImplementedError } from "#MatterError.js";
|
|
11
10
|
import { Bytes } from "#util/Bytes.js";
|
|
@@ -13,8 +12,9 @@ import { Entropy } from "#util/Entropy.js";
|
|
|
13
12
|
import { MaybePromise } from "#util/Promises.js";
|
|
14
13
|
import { describeList } from "#util/String.js";
|
|
15
14
|
import { Ccm } from "./aes/Ccm.js";
|
|
16
|
-
import { Crypto, CRYPTO_SYMMETRIC_KEY_LENGTH
|
|
15
|
+
import { Crypto, CRYPTO_SYMMETRIC_KEY_LENGTH } from "./Crypto.js";
|
|
17
16
|
import { CryptoVerifyError, KeyInputError } from "./CryptoError.js";
|
|
17
|
+
import { EcdsaSignature } from "./EcdsaSignature.js";
|
|
18
18
|
import { CurveType, Key, KeyType, PrivateKey, PublicKey } from "./Key.js";
|
|
19
19
|
import { WebCrypto } from "./WebCrypto.js";
|
|
20
20
|
|
|
@@ -146,7 +146,7 @@ export class StandardCrypto extends Crypto {
|
|
|
146
146
|
);
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
async signEcdsa(key: JsonWebKey, data: Bytes | Bytes[]
|
|
149
|
+
async signEcdsa(key: JsonWebKey, data: Bytes | Bytes[]) {
|
|
150
150
|
if (Array.isArray(data)) {
|
|
151
151
|
data = Bytes.concat(...data);
|
|
152
152
|
}
|
|
@@ -167,40 +167,18 @@ export class StandardCrypto extends Crypto {
|
|
|
167
167
|
|
|
168
168
|
const ieeeP1363 = Bytes.of(await this.#subtle.sign(SIGNATURE_ALGORITHM, subtleKey, Bytes.exclusive(data)));
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const bytesPerComponent = ieeeP1363.byteLength / 2;
|
|
173
|
-
|
|
174
|
-
return DerCodec.encode({
|
|
175
|
-
r: DerBigUint(ieeeP1363.slice(0, bytesPerComponent)),
|
|
176
|
-
s: DerBigUint(ieeeP1363.slice(bytesPerComponent)),
|
|
177
|
-
});
|
|
170
|
+
return new EcdsaSignature(ieeeP1363);
|
|
178
171
|
}
|
|
179
172
|
|
|
180
|
-
async verifyEcdsa(key: JsonWebKey, data: Bytes, signature:
|
|
173
|
+
async verifyEcdsa(key: JsonWebKey, data: Bytes, signature: EcdsaSignature) {
|
|
181
174
|
const { crv, kty, x, y } = key;
|
|
182
175
|
key = { crv, kty, x, y };
|
|
183
176
|
const subtleKey = await this.importKey("jwk", key, SIGNATURE_ALGORITHM, false, ["verify"]);
|
|
184
177
|
|
|
185
|
-
if (dsaEncoding === "der") {
|
|
186
|
-
try {
|
|
187
|
-
const decoded = DerCodec.decode(signature);
|
|
188
|
-
|
|
189
|
-
const r = DerCodec.decodeBigUint(decoded?._elements?.[0], 32);
|
|
190
|
-
const s = DerCodec.decodeBigUint(decoded?._elements?.[1], 32);
|
|
191
|
-
|
|
192
|
-
signature = Bytes.concat(r, s);
|
|
193
|
-
} catch (cause) {
|
|
194
|
-
DerError.accept(cause);
|
|
195
|
-
|
|
196
|
-
throw new CryptoVerifyError("Invalid DER signature", { cause });
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
178
|
const verified = await this.#subtle.verify(
|
|
201
179
|
SIGNATURE_ALGORITHM,
|
|
202
180
|
subtleKey,
|
|
203
|
-
Bytes.exclusive(signature),
|
|
181
|
+
Bytes.exclusive(signature.bytes),
|
|
204
182
|
Bytes.exclusive(data),
|
|
205
183
|
);
|
|
206
184
|
|
package/src/crypto/index.ts
CHANGED