@atproto/xrpc-server 0.4.0 → 0.4.2
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/CHANGELOG.md +16 -0
- package/dist/index.js +37 -15
- package/dist/index.js.map +2 -2
- package/package.json +5 -5
- package/src/auth.ts +1 -1
- package/src/server.ts +3 -5
- package/src/util.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atproto/xrpc-server
|
|
2
2
|
|
|
3
|
+
## 0.4.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies []:
|
|
8
|
+
- @atproto/lexicon@0.3.1
|
|
9
|
+
|
|
10
|
+
## 0.4.1
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- [#1839](https://github.com/bluesky-social/atproto/pull/1839) [`e1b5f253`](https://github.com/bluesky-social/atproto/commit/e1b5f2537a5ba4d8b951a741269b604856028ae5) Thanks [@dholms](https://github.com/dholms)! - Prevent signature malleability through DER-encoded signatures
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [[`e1b5f253`](https://github.com/bluesky-social/atproto/commit/e1b5f2537a5ba4d8b951a741269b604856028ae5)]:
|
|
17
|
+
- @atproto/crypto@0.3.0
|
|
18
|
+
|
|
3
19
|
## 0.4.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -43596,13 +43596,13 @@ var ensureValidAtUri = (uri2) => {
|
|
|
43596
43596
|
throw new Error("ATURI requires at least method and authority sections");
|
|
43597
43597
|
}
|
|
43598
43598
|
try {
|
|
43599
|
-
|
|
43600
|
-
} catch {
|
|
43601
|
-
try {
|
|
43599
|
+
if (parts[2].startsWith("did:")) {
|
|
43602
43600
|
ensureValidDid(parts[2]);
|
|
43603
|
-
}
|
|
43604
|
-
|
|
43601
|
+
} else {
|
|
43602
|
+
ensureValidHandle(parts[2]);
|
|
43605
43603
|
}
|
|
43604
|
+
} catch {
|
|
43605
|
+
throw new Error("ATURI authority must be a valid handle or DID");
|
|
43606
43606
|
}
|
|
43607
43607
|
if (parts.length >= 4) {
|
|
43608
43608
|
if (parts[3].length == 0) {
|
|
@@ -44938,7 +44938,7 @@ function datetime(path, value) {
|
|
|
44938
44938
|
} catch {
|
|
44939
44939
|
return {
|
|
44940
44940
|
success: false,
|
|
44941
|
-
error: new ValidationError(`${path} must be an
|
|
44941
|
+
error: new ValidationError(`${path} must be an valid atproto datetime (both RFC-3339 and ISO-8601)`)
|
|
44942
44942
|
};
|
|
44943
44943
|
}
|
|
44944
44944
|
return { success: true, value };
|
|
@@ -51925,11 +51925,23 @@ var verifyDidSig = async (did2, data, sig, opts) => {
|
|
|
51925
51925
|
return verifySig(keyBytes, data, sig, opts);
|
|
51926
51926
|
};
|
|
51927
51927
|
var verifySig = async (publicKey, data, sig, opts) => {
|
|
51928
|
+
const allowMalleable = opts?.allowMalleableSig ?? false;
|
|
51928
51929
|
const msgHash = await sha2562(data);
|
|
51930
|
+
if (!allowMalleable && !isCompactFormat(sig)) {
|
|
51931
|
+
return false;
|
|
51932
|
+
}
|
|
51929
51933
|
return p256.verify(sig, msgHash, publicKey, {
|
|
51930
|
-
lowS:
|
|
51934
|
+
lowS: !allowMalleable
|
|
51931
51935
|
});
|
|
51932
51936
|
};
|
|
51937
|
+
var isCompactFormat = (sig) => {
|
|
51938
|
+
try {
|
|
51939
|
+
const parsed = p256.Signature.fromCompact(sig);
|
|
51940
|
+
return equals3(parsed.toCompactRawBytes(), sig);
|
|
51941
|
+
} catch {
|
|
51942
|
+
return false;
|
|
51943
|
+
}
|
|
51944
|
+
};
|
|
51933
51945
|
|
|
51934
51946
|
// ../crypto/src/p256/plugin.ts
|
|
51935
51947
|
var p256Plugin = {
|
|
@@ -51948,11 +51960,23 @@ var verifyDidSig2 = async (did2, data, sig, opts) => {
|
|
|
51948
51960
|
return verifySig2(keyBytes, data, sig, opts);
|
|
51949
51961
|
};
|
|
51950
51962
|
var verifySig2 = async (publicKey, data, sig, opts) => {
|
|
51963
|
+
const allowMalleable = opts?.allowMalleableSig ?? false;
|
|
51951
51964
|
const msgHash = await sha2562(data);
|
|
51965
|
+
if (!allowMalleable && !isCompactFormat2(sig)) {
|
|
51966
|
+
return false;
|
|
51967
|
+
}
|
|
51952
51968
|
return secp256k1.verify(sig, msgHash, publicKey, {
|
|
51953
|
-
lowS:
|
|
51969
|
+
lowS: !allowMalleable
|
|
51954
51970
|
});
|
|
51955
51971
|
};
|
|
51972
|
+
var isCompactFormat2 = (sig) => {
|
|
51973
|
+
try {
|
|
51974
|
+
const parsed = secp256k1.Signature.fromCompact(sig);
|
|
51975
|
+
return equals3(parsed.toCompactRawBytes(), sig);
|
|
51976
|
+
} catch {
|
|
51977
|
+
return false;
|
|
51978
|
+
}
|
|
51979
|
+
};
|
|
51956
51980
|
|
|
51957
51981
|
// ../crypto/src/secp256k1/plugin.ts
|
|
51958
51982
|
var secp256k1Plugin = {
|
|
@@ -52051,7 +52075,7 @@ var verifyJwt = async (jwtStr, ownDid, getSigningKey) => {
|
|
|
52051
52075
|
const sigBytes = fromString2(sig, "base64url");
|
|
52052
52076
|
const verifySignatureWithKey = (key) => {
|
|
52053
52077
|
return verifySignature(key, msgBytes, sigBytes, {
|
|
52054
|
-
|
|
52078
|
+
allowMalleableSig: true
|
|
52055
52079
|
});
|
|
52056
52080
|
};
|
|
52057
52081
|
const signingKey = await getSigningKey(payload.iss, false);
|
|
@@ -52500,7 +52524,7 @@ function decodeQueryParam(type, value) {
|
|
|
52500
52524
|
if (type === "float") {
|
|
52501
52525
|
return Number(String(value));
|
|
52502
52526
|
} else if (type === "integer") {
|
|
52503
|
-
return
|
|
52527
|
+
return parseInt(String(value), 10) || 0;
|
|
52504
52528
|
} else if (type === "boolean") {
|
|
52505
52529
|
return value === "true";
|
|
52506
52530
|
}
|
|
@@ -52899,11 +52923,9 @@ var Server = class {
|
|
|
52899
52923
|
req,
|
|
52900
52924
|
res
|
|
52901
52925
|
};
|
|
52902
|
-
|
|
52903
|
-
|
|
52904
|
-
|
|
52905
|
-
return next(result);
|
|
52906
|
-
}
|
|
52926
|
+
const result = await consumeRateLimit(reqCtx);
|
|
52927
|
+
if (result instanceof RateLimitExceededError) {
|
|
52928
|
+
return next(result);
|
|
52907
52929
|
}
|
|
52908
52930
|
const outputUnvalidated = await handler(reqCtx);
|
|
52909
52931
|
if (isHandlerError(outputUnvalidated)) {
|