| ... | ... | @@ -256,6 +256,7 @@ pub fn Ecdsa(comptime C: type, comptime H: type) type { |
| 256 | 256 | const r = try Curve.scalar.Scalar.fromBytes(sig.r, .big); |
| 257 | 257 | const s = try Curve.scalar.Scalar.fromBytes(sig.s, .big); |
| 258 | 258 | if (r.isZero() or s.isZero()) return error.IdentityElement; |
| 259 | try public_key.p.rejectIdentity(); |
| 259 | 260 | |
| 260 | 261 | return Verifier{ |
| 261 | 262 | .h = Hash.init(.{}), |
| ... | ... | @@ -287,13 +288,19 @@ pub fn Ecdsa(comptime C: type, comptime H: type) type { |
| 287 | 288 | const s_inv = self.s.invert(); |
| 288 | 289 | const v1 = z.mul(s_inv).toBytes(.little); |
| 289 | 290 | const v2 = self.r.mul(s_inv).toBytes(.little); |
| 290 | | const v1g = try Curve.basePoint.mulPublic(v1, .little); |
| 291 | | const v2pk = try self.public_key.p.mulPublic(v2, .little); |
| 292 | | const vxs = v1g.add(v2pk).affineCoordinates().x.toBytes(.big); |
| 293 | | const vr = reduceToScalar(Curve.Fe.encoded_length, vxs); |
| 294 | | if (!self.r.equivalent(vr)) { |
| 291 | const v = Curve.mulDoubleBasePublic(Curve.basePoint, v1, self.public_key.p, v2, .little) catch |
| 295 | 292 | return error.SignatureVerificationFailed; |
| 293 | |
| 294 | const Fe = Curve.Fe; |
| 295 | const n = Curve.scalar.field_order; |
| 296 | comptime std.debug.assert(n < Fe.field_order and Fe.field_order < 2 * n); |
| 297 | const r = Fe.fromBytes(self.r.toBytes(.little), .little) catch unreachable; |
| 298 | if (v.x.equivalent(r.mul(v.z))) return; |
| 299 | if (r.toInt() < Fe.field_order - n) { |
| 300 | const n_fe = comptime Fe.fromInt(n) catch unreachable; |
| 301 | if (v.x.equivalent(r.add(n_fe).mul(v.z))) return; |
| 296 | 302 | } |
| 303 | return error.SignatureVerificationFailed; |
| 297 | 304 | } |
| 298 | 305 | |
| 299 | 306 | /// Verify that the signature is valid for the entire message. |