Skip to content

Commit 9944ec9

Browse files
committed
Allow non-canonical S values in Signatures moving errors to access-time (#5013).
1 parent 4eada38 commit 9944ec9

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

src.ts/crypto/signature.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,30 @@ export class Signature {
8080
/**
8181
* The ``s`` value for a signature.
8282
*/
83-
get s(): string { return this.#s; }
83+
get s(): string {
84+
assertArgument(parseInt(this.#s.substring(0, 3)) < 8, "non-canonical s; use ._s", "s", this.#s);
85+
return this.#s;
86+
}
8487
set s(_value: BytesLike) {
8588
assertArgument(dataLength(_value) === 32, "invalid s", "value", _value);
86-
const value = hexlify(_value);
87-
assertArgument(parseInt(value.substring(0, 3)) < 8, "non-canonical s", "value", value);
88-
this.#s = value;
89+
this.#s = hexlify(_value);
90+
}
91+
92+
/**
93+
* Return the s value, unchecked for EIP-2 compliance.
94+
*
95+
* This should generally not be used and is for situations where
96+
* a non-canonical S value might be relevant, such as Frontier blocks
97+
* that were mined prior to EIP-2 or invalid Authorization List
98+
* signatures.
99+
*/
100+
get _s(): string { return this.#s; }
101+
102+
/**
103+
* Returns true if the Signature is valid for [[link-eip-2]] signatures.
104+
*/
105+
isValid(): boolean {
106+
return (parseInt(this.#s.substring(0, 3)) < 8);
89107
}
90108

91109
/**
@@ -167,14 +185,14 @@ export class Signature {
167185
}
168186

169187
[Symbol.for('nodejs.util.inspect.custom')](): string {
170-
return `Signature { r: "${ this.r }", s: "${ this.s }", yParity: ${ this.yParity }, networkV: ${ this.networkV } }`;
188+
return `Signature { r: "${ this.r }", s: "${ this._s }"${ this.isValid() ? "": ', valid: "false"'}, yParity: ${ this.yParity }, networkV: ${ this.networkV } }`;
171189
}
172190

173191
/**
174192
* Returns a new identical [[Signature]].
175193
*/
176194
clone(): Signature {
177-
const clone = new Signature(_guard, this.r, this.s, this.v);
195+
const clone = new Signature(_guard, this.r, this._s, this.v);
178196
if (this.networkV) { clone.#networkV = this.networkV; }
179197
return clone;
180198
}
@@ -187,7 +205,7 @@ export class Signature {
187205
return {
188206
_type: "signature",
189207
networkV: ((networkV != null) ? networkV.toString(): null),
190-
r: this.r, s: this.s, v: this.v,
208+
r: this.r, s: this._s, v: this.v,
191209
};
192210
}
193211

@@ -293,10 +311,9 @@ export class Signature {
293311

294312
if (bytes.length === 65) {
295313
const r = hexlify(bytes.slice(0, 32));
296-
const s = bytes.slice(32, 64);
297-
assertError((s[0] & 0x80) === 0, "non-canonical s");
314+
const s = hexlify(bytes.slice(32, 64));
298315
const v = Signature.getNormalizedV(bytes[64]);
299-
return new Signature(_guard, r, hexlify(s), v);
316+
return new Signature(_guard, r, s, v);
300317
}
301318

302319
assertError(false, "invalid raw signature length");
@@ -322,7 +339,6 @@ export class Signature {
322339

323340
assertError(false, "missing s");
324341
})(sig.s, sig.yParityAndS);
325-
assertError((getBytes(s)[0] & 0x80) == 0, "non-canonical s");
326342

327343
// Get v; by any means necessary (we check consistency below)
328344
const { networkV, v } = (function(_v?: BigNumberish, yParityAndS?: string, yParity?: Numeric): { networkV?: bigint, v: 27 | 28 } {
@@ -360,4 +376,3 @@ export class Signature {
360376
return result;
361377
}
362378
}
363-

0 commit comments

Comments
 (0)